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