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_PRIVILEGES_LOADED = 20; 98 99 private static final LocalLog mLocalLog = new LocalLog(100); 100 101 private final int mPhoneId; 102 UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId)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 dispose()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 update(Context c, CommandsInterface ci, IccCardStatus ics)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_PRIVILEGES_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 createAndUpdateCatServiceLocked()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 finalize()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 */ sanitizeApplicationIndexesLocked()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 checkIndexLocked(int index, AppType expectedAppType, AppType altExpectedAppType)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 */ registerForAbsent(Handler h, int what, Object obj)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 unregisterForAbsent(Handler h)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 */ registerForCarrierPrivilegeRulesLoaded(Handler h, int what, Object obj)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 unregisterForCarrierPrivilegeRulesLoaded(Handler h)284 public void unregisterForCarrierPrivilegeRulesLoaded(Handler h) { 285 synchronized (mLock) { 286 mCarrierPrivilegeRegistrants.remove(h); 287 } 288 } 289 onIccSwap(boolean isAdded)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 promptForRestart(boolean isAdded)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_PRIVILEGES_LOADED: 388 onCarrierPriviligesLoadedMessage(); 389 break; 390 default: 391 loge("Unknown Event " + msg.what); 392 } 393 } 394 }; 395 isPackageInstalled(String pkgName)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; ClickListener(String pkgName)410 public ClickListener(String pkgName) { 411 this.pkgName = pkgName; 412 } 413 @Override onClick(DialogInterface dialog, int which)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 promptInstallCarrierApp(String pkgName)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 onCarrierPriviligesLoadedMessage()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 isApplicationOnIcc(IccCardApplicationStatus.AppType type)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 getCardState()485 public CardState getCardState() { 486 synchronized (mLock) { 487 return mCardState; 488 } 489 } 490 getUniversalPinState()491 public PinState getUniversalPinState() { 492 synchronized (mLock) { 493 return mUniversalPinState; 494 } 495 } 496 getApplication(int family)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 getApplicationIndex(int index)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 */ getApplicationByType(int type)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 */ resetAppWithAid(String aid)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 */ 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 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 */ hasCarrierPrivilegeRules()657 public boolean hasCarrierPrivilegeRules() { 658 UiccCarrierPrivilegeRules carrierPrivilegeRules = getCarrierPrivilegeRules(); 659 return carrierPrivilegeRules != null && carrierPrivilegeRules.hasCarrierPrivilegeRules(); 660 } 661 662 /** 663 * Exposes {@link UiccCarrierPrivilegeRules#getCarrierPrivilegeStatus}. 664 */ getCarrierPrivilegeStatus(Signature signature, String packageName)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 */ getCarrierPrivilegeStatus(PackageManager packageManager, String packageName)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 */ getCarrierPrivilegeStatus(PackageInfo packageInfo)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 */ getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager)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 */ getCarrierPackageNamesForIntent( PackageManager packageManager, Intent intent)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}. */ getCarrierPrivilegeRules()715 private UiccCarrierPrivilegeRules getCarrierPrivilegeRules() { 716 synchronized (mLock) { 717 return mCarrierPrivilegeRules; 718 } 719 } 720 setOperatorBrandOverride(String brand)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 getOperatorBrandOverride()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 getIccId()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 log(String msg)763 private void log(String msg) { 764 Rlog.d(LOG_TAG, msg); 765 } 766 loge(String msg)767 private void loge(String msg) { 768 Rlog.e(LOG_TAG, msg); 769 } 770 loglocal(String msg)771 private void loglocal(String msg) { 772 if (DBG) mLocalLog.log(msg); 773 } 774 dump(FileDescriptor fd, PrintWriter pw, String[] args)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