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