1 /* 2 * Copyright (C) 2006, 2012 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.app.AlertDialog; 20 import android.app.usage.UsageStatsManager; 21 import android.content.ActivityNotFoundException; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.Intent; 26 import android.content.SharedPreferences; 27 import android.content.pm.PackageInfo; 28 import android.content.pm.PackageManager; 29 import android.content.pm.Signature; 30 import android.content.res.Resources; 31 import android.net.Uri; 32 import android.os.AsyncResult; 33 import android.os.Binder; 34 import android.os.Handler; 35 import android.os.Message; 36 import android.os.PowerManager; 37 import android.os.Registrant; 38 import android.os.RegistrantList; 39 import android.preference.PreferenceManager; 40 import android.provider.Settings; 41 import android.telephony.Rlog; 42 import android.telephony.TelephonyManager; 43 import android.text.TextUtils; 44 import android.util.LocalLog; 45 import android.view.WindowManager; 46 47 import com.android.internal.telephony.CommandsInterface; 48 import com.android.internal.telephony.CommandsInterface.RadioState; 49 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; 50 import com.android.internal.telephony.uicc.IccCardStatus.CardState; 51 import com.android.internal.telephony.uicc.IccCardStatus.PinState; 52 import com.android.internal.telephony.cat.CatService; 53 54 import com.android.internal.R; 55 56 import java.io.FileDescriptor; 57 import java.io.PrintWriter; 58 59 import java.util.Arrays; 60 import java.util.HashSet; 61 import java.util.List; 62 63 /** 64 * {@hide} 65 */ 66 public class UiccCard { 67 protected static final String LOG_TAG = "UiccCard"; 68 protected static final boolean DBG = true; 69 70 public static final String EXTRA_ICC_CARD_ADDED = 71 "com.android.internal.telephony.uicc.ICC_CARD_ADDED"; 72 73 private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_"; 74 75 private final Object mLock = new Object(); 76 private CardState mCardState; 77 private PinState mUniversalPinState; 78 private int mGsmUmtsSubscriptionAppIndex; 79 private int mCdmaSubscriptionAppIndex; 80 private int mImsSubscriptionAppIndex; 81 private UiccCardApplication[] mUiccApplications = 82 new UiccCardApplication[IccCardStatus.CARD_MAX_APPS]; 83 private Context mContext; 84 private CommandsInterface mCi; 85 private CatService mCatService; 86 private RadioState mLastRadioState = RadioState.RADIO_UNAVAILABLE; 87 private UiccCarrierPrivilegeRules mCarrierPrivilegeRules; 88 89 private RegistrantList mAbsentRegistrants = new RegistrantList(); 90 private RegistrantList mCarrierPrivilegeRegistrants = new RegistrantList(); 91 92 private static final int EVENT_CARD_REMOVED = 13; 93 private static final int EVENT_CARD_ADDED = 14; 94 private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 15; 95 private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 16; 96 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 17; 97 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 18; 98 private static final int EVENT_SIM_IO_DONE = 19; 99 private static final int EVENT_CARRIER_PRIVILIGES_LOADED = 20; 100 101 private static final LocalLog mLocalLog = new LocalLog(100); 102 103 private int mPhoneId; 104 UiccCard(Context c, CommandsInterface ci, IccCardStatus ics)105 public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics) { 106 if (DBG) log("Creating"); 107 mCardState = ics.mCardState; 108 update(c, ci, ics); 109 } 110 UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId)111 public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) { 112 mCardState = ics.mCardState; 113 mPhoneId = phoneId; 114 update(c, ci, ics); 115 } 116 UiccCard()117 protected UiccCard() { 118 } 119 dispose()120 public void dispose() { 121 synchronized (mLock) { 122 if (DBG) log("Disposing card"); 123 if (mCatService != null) mCatService.dispose(); 124 for (UiccCardApplication app : mUiccApplications) { 125 if (app != null) { 126 app.dispose(); 127 } 128 } 129 mCatService = null; 130 mUiccApplications = null; 131 mCarrierPrivilegeRules = null; 132 } 133 } 134 update(Context c, CommandsInterface ci, IccCardStatus ics)135 public void update(Context c, CommandsInterface ci, IccCardStatus ics) { 136 synchronized (mLock) { 137 CardState oldState = mCardState; 138 mCardState = ics.mCardState; 139 mUniversalPinState = ics.mUniversalPinState; 140 mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex; 141 mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex; 142 mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex; 143 mContext = c; 144 mCi = ci; 145 146 //update applications 147 if (DBG) log(ics.mApplications.length + " applications"); 148 for ( int i = 0; i < mUiccApplications.length; i++) { 149 if (mUiccApplications[i] == null) { 150 //Create newly added Applications 151 if (i < ics.mApplications.length) { 152 mUiccApplications[i] = new UiccCardApplication(this, 153 ics.mApplications[i], mContext, mCi); 154 } 155 } else if (i >= ics.mApplications.length) { 156 //Delete removed applications 157 mUiccApplications[i].dispose(); 158 mUiccApplications[i] = null; 159 } else { 160 //Update the rest 161 mUiccApplications[i].update(ics.mApplications[i], mContext, mCi); 162 } 163 } 164 165 createAndUpdateCatService(); 166 167 // Reload the carrier privilege rules if necessary. 168 log("Before privilege rules: " + mCarrierPrivilegeRules + " : " + mCardState); 169 if (mCarrierPrivilegeRules == null && mCardState == CardState.CARDSTATE_PRESENT) { 170 mCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(this, 171 mHandler.obtainMessage(EVENT_CARRIER_PRIVILIGES_LOADED)); 172 } else if (mCarrierPrivilegeRules != null && mCardState != CardState.CARDSTATE_PRESENT) { 173 mCarrierPrivilegeRules = null; 174 } 175 176 sanitizeApplicationIndexes(); 177 178 RadioState radioState = mCi.getRadioState(); 179 if (DBG) log("update: radioState=" + radioState + " mLastRadioState=" 180 + mLastRadioState); 181 // No notifications while radio is off or we just powering up 182 if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) { 183 if (oldState != CardState.CARDSTATE_ABSENT && 184 mCardState == CardState.CARDSTATE_ABSENT) { 185 if (DBG) log("update: notify card removed"); 186 mAbsentRegistrants.notifyRegistrants(); 187 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null)); 188 } else if (oldState == CardState.CARDSTATE_ABSENT && 189 mCardState != CardState.CARDSTATE_ABSENT) { 190 if (DBG) log("update: notify card added"); 191 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null)); 192 } 193 } 194 mLastRadioState = radioState; 195 } 196 } 197 createAndUpdateCatService()198 protected void createAndUpdateCatService() { 199 if (mUiccApplications.length > 0 && mUiccApplications[0] != null) { 200 // Initialize or Reinitialize CatService 201 if (mCatService == null) { 202 mCatService = CatService.getInstance(mCi, mContext, this, mPhoneId); 203 } else { 204 ((CatService)mCatService).update(mCi, mContext, this); 205 } 206 } else { 207 if (mCatService != null) { 208 mCatService.dispose(); 209 } 210 mCatService = null; 211 } 212 } 213 getCatService()214 public CatService getCatService() { 215 return mCatService; 216 } 217 218 @Override finalize()219 protected void finalize() { 220 if (DBG) log("UiccCard finalized"); 221 } 222 223 /** 224 * This function makes sure that application indexes are valid 225 * and resets invalid indexes. (This should never happen, but in case 226 * RIL misbehaves we need to manage situation gracefully) 227 */ sanitizeApplicationIndexes()228 private void sanitizeApplicationIndexes() { 229 mGsmUmtsSubscriptionAppIndex = 230 checkIndex(mGsmUmtsSubscriptionAppIndex, AppType.APPTYPE_SIM, AppType.APPTYPE_USIM); 231 mCdmaSubscriptionAppIndex = 232 checkIndex(mCdmaSubscriptionAppIndex, AppType.APPTYPE_RUIM, AppType.APPTYPE_CSIM); 233 mImsSubscriptionAppIndex = 234 checkIndex(mImsSubscriptionAppIndex, AppType.APPTYPE_ISIM, null); 235 } 236 checkIndex(int index, AppType expectedAppType, AppType altExpectedAppType)237 private int checkIndex(int index, AppType expectedAppType, AppType altExpectedAppType) { 238 if (mUiccApplications == null || index >= mUiccApplications.length) { 239 loge("App index " + index + " is invalid since there are no applications"); 240 return -1; 241 } 242 243 if (index < 0) { 244 // This is normal. (i.e. no application of this type) 245 return -1; 246 } 247 248 if (mUiccApplications[index].getType() != expectedAppType && 249 mUiccApplications[index].getType() != altExpectedAppType) { 250 loge("App index " + index + " is invalid since it's not " + 251 expectedAppType + " and not " + altExpectedAppType); 252 return -1; 253 } 254 255 // Seems to be valid 256 return index; 257 } 258 259 /** 260 * Notifies handler of any transition into State.ABSENT 261 */ registerForAbsent(Handler h, int what, Object obj)262 public void registerForAbsent(Handler h, int what, Object obj) { 263 synchronized (mLock) { 264 Registrant r = new Registrant (h, what, obj); 265 266 mAbsentRegistrants.add(r); 267 268 if (mCardState == CardState.CARDSTATE_ABSENT) { 269 r.notifyRegistrant(); 270 } 271 } 272 } 273 unregisterForAbsent(Handler h)274 public void unregisterForAbsent(Handler h) { 275 synchronized (mLock) { 276 mAbsentRegistrants.remove(h); 277 } 278 } 279 280 /** 281 * Notifies handler when carrier privilege rules are loaded. 282 */ registerForCarrierPrivilegeRulesLoaded(Handler h, int what, Object obj)283 public void registerForCarrierPrivilegeRulesLoaded(Handler h, int what, Object obj) { 284 synchronized (mLock) { 285 Registrant r = new Registrant (h, what, obj); 286 287 mCarrierPrivilegeRegistrants.add(r); 288 289 if (areCarrierPriviligeRulesLoaded()) { 290 r.notifyRegistrant(); 291 } 292 } 293 } 294 unregisterForCarrierPrivilegeRulesLoaded(Handler h)295 public void unregisterForCarrierPrivilegeRulesLoaded(Handler h) { 296 synchronized (mLock) { 297 mCarrierPrivilegeRegistrants.remove(h); 298 } 299 } 300 onIccSwap(boolean isAdded)301 private void onIccSwap(boolean isAdded) { 302 303 boolean isHotSwapSupported = mContext.getResources().getBoolean( 304 R.bool.config_hotswapCapable); 305 306 if (isHotSwapSupported) { 307 log("onIccSwap: isHotSwapSupported is true, don't prompt for rebooting"); 308 return; 309 } 310 log("onIccSwap: isHotSwapSupported is false, prompt for rebooting"); 311 312 promptForRestart(isAdded); 313 } 314 promptForRestart(boolean isAdded)315 private void promptForRestart(boolean isAdded) { 316 synchronized (mLock) { 317 final Resources res = mContext.getResources(); 318 final String dialogComponent = res.getString( 319 R.string.config_iccHotswapPromptForRestartDialogComponent); 320 if (dialogComponent != null) { 321 Intent intent = new Intent().setComponent(ComponentName.unflattenFromString( 322 dialogComponent)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 323 .putExtra(EXTRA_ICC_CARD_ADDED, isAdded); 324 try { 325 mContext.startActivity(intent); 326 return; 327 } catch (ActivityNotFoundException e) { 328 loge("Unable to find ICC hotswap prompt for restart activity: " + e); 329 } 330 } 331 332 // TODO: Here we assume the device can't handle SIM hot-swap 333 // and has to reboot. We may want to add a property, 334 // e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support 335 // hot-swap. 336 DialogInterface.OnClickListener listener = null; 337 338 339 // TODO: SimRecords is not reset while SIM ABSENT (only reset while 340 // Radio_off_or_not_available). Have to reset in both both 341 // added or removed situation. 342 listener = new DialogInterface.OnClickListener() { 343 @Override 344 public void onClick(DialogInterface dialog, int which) { 345 synchronized (mLock) { 346 if (which == DialogInterface.BUTTON_POSITIVE) { 347 if (DBG) log("Reboot due to SIM swap"); 348 PowerManager pm = (PowerManager) mContext 349 .getSystemService(Context.POWER_SERVICE); 350 pm.reboot("SIM is added."); 351 } 352 } 353 } 354 355 }; 356 357 Resources r = Resources.getSystem(); 358 359 String title = (isAdded) ? r.getString(R.string.sim_added_title) : 360 r.getString(R.string.sim_removed_title); 361 String message = (isAdded) ? r.getString(R.string.sim_added_message) : 362 r.getString(R.string.sim_removed_message); 363 String buttonTxt = r.getString(R.string.sim_restart_button); 364 365 AlertDialog dialog = new AlertDialog.Builder(mContext) 366 .setTitle(title) 367 .setMessage(message) 368 .setPositiveButton(buttonTxt, listener) 369 .create(); 370 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 371 dialog.show(); 372 } 373 } 374 375 protected Handler mHandler = new Handler() { 376 @Override 377 public void handleMessage(Message msg){ 378 switch (msg.what) { 379 case EVENT_CARD_REMOVED: 380 onIccSwap(false); 381 break; 382 case EVENT_CARD_ADDED: 383 onIccSwap(true); 384 break; 385 case EVENT_OPEN_LOGICAL_CHANNEL_DONE: 386 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 387 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE: 388 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE: 389 case EVENT_SIM_IO_DONE: 390 AsyncResult ar = (AsyncResult)msg.obj; 391 if (ar.exception != null) { 392 loglocal("Exception: " + ar.exception); 393 log("Error in SIM access with exception" + ar.exception); 394 } 395 AsyncResult.forMessage((Message)ar.userObj, ar.result, ar.exception); 396 ((Message)ar.userObj).sendToTarget(); 397 break; 398 case EVENT_CARRIER_PRIVILIGES_LOADED: 399 onCarrierPriviligesLoadedMessage(); 400 break; 401 default: 402 loge("Unknown Event " + msg.what); 403 } 404 } 405 }; 406 isPackageInstalled(String pkgName)407 private boolean isPackageInstalled(String pkgName) { 408 PackageManager pm = mContext.getPackageManager(); 409 try { 410 pm.getPackageInfo(pkgName, PackageManager.GET_ACTIVITIES); 411 if (DBG) log(pkgName + " is installed."); 412 return true; 413 } catch (PackageManager.NameNotFoundException e) { 414 if (DBG) log(pkgName + " is not installed."); 415 return false; 416 } 417 } 418 419 private class ClickListener implements DialogInterface.OnClickListener { 420 String pkgName; ClickListener(String pkgName)421 public ClickListener(String pkgName) { 422 this.pkgName = pkgName; 423 } 424 @Override onClick(DialogInterface dialog, int which)425 public void onClick(DialogInterface dialog, int which) { 426 synchronized (mLock) { 427 if (which == DialogInterface.BUTTON_POSITIVE) { 428 Intent market = new Intent(Intent.ACTION_VIEW); 429 market.setData(Uri.parse("market://details?id=" + pkgName)); 430 market.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 431 mContext.startActivity(market); 432 } else if (which == DialogInterface.BUTTON_NEGATIVE) { 433 if (DBG) log("Not now clicked for carrier app dialog."); 434 } 435 } 436 } 437 } 438 promptInstallCarrierApp(String pkgName)439 private void promptInstallCarrierApp(String pkgName) { 440 DialogInterface.OnClickListener listener = new ClickListener(pkgName); 441 442 Resources r = Resources.getSystem(); 443 String message = r.getString(R.string.carrier_app_dialog_message); 444 String buttonTxt = r.getString(R.string.carrier_app_dialog_button); 445 String notNowTxt = r.getString(R.string.carrier_app_dialog_not_now); 446 447 AlertDialog dialog = new AlertDialog.Builder(mContext) 448 .setMessage(message) 449 .setNegativeButton(notNowTxt, listener) 450 .setPositiveButton(buttonTxt, listener) 451 .create(); 452 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 453 dialog.show(); 454 } 455 onCarrierPriviligesLoadedMessage()456 private void onCarrierPriviligesLoadedMessage() { 457 UsageStatsManager usm = (UsageStatsManager) mContext.getSystemService( 458 Context.USAGE_STATS_SERVICE); 459 if (usm != null) { 460 usm.onCarrierPrivilegedAppsChanged(); 461 } 462 synchronized (mLock) { 463 mCarrierPrivilegeRegistrants.notifyRegistrants(); 464 String whitelistSetting = Settings.Global.getString(mContext.getContentResolver(), 465 Settings.Global.CARRIER_APP_WHITELIST); 466 if (TextUtils.isEmpty(whitelistSetting)) { 467 return; 468 } 469 HashSet<String> carrierAppSet = new HashSet<String>( 470 Arrays.asList(whitelistSetting.split("\\s*;\\s*"))); 471 if (carrierAppSet.isEmpty()) { 472 return; 473 } 474 475 List<String> pkgNames = mCarrierPrivilegeRules.getPackageNames(); 476 for (String pkgName : pkgNames) { 477 if (!TextUtils.isEmpty(pkgName) && carrierAppSet.contains(pkgName) 478 && !isPackageInstalled(pkgName)) { 479 promptInstallCarrierApp(pkgName); 480 } 481 } 482 } 483 } 484 isApplicationOnIcc(IccCardApplicationStatus.AppType type)485 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 486 synchronized (mLock) { 487 for (int i = 0 ; i < mUiccApplications.length; i++) { 488 if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) { 489 return true; 490 } 491 } 492 return false; 493 } 494 } 495 getCardState()496 public CardState getCardState() { 497 synchronized (mLock) { 498 return mCardState; 499 } 500 } 501 getUniversalPinState()502 public PinState getUniversalPinState() { 503 synchronized (mLock) { 504 return mUniversalPinState; 505 } 506 } 507 getApplication(int family)508 public UiccCardApplication getApplication(int family) { 509 synchronized (mLock) { 510 int index = IccCardStatus.CARD_MAX_APPS; 511 switch (family) { 512 case UiccController.APP_FAM_3GPP: 513 index = mGsmUmtsSubscriptionAppIndex; 514 break; 515 case UiccController.APP_FAM_3GPP2: 516 index = mCdmaSubscriptionAppIndex; 517 break; 518 case UiccController.APP_FAM_IMS: 519 index = mImsSubscriptionAppIndex; 520 break; 521 } 522 if (index >= 0 && index < mUiccApplications.length) { 523 return mUiccApplications[index]; 524 } 525 return null; 526 } 527 } 528 getApplicationIndex(int index)529 public UiccCardApplication getApplicationIndex(int index) { 530 synchronized (mLock) { 531 if (index >= 0 && index < mUiccApplications.length) { 532 return mUiccApplications[index]; 533 } 534 return null; 535 } 536 } 537 538 /** 539 * Returns the SIM application of the specified type. 540 * 541 * @param type ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx) 542 * @return application corresponding to type or a null if no match found 543 */ getApplicationByType(int type)544 public UiccCardApplication getApplicationByType(int type) { 545 synchronized (mLock) { 546 for (int i = 0 ; i < mUiccApplications.length; i++) { 547 if (mUiccApplications[i] != null && 548 mUiccApplications[i].getType().ordinal() == type) { 549 return mUiccApplications[i]; 550 } 551 } 552 return null; 553 } 554 } 555 556 /** 557 * Resets the application with the input AID. Returns true if any changes were made. 558 * 559 * A null aid implies a card level reset - all applications must be reset. 560 */ resetAppWithAid(String aid)561 public boolean resetAppWithAid(String aid) { 562 synchronized (mLock) { 563 boolean changed = false; 564 for (int i = 0; i < mUiccApplications.length; i++) { 565 if (mUiccApplications[i] != null && 566 (aid == null || aid.equals(mUiccApplications[i].getAid()))) { 567 // Delete removed applications 568 mUiccApplications[i].dispose(); 569 mUiccApplications[i] = null; 570 changed = true; 571 } 572 } 573 return changed; 574 } 575 // TODO: For a card level notification, we should delete the CarrierPrivilegeRules and the 576 // CAT service. 577 } 578 579 /** 580 * Exposes {@link CommandsInterface.iccOpenLogicalChannel} 581 */ iccOpenLogicalChannel(String AID, Message response)582 public void iccOpenLogicalChannel(String AID, Message response) { 583 loglocal("Open Logical Channel: " + AID + " by pid:" + Binder.getCallingPid() 584 + " uid:" + Binder.getCallingUid()); 585 mCi.iccOpenLogicalChannel(AID, 586 mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, response)); 587 } 588 589 /** 590 * Exposes {@link CommandsInterface.iccCloseLogicalChannel} 591 */ iccCloseLogicalChannel(int channel, Message response)592 public void iccCloseLogicalChannel(int channel, Message response) { 593 loglocal("Close Logical Channel: " + channel); 594 mCi.iccCloseLogicalChannel(channel, 595 mHandler.obtainMessage(EVENT_CLOSE_LOGICAL_CHANNEL_DONE, response)); 596 } 597 598 /** 599 * Exposes {@link CommandsInterface.iccTransmitApduLogicalChannel} 600 */ iccTransmitApduLogicalChannel(int channel, int cla, int command, int p1, int p2, int p3, String data, Message response)601 public void iccTransmitApduLogicalChannel(int channel, int cla, int command, 602 int p1, int p2, int p3, String data, Message response) { 603 mCi.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3, 604 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, response)); 605 } 606 607 /** 608 * Exposes {@link CommandsInterface.iccTransmitApduBasicChannel} 609 */ iccTransmitApduBasicChannel(int cla, int command, int p1, int p2, int p3, String data, Message response)610 public void iccTransmitApduBasicChannel(int cla, int command, 611 int p1, int p2, int p3, String data, Message response) { 612 mCi.iccTransmitApduBasicChannel(cla, command, p1, p2, p3, 613 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, response)); 614 } 615 616 /** 617 * Exposes {@link CommandsInterface.iccIO} 618 */ iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3, String pathID, Message response)619 public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3, 620 String pathID, Message response) { 621 mCi.iccIO(command, fileID, pathID, p1, p2, p3, null, null, 622 mHandler.obtainMessage(EVENT_SIM_IO_DONE, response)); 623 } 624 625 /** 626 * Exposes {@link CommandsInterface.sendEnvelopeWithStatus} 627 */ sendEnvelopeWithStatus(String contents, Message response)628 public void sendEnvelopeWithStatus(String contents, Message response) { 629 mCi.sendEnvelopeWithStatus(contents, response); 630 } 631 632 /* Returns number of applications on this card */ getNumApplications()633 public int getNumApplications() { 634 int count = 0; 635 for (UiccCardApplication a : mUiccApplications) { 636 if (a != null) { 637 count++; 638 } 639 } 640 return count; 641 } 642 getPhoneId()643 public int getPhoneId() { 644 return mPhoneId; 645 } 646 647 /** 648 * Returns true iff carrier privileges rules are null (dont need to be loaded) or loaded. 649 */ areCarrierPriviligeRulesLoaded()650 public boolean areCarrierPriviligeRulesLoaded() { 651 return mCarrierPrivilegeRules == null 652 || mCarrierPrivilegeRules.areCarrierPriviligeRulesLoaded(); 653 } 654 655 /** 656 * Returns true if there are some carrier privilege rules loaded and specified. 657 */ hasCarrierPrivilegeRules()658 public boolean hasCarrierPrivilegeRules() { 659 return mCarrierPrivilegeRules != null 660 && mCarrierPrivilegeRules.hasCarrierPrivilegeRules(); 661 } 662 663 /** 664 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}. 665 */ getCarrierPrivilegeStatus(Signature signature, String packageName)666 public int getCarrierPrivilegeStatus(Signature signature, String packageName) { 667 return mCarrierPrivilegeRules == null ? 668 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 669 mCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature, packageName); 670 } 671 672 /** 673 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}. 674 */ getCarrierPrivilegeStatus(PackageManager packageManager, String packageName)675 public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) { 676 return mCarrierPrivilegeRules == null ? 677 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 678 mCarrierPrivilegeRules.getCarrierPrivilegeStatus(packageManager, packageName); 679 } 680 681 /** 682 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}. 683 */ getCarrierPrivilegeStatus(PackageInfo packageInfo)684 public int getCarrierPrivilegeStatus(PackageInfo packageInfo) { 685 return mCarrierPrivilegeRules == null ? 686 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 687 mCarrierPrivilegeRules.getCarrierPrivilegeStatus(packageInfo); 688 } 689 690 /** 691 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction}. 692 */ getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager)693 public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) { 694 return mCarrierPrivilegeRules == null ? 695 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 696 mCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction(packageManager); 697 } 698 699 /** 700 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPackageNamesForIntent}. 701 */ getCarrierPackageNamesForIntent( PackageManager packageManager, Intent intent)702 public List<String> getCarrierPackageNamesForIntent( 703 PackageManager packageManager, Intent intent) { 704 return mCarrierPrivilegeRules == null ? null : 705 mCarrierPrivilegeRules.getCarrierPackageNamesForIntent( 706 packageManager, intent); 707 } 708 setOperatorBrandOverride(String brand)709 public boolean setOperatorBrandOverride(String brand) { 710 log("setOperatorBrandOverride: " + brand); 711 log("current iccId: " + getIccId()); 712 713 String iccId = getIccId(); 714 if (TextUtils.isEmpty(iccId)) { 715 return false; 716 } 717 718 SharedPreferences.Editor spEditor = 719 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 720 String key = OPERATOR_BRAND_OVERRIDE_PREFIX + iccId; 721 if (brand == null) { 722 spEditor.remove(key).commit(); 723 } else { 724 spEditor.putString(key, brand).commit(); 725 } 726 return true; 727 } 728 getOperatorBrandOverride()729 public String getOperatorBrandOverride() { 730 String iccId = getIccId(); 731 if (TextUtils.isEmpty(iccId)) { 732 return null; 733 } 734 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); 735 return sp.getString(OPERATOR_BRAND_OVERRIDE_PREFIX + iccId, null); 736 } 737 getIccId()738 public String getIccId() { 739 // ICCID should be same across all the apps. 740 for (UiccCardApplication app : mUiccApplications) { 741 if (app != null) { 742 IccRecords ir = app.getIccRecords(); 743 if (ir != null && ir.getIccId() != null) { 744 return ir.getIccId(); 745 } 746 } 747 } 748 return null; 749 } 750 log(String msg)751 private void log(String msg) { 752 Rlog.d(LOG_TAG, msg); 753 } 754 loge(String msg)755 private void loge(String msg) { 756 Rlog.e(LOG_TAG, msg); 757 } 758 loglocal(String msg)759 private void loglocal(String msg) { 760 if (DBG) mLocalLog.log(msg); 761 } 762 dump(FileDescriptor fd, PrintWriter pw, String[] args)763 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 764 pw.println("UiccCard:"); 765 pw.println(" mCi=" + mCi); 766 pw.println(" mLastRadioState=" + mLastRadioState); 767 pw.println(" mCatService=" + mCatService); 768 pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size()); 769 for (int i = 0; i < mAbsentRegistrants.size(); i++) { 770 pw.println(" mAbsentRegistrants[" + i + "]=" 771 + ((Registrant)mAbsentRegistrants.get(i)).getHandler()); 772 } 773 for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) { 774 pw.println(" mCarrierPrivilegeRegistrants[" + i + "]=" 775 + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler()); 776 } 777 pw.println(" mCardState=" + mCardState); 778 pw.println(" mUniversalPinState=" + mUniversalPinState); 779 pw.println(" mGsmUmtsSubscriptionAppIndex=" + mGsmUmtsSubscriptionAppIndex); 780 pw.println(" mCdmaSubscriptionAppIndex=" + mCdmaSubscriptionAppIndex); 781 pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex); 782 pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex); 783 pw.println(" mUiccApplications: length=" + mUiccApplications.length); 784 for (int i = 0; i < mUiccApplications.length; i++) { 785 if (mUiccApplications[i] == null) { 786 pw.println(" mUiccApplications[" + i + "]=" + null); 787 } else { 788 pw.println(" mUiccApplications[" + i + "]=" 789 + mUiccApplications[i].getType() + " " + mUiccApplications[i]); 790 } 791 } 792 pw.println(); 793 // Print details of all applications 794 for (UiccCardApplication app : mUiccApplications) { 795 if (app != null) { 796 app.dump(fd, pw, args); 797 pw.println(); 798 } 799 } 800 // Print details of all IccRecords 801 for (UiccCardApplication app : mUiccApplications) { 802 if (app != null) { 803 IccRecords ir = app.getIccRecords(); 804 if (ir != null) { 805 ir.dump(fd, pw, args); 806 pw.println(); 807 } 808 } 809 } 810 // Print UiccCarrierPrivilegeRules and registrants. 811 if (mCarrierPrivilegeRules == null) { 812 pw.println(" mCarrierPrivilegeRules: null"); 813 } else { 814 pw.println(" mCarrierPrivilegeRules: " + mCarrierPrivilegeRules); 815 mCarrierPrivilegeRules.dump(fd, pw, args); 816 } 817 pw.println(" mCarrierPrivilegeRegistrants: size=" + mCarrierPrivilegeRegistrants.size()); 818 for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) { 819 pw.println(" mCarrierPrivilegeRegistrants[" + i + "]=" 820 + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler()); 821 } 822 pw.flush(); 823 pw.println("mLocalLog:"); 824 mLocalLog.dump(fd, pw, args); 825 pw.flush(); 826 } 827 } 828