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