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.Build; 22 import android.os.Handler; 23 import android.os.Message; 24 25 import com.android.internal.telephony.CommandsInterface; 26 27 import java.util.ArrayList; 28 29 /** 30 * {@hide} 31 */ 32 public abstract class IccFileHandler extends Handler implements IccConstants { 33 private static final boolean VDBG = false; 34 35 //from TS 11.11 9.1 or elsewhere 36 static protected final int COMMAND_READ_BINARY = 0xb0; 37 static protected final int COMMAND_UPDATE_BINARY = 0xd6; 38 static protected final int COMMAND_READ_RECORD = 0xb2; 39 static protected final int COMMAND_UPDATE_RECORD = 0xdc; 40 static protected final int COMMAND_SEEK = 0xa2; 41 static protected final int COMMAND_GET_RESPONSE = 0xc0; 42 43 // from TS 11.11 9.2.5 44 static protected final int READ_RECORD_MODE_ABSOLUTE = 4; 45 46 //***** types of files TS 11.11 9.3 47 static protected final int EF_TYPE_TRANSPARENT = 0; 48 static protected final int EF_TYPE_LINEAR_FIXED = 1; 49 static protected final int EF_TYPE_CYCLIC = 3; 50 51 //***** types of files TS 11.11 9.3 52 static protected final int TYPE_RFU = 0; 53 static protected final int TYPE_MF = 1; 54 static protected final int TYPE_DF = 2; 55 static protected final int TYPE_EF = 4; 56 57 // size of GET_RESPONSE for EF's 58 static protected final int GET_RESPONSE_EF_SIZE_BYTES = 15; 59 static protected final int GET_RESPONSE_EF_IMG_SIZE_BYTES = 10; 60 61 // Byte order received in response to COMMAND_GET_RESPONSE 62 // Refer TS 51.011 Section 9.2.1 63 static protected final int RESPONSE_DATA_RFU_1 = 0; 64 static protected final int RESPONSE_DATA_RFU_2 = 1; 65 66 static protected final int RESPONSE_DATA_FILE_SIZE_1 = 2; 67 static protected final int RESPONSE_DATA_FILE_SIZE_2 = 3; 68 69 static protected final int RESPONSE_DATA_FILE_ID_1 = 4; 70 static protected final int RESPONSE_DATA_FILE_ID_2 = 5; 71 static protected final int RESPONSE_DATA_FILE_TYPE = 6; 72 static protected final int RESPONSE_DATA_RFU_3 = 7; 73 static protected final int RESPONSE_DATA_ACCESS_CONDITION_1 = 8; 74 static protected final int RESPONSE_DATA_ACCESS_CONDITION_2 = 9; 75 static protected final int RESPONSE_DATA_ACCESS_CONDITION_3 = 10; 76 static protected final int RESPONSE_DATA_FILE_STATUS = 11; 77 static protected final int RESPONSE_DATA_LENGTH = 12; 78 static protected final int RESPONSE_DATA_STRUCTURE = 13; 79 static protected final int RESPONSE_DATA_RECORD_LENGTH = 14; 80 81 82 //***** Events 83 84 /** Finished retrieving size of transparent EF; start loading. */ 85 static protected final int EVENT_GET_BINARY_SIZE_DONE = 4; 86 /** Finished loading contents of transparent EF; post result. */ 87 static protected final int EVENT_READ_BINARY_DONE = 5; 88 /** Finished retrieving size of records for linear-fixed EF; now load. */ 89 static protected final int EVENT_GET_RECORD_SIZE_DONE = 6; 90 /** Finished loading single record from a linear-fixed EF; post result. */ 91 static protected final int EVENT_READ_RECORD_DONE = 7; 92 /** Finished retrieving record size; post result. */ 93 static protected final int EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE = 8; 94 /** Finished retrieving image instance record; post result. */ 95 static protected final int EVENT_READ_IMG_DONE = 9; 96 /** Finished retrieving icon data; post result. */ 97 static protected final int EVENT_READ_ICON_DONE = 10; 98 /** Finished retrieving size of record for EFimg now. */ 99 static protected final int EVENT_GET_RECORD_SIZE_IMG_DONE = 11; 100 /** Finished retriveing record size of transparent file. */ 101 protected static final int EVENT_GET_EF_TRANSPARENT_SIZE_DONE = 12; 102 103 // member variables 104 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 105 protected final CommandsInterface mCi; 106 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 107 protected final UiccCardApplication mParentApp; 108 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 109 protected final String mAid; 110 111 static class LoadLinearFixedContext { 112 113 int mEfid; 114 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 115 int mRecordNum, mRecordSize, mCountRecords; 116 boolean mLoadAll; 117 String mPath; 118 119 Message mOnLoaded; 120 121 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 122 ArrayList<byte[]> results; 123 124 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) LoadLinearFixedContext(int efid, int recordNum, Message onLoaded)125 LoadLinearFixedContext(int efid, int recordNum, Message onLoaded) { 126 mEfid = efid; 127 mRecordNum = recordNum; 128 mOnLoaded = onLoaded; 129 mLoadAll = false; 130 mPath = null; 131 } 132 LoadLinearFixedContext(int efid, int recordNum, String path, Message onLoaded)133 LoadLinearFixedContext(int efid, int recordNum, String path, Message onLoaded) { 134 mEfid = efid; 135 mRecordNum = recordNum; 136 mOnLoaded = onLoaded; 137 mLoadAll = false; 138 mPath = path; 139 } 140 LoadLinearFixedContext(int efid, String path, Message onLoaded)141 LoadLinearFixedContext(int efid, String path, Message onLoaded) { 142 mEfid = efid; 143 mRecordNum = 1; 144 mLoadAll = true; 145 mOnLoaded = onLoaded; 146 mPath = path; 147 } 148 LoadLinearFixedContext(int efid, Message onLoaded)149 LoadLinearFixedContext(int efid, Message onLoaded) { 150 mEfid = efid; 151 mRecordNum = 1; 152 mLoadAll = true; 153 mOnLoaded = onLoaded; 154 mPath = null; 155 } 156 } 157 158 /** 159 * Default constructor 160 */ IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci)161 protected IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) { 162 mParentApp = app; 163 mAid = aid; 164 mCi = ci; 165 } 166 dispose()167 public void dispose() { 168 } 169 170 //***** Public Methods 171 172 /** 173 * Load a record from a SIM Linear Fixed EF 174 * 175 * @param fileid EF id 176 * @param path Path of the EF on the card 177 * @param recordNum 1-based (not 0-based) record number 178 * @param onLoaded 179 * 180 * ((AsyncResult)(onLoaded.obj)).result is the byte[] 181 * 182 */ 183 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) loadEFLinearFixed(int fileid, String path, int recordNum, Message onLoaded)184 public void loadEFLinearFixed(int fileid, String path, int recordNum, Message onLoaded) { 185 String efPath = (path == null) ? getEFPath(fileid) : path; 186 Message response 187 = obtainMessage(EVENT_GET_RECORD_SIZE_DONE, 188 new LoadLinearFixedContext(fileid, recordNum, efPath, onLoaded)); 189 190 mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath, 191 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response); 192 } 193 194 /** 195 * Load a record from a SIM Linear Fixed EF 196 * 197 * @param fileid EF id 198 * @param recordNum 1-based (not 0-based) record number 199 * @param onLoaded 200 * 201 * ((AsyncResult)(onLoaded.obj)).result is the byte[] 202 * 203 */ 204 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) loadEFLinearFixed(int fileid, int recordNum, Message onLoaded)205 public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) { 206 loadEFLinearFixed(fileid, getEFPath(fileid), recordNum, onLoaded); 207 } 208 209 /** 210 * Load a image instance record from a SIM Linear Fixed EF-IMG 211 * 212 * @param recordNum 1-based (not 0-based) record number 213 * @param onLoaded 214 * 215 * ((AsyncResult)(onLoaded.obj)).result is the byte[] 216 * 217 */ loadEFImgLinearFixed(int recordNum, Message onLoaded)218 public void loadEFImgLinearFixed(int recordNum, Message onLoaded) { 219 Message response = obtainMessage(EVENT_GET_RECORD_SIZE_IMG_DONE, 220 new LoadLinearFixedContext(IccConstants.EF_IMG, recordNum, 221 onLoaded)); 222 223 mCi.iccIOForApp(COMMAND_GET_RESPONSE, IccConstants.EF_IMG, 224 getEFPath(IccConstants.EF_IMG), recordNum, 225 READ_RECORD_MODE_ABSOLUTE, GET_RESPONSE_EF_IMG_SIZE_BYTES, 226 null, null, mAid, response); 227 } 228 229 /** 230 * Get record size for a linear fixed EF 231 * 232 * @param fileid EF id 233 * @param path Path of the EF on the card 234 * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]. recordSize[0] is 235 * the single record length, recordSize[1] is the total length of the EF file 236 * and recordSize[2] is the number of records in the EF file. So recordSize[0] 237 * * recordSize[2] = recordSize[1]. 238 */ 239 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getEFLinearRecordSize(int fileid, String path, Message onLoaded)240 public void getEFLinearRecordSize(int fileid, String path, Message onLoaded) { 241 String efPath = (path == null) ? getEFPath(fileid) : path; 242 Message response 243 = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE, 244 new LoadLinearFixedContext(fileid, efPath, onLoaded)); 245 mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath, 246 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response); 247 } 248 249 /** 250 * Get record size for a linear fixed EF 251 * 252 * @param fileid EF id 253 * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]. recordSize[0] is 254 * the single record length, recordSize[1] is the total length of the EF file 255 * and recordSize[2] is the number of records in the EF file. So recordSize[0] 256 * * recordSize[2] = recordSize[1]. 257 */ 258 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getEFLinearRecordSize(int fileid, Message onLoaded)259 public void getEFLinearRecordSize(int fileid, Message onLoaded) { 260 getEFLinearRecordSize(fileid, getEFPath(fileid), onLoaded); 261 } 262 263 /** 264 * Get record size for a transparent EF 265 * 266 * @param fileid EF id 267 * @param path Path of the EF on the card 268 * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the size of data int 269 */ getEFTransparentRecordSize(int fileid, String path, Message onLoaded)270 public void getEFTransparentRecordSize(int fileid, String path, Message onLoaded) { 271 String efPath = (path == null) ? getEFPath(fileid) : path; 272 Message response = obtainMessage(EVENT_GET_EF_TRANSPARENT_SIZE_DONE, fileid, 0, onLoaded); 273 mCi.iccIOForApp( 274 COMMAND_GET_RESPONSE, 275 fileid, 276 getEFPath(fileid), 277 0, 278 0, 279 GET_RESPONSE_EF_SIZE_BYTES, 280 null, 281 null, 282 mAid, 283 response); 284 } 285 286 /** 287 * Get record size for a transparent EF 288 * 289 * @param fileid EF id 290 * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the size of the data int 291 */ getEFTransparentRecordSize(int fileid, Message onLoaded)292 public void getEFTransparentRecordSize(int fileid, Message onLoaded) { 293 getEFTransparentRecordSize(fileid, getEFPath(fileid), onLoaded); 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_PSI: 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