AdnRecordLoader.java revision d720945f2be5ea5fe0faf67e67d9ea0e184eba67
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony.uicc;
18
19import java.util.ArrayList;
20
21import android.os.AsyncResult;
22import android.os.Handler;
23import android.os.Looper;
24import android.os.Message;
25import android.telephony.Rlog;
26
27public class AdnRecordLoader extends Handler {
28    final static String LOG_TAG = "RIL_AdnRecordLoader";
29
30    //***** Instance Variables
31
32    private IccFileHandler mFh;
33    int ef;
34    int extensionEF;
35    int pendingExtLoads;
36    Message userResponse;
37    String pin2;
38
39    // For "load one"
40    int recordNumber;
41
42    // for "load all"
43    ArrayList<AdnRecord> adns; // only valid after EVENT_ADN_LOAD_ALL_DONE
44
45    // Either an AdnRecord or a reference to adns depending
46    // if this is a load one or load all operation
47    Object result;
48
49    //***** Event Constants
50
51    static final int EVENT_ADN_LOAD_DONE = 1;
52    static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
53    static final int EVENT_ADN_LOAD_ALL_DONE = 3;
54    static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
55    static final int EVENT_UPDATE_RECORD_DONE = 5;
56
57    //***** Constructor
58
59    AdnRecordLoader(IccFileHandler fh) {
60        // The telephony unit-test cases may create AdnRecords
61        // in secondary threads
62        super(Looper.getMainLooper());
63        mFh = fh;
64    }
65
66    /**
67     * Resulting AdnRecord is placed in response.obj.result
68     * or response.obj.exception is set
69     */
70    public void
71    loadFromEF(int ef, int extensionEF, int recordNumber,
72                Message response) {
73        this.ef = ef;
74        this.extensionEF = extensionEF;
75        this.recordNumber = recordNumber;
76        this.userResponse = response;
77
78        mFh.loadEFLinearFixed(
79                    ef, recordNumber,
80                    obtainMessage(EVENT_ADN_LOAD_DONE));
81
82    }
83
84
85    /**
86     * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
87     * or response.obj.exception is set
88     */
89    public void
90    loadAllFromEF(int ef, int extensionEF,
91                Message response) {
92        this.ef = ef;
93        this.extensionEF = extensionEF;
94        this.userResponse = response;
95
96        mFh.loadEFLinearFixedAll(
97                    ef,
98                    obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
99
100    }
101
102    /**
103     * Write adn to a EF SIM record
104     * It will get the record size of EF record and compose hex adn array
105     * then write the hex array to EF record
106     *
107     * @param adn is set with alphaTag and phone number
108     * @param ef EF fileid
109     * @param extensionEF extension EF fileid
110     * @param recordNumber 1-based record index
111     * @param pin2 for CHV2 operations, must be null if pin2 is not needed
112     * @param response will be sent to its handler when completed
113     */
114    public void
115    updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
116            String pin2, Message response) {
117        this.ef = ef;
118        this.extensionEF = extensionEF;
119        this.recordNumber = recordNumber;
120        this.userResponse = response;
121        this.pin2 = pin2;
122
123        mFh.getEFLinearRecordSize( ef,
124            obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
125    }
126
127    //***** Overridden from Handler
128
129    public void
130    handleMessage(Message msg) {
131        AsyncResult ar;
132        byte data[];
133        AdnRecord adn;
134
135        try {
136            switch (msg.what) {
137                case EVENT_EF_LINEAR_RECORD_SIZE_DONE:
138                    ar = (AsyncResult)(msg.obj);
139                    adn = (AdnRecord)(ar.userObj);
140
141                    if (ar.exception != null) {
142                        throw new RuntimeException("get EF record size failed",
143                                ar.exception);
144                    }
145
146                    int[] recordSize = (int[])ar.result;
147                    // recordSize is int[3] array
148                    // int[0]  is the record length
149                    // int[1]  is the total length of the EF file
150                    // int[2]  is the number of records in the EF file
151                    // So int[0] * int[2] = int[1]
152                   if (recordSize.length != 3 || recordNumber > recordSize[2]) {
153                        throw new RuntimeException("get wrong EF record size format",
154                                ar.exception);
155                    }
156
157                    data = adn.buildAdnString(recordSize[0]);
158
159                    if(data == null) {
160                        throw new RuntimeException("wrong ADN format",
161                                ar.exception);
162                    }
163
164                    mFh.updateEFLinearFixed(ef, recordNumber,
165                            data, pin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
166
167                    pendingExtLoads = 1;
168
169                    break;
170                case EVENT_UPDATE_RECORD_DONE:
171                    ar = (AsyncResult)(msg.obj);
172                    if (ar.exception != null) {
173                        throw new RuntimeException("update EF adn record failed",
174                                ar.exception);
175                    }
176                    pendingExtLoads = 0;
177                    result = null;
178                    break;
179                case EVENT_ADN_LOAD_DONE:
180                    ar = (AsyncResult)(msg.obj);
181                    data = (byte[])(ar.result);
182
183                    if (ar.exception != null) {
184                        throw new RuntimeException("load failed", ar.exception);
185                    }
186
187                    if (false) {
188                        Rlog.d(LOG_TAG,"ADN EF: 0x"
189                            + Integer.toHexString(ef)
190                            + ":" + recordNumber
191                            + "\n" + IccUtils.bytesToHexString(data));
192                    }
193
194                    adn = new AdnRecord(ef, recordNumber, data);
195                    result = adn;
196
197                    if (adn.hasExtendedRecord()) {
198                        // If we have a valid value in the ext record field,
199                        // we're not done yet: we need to read the corresponding
200                        // ext record and append it
201
202                        pendingExtLoads = 1;
203
204                        mFh.loadEFLinearFixed(
205                            extensionEF, adn.extRecord,
206                            obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
207                    }
208                break;
209
210                case EVENT_EXT_RECORD_LOAD_DONE:
211                    ar = (AsyncResult)(msg.obj);
212                    data = (byte[])(ar.result);
213                    adn = (AdnRecord)(ar.userObj);
214
215                    if (ar.exception != null) {
216                        throw new RuntimeException("load failed", ar.exception);
217                    }
218
219                    Rlog.d(LOG_TAG,"ADN extension EF: 0x"
220                        + Integer.toHexString(extensionEF)
221                        + ":" + adn.extRecord
222                        + "\n" + IccUtils.bytesToHexString(data));
223
224                    adn.appendExtRecord(data);
225
226                    pendingExtLoads--;
227                    // result should have been set in
228                    // EVENT_ADN_LOAD_DONE or EVENT_ADN_LOAD_ALL_DONE
229                break;
230
231                case EVENT_ADN_LOAD_ALL_DONE:
232                    ar = (AsyncResult)(msg.obj);
233                    ArrayList<byte[]> datas = (ArrayList<byte[]>)(ar.result);
234
235                    if (ar.exception != null) {
236                        throw new RuntimeException("load failed", ar.exception);
237                    }
238
239                    adns = new ArrayList<AdnRecord>(datas.size());
240                    result = adns;
241                    pendingExtLoads = 0;
242
243                    for(int i = 0, s = datas.size() ; i < s ; i++) {
244                        adn = new AdnRecord(ef, 1 + i, datas.get(i));
245                        adns.add(adn);
246
247                        if (adn.hasExtendedRecord()) {
248                            // If we have a valid value in the ext record field,
249                            // we're not done yet: we need to read the corresponding
250                            // ext record and append it
251
252                            pendingExtLoads++;
253
254                            mFh.loadEFLinearFixed(
255                                extensionEF, adn.extRecord,
256                                obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
257                        }
258                    }
259                break;
260            }
261        } catch (RuntimeException exc) {
262            if (userResponse != null) {
263                AsyncResult.forMessage(userResponse)
264                                .exception = exc;
265                userResponse.sendToTarget();
266                // Loading is all or nothing--either every load succeeds
267                // or we fail the whole thing.
268                userResponse = null;
269            }
270            return;
271        }
272
273        if (userResponse != null && pendingExtLoads == 0) {
274            AsyncResult.forMessage(userResponse).result
275                = result;
276
277            userResponse.sendToTarget();
278            userResponse = null;
279        }
280    }
281
282
283}
284