1 /*
2  * Copyright (C) 2008 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 
17 package com.android.internal.telephony.uicc;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.os.AsyncResult;
21 import android.os.Handler;
22 import android.os.Message;
23 
24 import com.android.internal.telephony.CommandsInterface;
25 
26 import java.util.ArrayList;
27 
28 /**
29  * {@hide}
30  */
31 public abstract class IccFileHandler extends Handler implements IccConstants {
32     private static final boolean VDBG = false;
33 
34     //from TS 11.11 9.1 or elsewhere
35     static protected final int COMMAND_READ_BINARY = 0xb0;
36     static protected final int COMMAND_UPDATE_BINARY = 0xd6;
37     static protected final int COMMAND_READ_RECORD = 0xb2;
38     static protected final int COMMAND_UPDATE_RECORD = 0xdc;
39     static protected final int COMMAND_SEEK = 0xa2;
40     static protected final int COMMAND_GET_RESPONSE = 0xc0;
41 
42     // from TS 11.11 9.2.5
43     static protected final int READ_RECORD_MODE_ABSOLUTE = 4;
44 
45     //***** types of files  TS 11.11 9.3
46     static protected final int EF_TYPE_TRANSPARENT = 0;
47     static protected final int EF_TYPE_LINEAR_FIXED = 1;
48     static protected final int EF_TYPE_CYCLIC = 3;
49 
50     //***** types of files  TS 11.11 9.3
51     static protected final int TYPE_RFU = 0;
52     static protected final int TYPE_MF  = 1;
53     static protected final int TYPE_DF  = 2;
54     static protected final int TYPE_EF  = 4;
55 
56     // size of GET_RESPONSE for EF's
57     static protected final int GET_RESPONSE_EF_SIZE_BYTES = 15;
58     static protected final int GET_RESPONSE_EF_IMG_SIZE_BYTES = 10;
59 
60     // Byte order received in response to COMMAND_GET_RESPONSE
61     // Refer TS 51.011 Section 9.2.1
62     static protected final int RESPONSE_DATA_RFU_1 = 0;
63     static protected final int RESPONSE_DATA_RFU_2 = 1;
64 
65     static protected final int RESPONSE_DATA_FILE_SIZE_1 = 2;
66     static protected final int RESPONSE_DATA_FILE_SIZE_2 = 3;
67 
68     static protected final int RESPONSE_DATA_FILE_ID_1 = 4;
69     static protected final int RESPONSE_DATA_FILE_ID_2 = 5;
70     static protected final int RESPONSE_DATA_FILE_TYPE = 6;
71     static protected final int RESPONSE_DATA_RFU_3 = 7;
72     static protected final int RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
73     static protected final int RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
74     static protected final int RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
75     static protected final int RESPONSE_DATA_FILE_STATUS = 11;
76     static protected final int RESPONSE_DATA_LENGTH = 12;
77     static protected final int RESPONSE_DATA_STRUCTURE = 13;
78     static protected final int RESPONSE_DATA_RECORD_LENGTH = 14;
79 
80 
81     //***** Events
82 
83     /** Finished retrieving size of transparent EF; start loading. */
84     static protected final int EVENT_GET_BINARY_SIZE_DONE = 4;
85     /** Finished loading contents of transparent EF; post result. */
86     static protected final int EVENT_READ_BINARY_DONE = 5;
87     /** Finished retrieving size of records for linear-fixed EF; now load. */
88     static protected final int EVENT_GET_RECORD_SIZE_DONE = 6;
89     /** Finished loading single record from a linear-fixed EF; post result. */
90     static protected final int EVENT_READ_RECORD_DONE = 7;
91     /** Finished retrieving record size; post result. */
92     static protected final int EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE = 8;
93     /** Finished retrieving image instance record; post result. */
94     static protected final int EVENT_READ_IMG_DONE = 9;
95     /** Finished retrieving icon data; post result. */
96     static protected final int EVENT_READ_ICON_DONE = 10;
97     /** Finished retrieving size of record for EFimg now. */
98     static protected final int EVENT_GET_RECORD_SIZE_IMG_DONE = 11;
99     /** Finished retriveing record size of transparent file. */
100     protected static final int EVENT_GET_EF_TRANSPARENT_SIZE_DONE = 12;
101 
102      // member variables
103     @UnsupportedAppUsage
104     protected final CommandsInterface mCi;
105     @UnsupportedAppUsage
106     protected final UiccCardApplication mParentApp;
107     @UnsupportedAppUsage
108     protected final String mAid;
109 
110     static class LoadLinearFixedContext {
111 
112         int mEfid;
113         @UnsupportedAppUsage
114         int mRecordNum, mRecordSize, mCountRecords;
115         boolean mLoadAll;
116         String mPath;
117 
118         Message mOnLoaded;
119 
120         @UnsupportedAppUsage
121         ArrayList<byte[]> results;
122 
123         @UnsupportedAppUsage
LoadLinearFixedContext(int efid, int recordNum, Message onLoaded)124         LoadLinearFixedContext(int efid, int recordNum, Message onLoaded) {
125             mEfid = efid;
126             mRecordNum = recordNum;
127             mOnLoaded = onLoaded;
128             mLoadAll = false;
129             mPath = null;
130         }
131 
LoadLinearFixedContext(int efid, int recordNum, String path, Message onLoaded)132         LoadLinearFixedContext(int efid, int recordNum, String path, Message onLoaded) {
133             mEfid = efid;
134             mRecordNum = recordNum;
135             mOnLoaded = onLoaded;
136             mLoadAll = false;
137             mPath = path;
138         }
139 
LoadLinearFixedContext(int efid, String path, Message onLoaded)140         LoadLinearFixedContext(int efid, String path, Message onLoaded) {
141             mEfid = efid;
142             mRecordNum = 1;
143             mLoadAll = true;
144             mOnLoaded = onLoaded;
145             mPath = path;
146         }
147 
LoadLinearFixedContext(int efid, Message onLoaded)148         LoadLinearFixedContext(int efid, Message onLoaded) {
149             mEfid = efid;
150             mRecordNum = 1;
151             mLoadAll = true;
152             mOnLoaded = onLoaded;
153             mPath = null;
154         }
155     }
156 
157     /**
158      * Default constructor
159      */
IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci)160     protected IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
161         mParentApp = app;
162         mAid = aid;
163         mCi = ci;
164     }
165 
dispose()166     public void dispose() {
167     }
168 
169     //***** Public Methods
170 
171     /**
172      * Load a record from a SIM Linear Fixed EF
173      *
174      * @param fileid EF id
175      * @param path Path of the EF on the card
176      * @param recordNum 1-based (not 0-based) record number
177      * @param onLoaded
178      *
179      * ((AsyncResult)(onLoaded.obj)).result is the byte[]
180      *
181      */
182     @UnsupportedAppUsage
loadEFLinearFixed(int fileid, String path, int recordNum, Message onLoaded)183     public void loadEFLinearFixed(int fileid, String path, int recordNum, Message onLoaded) {
184         String efPath = (path == null) ? getEFPath(fileid) : path;
185         Message response
186                 = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
187                         new LoadLinearFixedContext(fileid, recordNum, efPath, onLoaded));
188 
189         mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath,
190                         0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
191     }
192 
193     /**
194      * Load a record from a SIM Linear Fixed EF
195      *
196      * @param fileid EF id
197      * @param recordNum 1-based (not 0-based) record number
198      * @param onLoaded
199      *
200      * ((AsyncResult)(onLoaded.obj)).result is the byte[]
201      *
202      */
203     @UnsupportedAppUsage
loadEFLinearFixed(int fileid, int recordNum, Message onLoaded)204     public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) {
205         loadEFLinearFixed(fileid, getEFPath(fileid), recordNum, onLoaded);
206     }
207 
208     /**
209      * Load a image instance record from a SIM Linear Fixed EF-IMG
210      *
211      * @param recordNum 1-based (not 0-based) record number
212      * @param onLoaded
213      *
214      * ((AsyncResult)(onLoaded.obj)).result is the byte[]
215      *
216      */
loadEFImgLinearFixed(int recordNum, Message onLoaded)217     public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {
218         Message response = obtainMessage(EVENT_GET_RECORD_SIZE_IMG_DONE,
219                 new LoadLinearFixedContext(IccConstants.EF_IMG, recordNum,
220                         onLoaded));
221 
222         mCi.iccIOForApp(COMMAND_GET_RESPONSE, IccConstants.EF_IMG,
223                     getEFPath(IccConstants.EF_IMG), recordNum,
224                     READ_RECORD_MODE_ABSOLUTE, GET_RESPONSE_EF_IMG_SIZE_BYTES,
225                     null, null, mAid, response);
226     }
227 
228     /**
229      * Get record size for a linear fixed EF
230      *
231      * @param fileid EF id
232      * @param path Path of the EF on the card
233      * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]. recordSize[0] is
234      *                 the single record length, recordSize[1] is the total length of the EF file
235      *                 and recordSize[2] is the number of records in the EF file. So recordSize[0]
236      *                 * recordSize[2] = recordSize[1].
237      */
238     @UnsupportedAppUsage
getEFLinearRecordSize(int fileid, String path, Message onLoaded)239     public void getEFLinearRecordSize(int fileid, String path, Message onLoaded) {
240         String efPath = (path == null) ? getEFPath(fileid) : path;
241         Message response
242                 = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE,
243                         new LoadLinearFixedContext(fileid, efPath, onLoaded));
244         mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath,
245                     0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
246     }
247 
248     /**
249      * Get record size for a linear fixed EF
250      *
251      * @param fileid EF id
252      * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]. recordSize[0] is
253      *                 the single record length, recordSize[1] is the total length of the EF file
254      *                 and recordSize[2] is the number of records in the EF file. So recordSize[0]
255      *                 * recordSize[2] = recordSize[1].
256      */
257     @UnsupportedAppUsage
getEFLinearRecordSize(int fileid, Message onLoaded)258     public void getEFLinearRecordSize(int fileid, Message onLoaded) {
259         getEFLinearRecordSize(fileid, getEFPath(fileid), onLoaded);
260     }
261 
262     /**
263      * Get record size for a transparent EF
264      *
265      * @param fileid EF id
266      * @param path Path of the EF on the card
267      * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the size of data int
268      */
getEFTransparentRecordSize(int fileid, String path, Message onLoaded)269     public void getEFTransparentRecordSize(int fileid, String path, Message onLoaded) {
270         String efPath = (path == null) ? getEFPath(fileid) : path;
271         Message response = obtainMessage(EVENT_GET_EF_TRANSPARENT_SIZE_DONE, fileid, 0, onLoaded);
272         mCi.iccIOForApp(
273                 COMMAND_GET_RESPONSE,
274                 fileid,
275                 getEFPath(fileid),
276                 0,
277                 0,
278                 GET_RESPONSE_EF_SIZE_BYTES,
279                 null,
280                 null,
281                 mAid,
282                 response);
283     }
284 
285     /**
286      * Get record size for a transparent EF
287      *
288      * @param fileid EF id
289      * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the size of the data int
290      */
getEFTransparentRecordSize(int fileid, Message onLoaded)291     public void getEFTransparentRecordSize(int fileid, Message onLoaded) {
292         getEFTransparentRecordSize(fileid, getEFPath(fileid), onLoaded);
293     }
294 
295     /**
296      * Load all records from a SIM Linear Fixed EF
297      *
298      * @param fileid EF id
299      * @param path Path of the EF on the card
300      * @param onLoaded
301      *
302      * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
303      */
304     @UnsupportedAppUsage
loadEFLinearFixedAll(int fileid, String path, Message onLoaded)305     public void loadEFLinearFixedAll(int fileid, String path, Message onLoaded) {
306         String efPath = (path == null) ? getEFPath(fileid) : path;
307         Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
308                         new LoadLinearFixedContext(fileid, efPath, onLoaded));
309 
310         mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath,
311                         0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
312     }
313 
314     /**
315      * Load all records from a SIM Linear Fixed EF
316      *
317      * @param fileid EF id
318      * @param onLoaded
319      *
320      * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
321      *
322      */
323     @UnsupportedAppUsage
loadEFLinearFixedAll(int fileid, Message onLoaded)324     public void loadEFLinearFixedAll(int fileid, Message onLoaded) {
325         loadEFLinearFixedAll(fileid, getEFPath(fileid), onLoaded);
326     }
327 
328     /**
329      * Load a SIM Transparent EF
330      *
331      * @param fileid EF id
332      * @param onLoaded
333      *
334      * ((AsyncResult)(onLoaded.obj)).result is the byte[]
335      */
336     @UnsupportedAppUsage
loadEFTransparent(int fileid, Message onLoaded)337     public void loadEFTransparent(int fileid, Message onLoaded) {
338         Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
339                         fileid, 0, onLoaded);
340 
341         mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
342                         0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
343     }
344 
345     /**
346      * Load first @size bytes from SIM Transparent EF
347      *
348      * @param fileid EF id
349      * @param size
350      * @param onLoaded
351      *
352      * ((AsyncResult)(onLoaded.obj)).result is the byte[]
353      *
354      */
loadEFTransparent(int fileid, int size, Message onLoaded)355     public void loadEFTransparent(int fileid, int size, Message onLoaded) {
356         Message response = obtainMessage(EVENT_READ_BINARY_DONE,
357                         fileid, 0, onLoaded);
358 
359         mCi.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
360                         0, 0, size, null, null, mAid, response);
361     }
362 
363     /**
364      * Load a SIM Transparent EF-IMG. Used right after loadEFImgLinearFixed to
365      * retrive STK's icon data.
366      *
367      * @param fileid EF id
368      * @param onLoaded
369      *
370      * ((AsyncResult)(onLoaded.obj)).result is the byte[]
371      *
372      */
loadEFImgTransparent(int fileid, int highOffset, int lowOffset, int length, Message onLoaded)373     public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
374             int length, Message onLoaded) {
375         Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
376                 onLoaded);
377 
378         logd("IccFileHandler: loadEFImgTransparent fileid = " + fileid
379                 + " filePath = " + getEFPath(EF_IMG) + " highOffset = " + highOffset
380                 + " lowOffset = " + lowOffset + " length = " + length);
381 
382         /* Per TS 31.102, for displaying of Icon, under
383          * DF Telecom and DF Graphics , EF instance(s) (4FXX,transparent files)
384          * are present. The possible image file identifiers (EF instance) for
385          * EF img ( 4F20, linear fixed file) are : 4F01 ... 4F05.
386          * It should be MF_SIM + DF_TELECOM + DF_GRAPHICS, same path as EF IMG
387          */
388         mCi.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(EF_IMG),
389                 highOffset, lowOffset, length, null, null, mAid, response);
390     }
391 
392     /**
393      * Update a record in a linear fixed EF
394      * @param fileid EF id
395      * @param path Path of the EF on the card
396      * @param recordNum 1-based (not 0-based) record number
397      * @param data must be exactly as long as the record in the EF
398      * @param pin2 for CHV2 operations, otherwist must be null
399      * @param onComplete onComplete.obj will be an AsyncResult
400      *                   onComplete.obj.userObj will be a IccIoResult on success
401      */
402     @UnsupportedAppUsage
updateEFLinearFixed(int fileid, String path, int recordNum, byte[] data, String pin2, Message onComplete)403     public void updateEFLinearFixed(int fileid, String path, int recordNum, byte[] data,
404             String pin2, Message onComplete) {
405         String efPath = (path == null) ? getEFPath(fileid) : path;
406         mCi.iccIOForApp(COMMAND_UPDATE_RECORD, fileid, efPath,
407                         recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
408                         IccUtils.bytesToHexString(data), pin2, mAid, onComplete);
409     }
410 
411     /**
412      * Update a record in a linear fixed EF
413      * @param fileid EF id
414      * @param recordNum 1-based (not 0-based) record number
415      * @param data must be exactly as long as the record in the EF
416      * @param pin2 for CHV2 operations, otherwist must be null
417      * @param onComplete onComplete.obj will be an AsyncResult
418      *                   onComplete.obj.userObj will be a IccIoResult on success
419      */
420     @UnsupportedAppUsage
updateEFLinearFixed(int fileid, int recordNum, byte[] data, String pin2, Message onComplete)421     public void updateEFLinearFixed(int fileid, int recordNum, byte[] data,
422             String pin2, Message onComplete) {
423         mCi.iccIOForApp(COMMAND_UPDATE_RECORD, fileid, getEFPath(fileid),
424                         recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
425                         IccUtils.bytesToHexString(data), pin2, mAid, onComplete);
426     }
427 
428     /**
429      * Update a transparent EF
430      * @param fileid EF id
431      * @param data must be exactly as long as the EF
432      */
433     @UnsupportedAppUsage
updateEFTransparent(int fileid, byte[] data, Message onComplete)434     public void updateEFTransparent(int fileid, byte[] data, Message onComplete) {
435         mCi.iccIOForApp(COMMAND_UPDATE_BINARY, fileid, getEFPath(fileid),
436                         0, 0, data.length,
437                         IccUtils.bytesToHexString(data), null, mAid, onComplete);
438     }
439 
440 
441     //***** Abstract Methods
442 
443 
444     //***** Private Methods
445 
sendResult(Message response, Object result, Throwable ex)446     private void sendResult(Message response, Object result, Throwable ex) {
447         if (response == null) {
448             return;
449         }
450 
451         AsyncResult.forMessage(response, result, ex);
452 
453         response.sendToTarget();
454     }
455 
processException(Message response, AsyncResult ar)456     private boolean processException(Message response, AsyncResult ar) {
457         IccException iccException;
458         boolean flag = false;
459         IccIoResult result = (IccIoResult) ar.result;
460         if (ar.exception != null) {
461             sendResult(response, null, ar.exception);
462             flag = true;
463         } else {
464             iccException = result.getException();
465             if (iccException != null) {
466                 sendResult(response, null, iccException);
467                 flag = true;
468             }
469         }
470         return flag;
471     }
472 
473     //***** Overridden from Handler
474 
475     @Override
handleMessage(Message msg)476     public void handleMessage(Message msg) {
477         AsyncResult ar;
478         IccIoResult result;
479         Message response = null;
480         String str;
481         LoadLinearFixedContext lc;
482 
483         byte data[];
484         int size;
485         int fileid;
486         int recordSize[];
487         String path = null;
488 
489         try {
490             switch (msg.what) {
491             case EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE:
492                 ar = (AsyncResult)msg.obj;
493                 lc = (LoadLinearFixedContext) ar.userObj;
494                 result = (IccIoResult) ar.result;
495                 response = lc.mOnLoaded;
496 
497                 if (processException(response, (AsyncResult) msg.obj)) {
498                     break;
499                 }
500 
501                 data = result.payload;
502 
503                 if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE] ||
504                     EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
505                     throw new IccFileTypeMismatch();
506                 }
507 
508                 recordSize = new int[3];
509                 recordSize[0] = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
510                 recordSize[1] = getDataFileSize(data);
511                 recordSize[2] = recordSize[1] / recordSize[0];
512 
513                 sendResult(response, recordSize, null);
514                 break;
515 
516             case EVENT_GET_RECORD_SIZE_IMG_DONE:
517             case EVENT_GET_RECORD_SIZE_DONE:
518                 ar = (AsyncResult)msg.obj;
519                 lc = (LoadLinearFixedContext) ar.userObj;
520                 result = (IccIoResult) ar.result;
521                 response = lc.mOnLoaded;
522 
523                 if (processException(response, (AsyncResult) msg.obj)) {
524                     loge("exception caught from EVENT_GET_RECORD_SIZE");
525                     break;
526                 }
527 
528                 data = result.payload;
529                 path = lc.mPath;
530 
531                 if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
532                     throw new IccFileTypeMismatch();
533                 }
534 
535                 if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
536                     throw new IccFileTypeMismatch();
537                 }
538 
539                 lc.mRecordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
540 
541                 size = getDataFileSize(data);
542 
543                 lc.mCountRecords = size / lc.mRecordSize;
544 
545                 if (lc.mLoadAll) {
546                     lc.results = new ArrayList<byte[]>(lc.mCountRecords);
547                 }
548 
549                 if (path == null) {
550                     path = getEFPath(lc.mEfid);
551                 }
552                 mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, path,
553                         lc.mRecordNum,
554                         READ_RECORD_MODE_ABSOLUTE,
555                         lc.mRecordSize, null, null, mAid,
556                         obtainMessage(EVENT_READ_RECORD_DONE, lc));
557                 break;
558             case EVENT_GET_BINARY_SIZE_DONE:
559                 ar = (AsyncResult)msg.obj;
560                 response = (Message) ar.userObj;
561                 result = (IccIoResult) ar.result;
562 
563                 if (processException(response, (AsyncResult) msg.obj)) {
564                     break;
565                 }
566 
567                 data = result.payload;
568 
569                 fileid = msg.arg1;
570 
571                 if (VDBG) {
572                     logd(String.format("Contents of the Select Response for command %x: ", fileid)
573                             + IccUtils.bytesToHexString(data));
574                 }
575 
576                 if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
577                     throw new IccFileTypeMismatch();
578                 }
579 
580                 if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
581                     throw new IccFileTypeMismatch();
582                 }
583 
584                 size = getDataFileSize(data);
585 
586                 mCi.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
587                                 0, 0, size, null, null, mAid,
588                                 obtainMessage(EVENT_READ_BINARY_DONE,
589                                             fileid, 0, response));
590             break;
591 
592             case EVENT_READ_IMG_DONE:
593             case EVENT_READ_RECORD_DONE:
594 
595                 ar = (AsyncResult)msg.obj;
596                 lc = (LoadLinearFixedContext) ar.userObj;
597                 result = (IccIoResult) ar.result;
598                 response = lc.mOnLoaded;
599                 path = lc.mPath;
600 
601                 if (processException(response, (AsyncResult) msg.obj)) {
602                     break;
603                 }
604 
605                 if (!lc.mLoadAll) {
606                     sendResult(response, result.payload, null);
607                 } else {
608                     lc.results.add(result.payload);
609 
610                     lc.mRecordNum++;
611 
612                     if (lc.mRecordNum > lc.mCountRecords) {
613                         sendResult(response, lc.results, null);
614                     } else {
615                         if (path == null) {
616                             path = getEFPath(lc.mEfid);
617                         }
618 
619                         mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, path,
620                                     lc.mRecordNum,
621                                     READ_RECORD_MODE_ABSOLUTE,
622                                     lc.mRecordSize, null, null, mAid,
623                                     obtainMessage(EVENT_READ_RECORD_DONE, lc));
624                     }
625                 }
626 
627             break;
628 
629             case EVENT_READ_BINARY_DONE:
630             case EVENT_READ_ICON_DONE:
631                 ar = (AsyncResult)msg.obj;
632                 response = (Message) ar.userObj;
633                 result = (IccIoResult) ar.result;
634 
635                 if (processException(response, (AsyncResult) msg.obj)) {
636                     break;
637                 }
638 
639                 sendResult(response, result.payload, null);
640             break;
641 
642             case EVENT_GET_EF_TRANSPARENT_SIZE_DONE:
643                 ar = (AsyncResult) msg.obj;
644                 response = (Message) ar.userObj;
645                 result = (IccIoResult) ar.result;
646 
647                 if (processException(response, (AsyncResult) msg.obj)) {
648                     break;
649                 }
650 
651                 data = result.payload;
652 
653                 fileid = msg.arg1;
654 
655                 if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
656                     throw new IccFileTypeMismatch();
657                 }
658 
659                 if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
660                     throw new IccFileTypeMismatch();
661                 }
662 
663                 size = getDataFileSize(data);
664                 sendResult(response, size, null);
665                 break;
666 
667         }} catch (Exception exc) {
668             if (response != null) {
669                 sendResult(response, null, exc);
670             } else {
671                 loge("uncaught exception" + exc);
672             }
673         }
674     }
675 
676     /**
677      * Returns the root path of the EF file.
678      * i.e returns MainFile + DFfile as a string.
679      * Ex: For EF_ADN on a SIM, it will return "3F007F10"
680      * This function handles only EFids that are common to
681      * RUIM, SIM, USIM and other types of Icc cards.
682      *
683      * @param efid of path to retrieve
684      * @return root path of the file.
685      */
getCommonIccEFPath(int efid)686     protected String getCommonIccEFPath(int efid) {
687         switch(efid) {
688         case EF_ADN:
689         case EF_FDN:
690         case EF_MSISDN:
691         case EF_SDN:
692         case EF_EXT1:
693         case EF_EXT2:
694         case EF_EXT3:
695         case EF_PSI:
696             return MF_SIM + DF_TELECOM;
697 
698         case EF_ICCID:
699         case EF_PL:
700             return MF_SIM;
701         case EF_PBR:
702             // we only support global phonebook.
703             return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
704         case EF_IMG:
705             return MF_SIM + DF_TELECOM + DF_GRAPHICS;
706         }
707         return null;
708     }
709 
710     @UnsupportedAppUsage
getEFPath(int efid)711     protected abstract String getEFPath(int efid);
logd(String s)712     protected abstract void logd(String s);
loge(String s)713     protected abstract void loge(String s);
714 
715     /**
716      * Calculate the size of a data file
717      *
718      * @param data the raw file
719      * @return the size of the file
720      */
getDataFileSize(byte[] data)721     private static int getDataFileSize(byte[] data) {
722         return (((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
723                     + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff));
724     }
725 }
726