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