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