1/* 2* Copyright (C) 2014 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; 18 19import android.app.ActivityManager; 20import android.app.UserSwitchObserver; 21import android.content.BroadcastReceiver; 22import android.content.ContentResolver; 23import android.content.ContentValues; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.SharedPreferences; 28import android.content.pm.IPackageManager; 29import android.os.AsyncResult; 30import android.os.Handler; 31import android.os.IRemoteCallback; 32import android.os.Message; 33import android.os.RemoteException; 34import android.os.ServiceManager; 35import android.os.UserHandle; 36import android.os.UserManager; 37import android.preference.PreferenceManager; 38import android.provider.Settings; 39import android.telephony.CarrierConfigManager; 40import android.telephony.Rlog; 41import android.telephony.SubscriptionInfo; 42import android.telephony.SubscriptionManager; 43import android.telephony.TelephonyManager; 44import android.text.TextUtils; 45 46import com.android.internal.telephony.uicc.IccCardProxy; 47import com.android.internal.telephony.uicc.IccConstants; 48import com.android.internal.telephony.uicc.IccFileHandler; 49import com.android.internal.telephony.uicc.IccRecords; 50import com.android.internal.telephony.uicc.IccUtils; 51 52import java.io.FileDescriptor; 53import java.io.PrintWriter; 54import java.util.HashMap; 55import java.util.Iterator; 56import java.util.List; 57import java.util.Map; 58 59/** 60 *@hide 61 */ 62public class SubscriptionInfoUpdater extends Handler { 63 private static final String LOG_TAG = "SubscriptionInfoUpdater"; 64 private static final int PROJECT_SIM_NUM = TelephonyManager.getDefault().getPhoneCount(); 65 66 private static final int EVENT_SIM_LOCKED_QUERY_ICCID_DONE = 1; 67 private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 2; 68 private static final int EVENT_SIM_LOADED = 3; 69 private static final int EVENT_SIM_ABSENT = 4; 70 private static final int EVENT_SIM_LOCKED = 5; 71 private static final int EVENT_SIM_IO_ERROR = 6; 72 private static final int EVENT_SIM_UNKNOWN = 7; 73 private static final int EVENT_SIM_RESTRICTED = 8; 74 75 private static final String ICCID_STRING_FOR_NO_SIM = ""; 76 /** 77 * int[] sInsertSimState maintains all slots' SIM inserted status currently, 78 * it may contain 4 kinds of values: 79 * SIM_NOT_INSERT : no SIM inserted in slot i now 80 * SIM_CHANGED : a valid SIM insert in slot i and is different SIM from last time 81 * it will later become SIM_NEW or SIM_REPOSITION during update procedure 82 * SIM_NOT_CHANGE : a valid SIM insert in slot i and is the same SIM as last time 83 * SIM_NEW : a valid SIM insert in slot i and is a new SIM 84 * SIM_REPOSITION : a valid SIM insert in slot i and is inserted in different slot last time 85 * positive integer #: index to distinguish SIM cards with the same IccId 86 */ 87 public static final int SIM_NOT_CHANGE = 0; 88 public static final int SIM_CHANGED = -1; 89 public static final int SIM_NEW = -2; 90 public static final int SIM_REPOSITION = -3; 91 public static final int SIM_NOT_INSERT = -99; 92 93 public static final int STATUS_NO_SIM_INSERTED = 0x00; 94 public static final int STATUS_SIM1_INSERTED = 0x01; 95 public static final int STATUS_SIM2_INSERTED = 0x02; 96 public static final int STATUS_SIM3_INSERTED = 0x04; 97 public static final int STATUS_SIM4_INSERTED = 0x08; 98 99 // Key used to read/write the current IMSI. Updated on SIM_STATE_CHANGED - LOADED. 100 public static final String CURR_SUBID = "curr_subid"; 101 102 private static Phone[] mPhone; 103 private static Context mContext = null; 104 private static String mIccId[] = new String[PROJECT_SIM_NUM]; 105 private static int[] mInsertSimState = new int[PROJECT_SIM_NUM]; 106 private SubscriptionManager mSubscriptionManager = null; 107 private IPackageManager mPackageManager; 108 private UserManager mUserManager; 109 private Map<Integer, Intent> rebroadcastIntentsOnUnlock = new HashMap<>(); 110 111 // The current foreground user ID. 112 private int mCurrentlyActiveUserId; 113 private CarrierServiceBindHelper mCarrierServiceBindHelper; 114 115 public SubscriptionInfoUpdater(Context context, Phone[] phone, CommandsInterface[] ci) { 116 logd("Constructor invoked"); 117 118 mContext = context; 119 mPhone = phone; 120 mSubscriptionManager = SubscriptionManager.from(mContext); 121 mPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 122 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 123 124 IntentFilter intentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 125 intentFilter.addAction(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED); 126 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); 127 mContext.registerReceiver(sReceiver, intentFilter); 128 129 mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext); 130 initializeCarrierApps(); 131 } 132 133 private void initializeCarrierApps() { 134 // Initialize carrier apps: 135 // -Now (on system startup) 136 // -Whenever new carrier privilege rules might change (new SIM is loaded) 137 // -Whenever we switch to a new user 138 mCurrentlyActiveUserId = 0; 139 try { 140 ActivityManager.getService().registerUserSwitchObserver(new UserSwitchObserver() { 141 @Override 142 public void onUserSwitching(int newUserId, IRemoteCallback reply) 143 throws RemoteException { 144 mCurrentlyActiveUserId = newUserId; 145 CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), 146 mPackageManager, TelephonyManager.getDefault(), 147 mContext.getContentResolver(), mCurrentlyActiveUserId); 148 149 if (reply != null) { 150 try { 151 reply.sendResult(null); 152 } catch (RemoteException e) { 153 } 154 } 155 } 156 }, LOG_TAG); 157 mCurrentlyActiveUserId = ActivityManager.getService().getCurrentUser().id; 158 } catch (RemoteException e) { 159 logd("Couldn't get current user ID; guessing it's 0: " + e.getMessage()); 160 } 161 CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), 162 mPackageManager, TelephonyManager.getDefault(), mContext.getContentResolver(), 163 mCurrentlyActiveUserId); 164 } 165 166 private final BroadcastReceiver sReceiver = new BroadcastReceiver() { 167 @Override 168 public void onReceive(Context context, Intent intent) { 169 logd("[Receiver]+"); 170 String action = intent.getAction(); 171 logd("Action: " + action); 172 173 if (action.equals(Intent.ACTION_USER_UNLOCKED)) { 174 // broadcast pending intents 175 Iterator iterator = rebroadcastIntentsOnUnlock.entrySet().iterator(); 176 while (iterator.hasNext()) { 177 Map.Entry pair = (Map.Entry) iterator.next(); 178 Intent i = (Intent)pair.getValue(); 179 i.putExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, true); 180 iterator.remove(); 181 logd("Broadcasting intent ACTION_SIM_STATE_CHANGED for mCardIndex: " + 182 pair.getKey()); 183 ActivityManager.broadcastStickyIntent(i, UserHandle.USER_ALL); 184 } 185 logd("[Receiver]-"); 186 return; 187 } 188 189 if (!action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED) && 190 !action.equals(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED)) { 191 return; 192 } 193 194 int slotIndex = intent.getIntExtra(PhoneConstants.PHONE_KEY, 195 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 196 logd("slotIndex: " + slotIndex); 197 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 198 logd("ACTION_SIM_STATE_CHANGED contains invalid slotIndex: " + slotIndex); 199 return; 200 } 201 202 String simStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 203 logd("simStatus: " + simStatus); 204 205 if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 206 rebroadcastIntentsOnUnlock.put(slotIndex, intent); 207 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(simStatus)) { 208 sendMessage(obtainMessage(EVENT_SIM_ABSENT, slotIndex, -1)); 209 } else if (IccCardConstants.INTENT_VALUE_ICC_UNKNOWN.equals(simStatus)) { 210 sendMessage(obtainMessage(EVENT_SIM_UNKNOWN, slotIndex, -1)); 211 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(simStatus)) { 212 sendMessage(obtainMessage(EVENT_SIM_IO_ERROR, slotIndex, -1)); 213 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(simStatus)) { 214 sendMessage(obtainMessage(EVENT_SIM_RESTRICTED, slotIndex, -1)); 215 } else { 216 logd("Ignoring simStatus: " + simStatus); 217 } 218 } else if (action.equals(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED)) { 219 if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(simStatus)) { 220 String reason = intent.getStringExtra( 221 IccCardConstants.INTENT_KEY_LOCKED_REASON); 222 sendMessage(obtainMessage(EVENT_SIM_LOCKED, slotIndex, -1, reason)); 223 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(simStatus)) { 224 sendMessage(obtainMessage(EVENT_SIM_LOADED, slotIndex, -1)); 225 } else { 226 logd("Ignoring simStatus: " + simStatus); 227 } 228 } 229 logd("[Receiver]-"); 230 } 231 }; 232 233 private boolean isAllIccIdQueryDone() { 234 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 235 if (mIccId[i] == null) { 236 logd("Wait for SIM" + (i + 1) + " IccId"); 237 return false; 238 } 239 } 240 logd("All IccIds query complete"); 241 242 return true; 243 } 244 245 public void setDisplayNameForNewSub(String newSubName, int subId, int newNameSource) { 246 SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId); 247 if (subInfo != null) { 248 // overwrite SIM display name if it is not assigned by user 249 int oldNameSource = subInfo.getNameSource(); 250 CharSequence oldSubName = subInfo.getDisplayName(); 251 logd("[setDisplayNameForNewSub] subId = " + subInfo.getSubscriptionId() 252 + ", oldSimName = " + oldSubName + ", oldNameSource = " + oldNameSource 253 + ", newSubName = " + newSubName + ", newNameSource = " + newNameSource); 254 if (oldSubName == null || 255 (oldNameSource == 256 SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE && newSubName != null) || 257 (oldNameSource == SubscriptionManager.NAME_SOURCE_SIM_SOURCE && newSubName != null 258 && !newSubName.equals(oldSubName))) { 259 mSubscriptionManager.setDisplayName(newSubName, subInfo.getSubscriptionId(), 260 newNameSource); 261 } 262 } else { 263 logd("SUB" + (subId + 1) + " SubInfo not created yet"); 264 } 265 } 266 267 @Override 268 public void handleMessage(Message msg) { 269 switch (msg.what) { 270 case EVENT_SIM_LOCKED_QUERY_ICCID_DONE: { 271 AsyncResult ar = (AsyncResult)msg.obj; 272 QueryIccIdUserObj uObj = (QueryIccIdUserObj) ar.userObj; 273 int slotId = uObj.slotId; 274 logd("handleMessage : <EVENT_SIM_LOCKED_QUERY_ICCID_DONE> SIM" + (slotId + 1)); 275 if (ar.exception == null) { 276 if (ar.result != null) { 277 byte[] data = (byte[])ar.result; 278 mIccId[slotId] = IccUtils.bcdToString(data, 0, data.length); 279 } else { 280 logd("Null ar"); 281 mIccId[slotId] = ICCID_STRING_FOR_NO_SIM; 282 } 283 } else { 284 mIccId[slotId] = ICCID_STRING_FOR_NO_SIM; 285 logd("Query IccId fail: " + ar.exception); 286 } 287 logd("sIccId[" + slotId + "] = " + mIccId[slotId]); 288 if (isAllIccIdQueryDone()) { 289 updateSubscriptionInfoByIccId(); 290 } 291 broadcastSimStateChanged(slotId, IccCardConstants.INTENT_VALUE_ICC_LOCKED, 292 uObj.reason); 293 if (!ICCID_STRING_FOR_NO_SIM.equals(mIccId[slotId])) { 294 updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_LOCKED); 295 } 296 break; 297 } 298 299 case EVENT_GET_NETWORK_SELECTION_MODE_DONE: { 300 AsyncResult ar = (AsyncResult)msg.obj; 301 Integer slotId = (Integer)ar.userObj; 302 if (ar.exception == null && ar.result != null) { 303 int[] modes = (int[])ar.result; 304 if (modes[0] == 1) { // Manual mode. 305 mPhone[slotId].setNetworkSelectionModeAutomatic(null); 306 } 307 } else { 308 logd("EVENT_GET_NETWORK_SELECTION_MODE_DONE: error getting network mode."); 309 } 310 break; 311 } 312 313 case EVENT_SIM_LOADED: 314 handleSimLoaded(msg.arg1); 315 break; 316 317 case EVENT_SIM_ABSENT: 318 handleSimAbsent(msg.arg1); 319 break; 320 321 case EVENT_SIM_LOCKED: 322 handleSimLocked(msg.arg1, (String) msg.obj); 323 break; 324 325 case EVENT_SIM_UNKNOWN: 326 updateCarrierServices(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 327 break; 328 329 case EVENT_SIM_IO_ERROR: 330 handleSimError(msg.arg1); 331 break; 332 333 case EVENT_SIM_RESTRICTED: 334 updateCarrierServices(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED); 335 break; 336 337 default: 338 logd("Unknown msg:" + msg.what); 339 } 340 } 341 342 private static class QueryIccIdUserObj { 343 public String reason; 344 public int slotId; 345 346 QueryIccIdUserObj(String reason, int slotId) { 347 this.reason = reason; 348 this.slotId = slotId; 349 } 350 }; 351 352 private void handleSimLocked(int slotId, String reason) { 353 if (mIccId[slotId] != null && mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) { 354 logd("SIM" + (slotId + 1) + " hot plug in"); 355 mIccId[slotId] = null; 356 } 357 358 359 IccFileHandler fileHandler = mPhone[slotId].getIccCard() == null ? null : 360 mPhone[slotId].getIccCard().getIccFileHandler(); 361 362 if (fileHandler != null) { 363 String iccId = mIccId[slotId]; 364 if (iccId == null) { 365 logd("Querying IccId"); 366 fileHandler.loadEFTransparent(IccConstants.EF_ICCID, 367 obtainMessage(EVENT_SIM_LOCKED_QUERY_ICCID_DONE, 368 new QueryIccIdUserObj(reason, slotId))); 369 } else { 370 logd("NOT Querying IccId its already set sIccid[" + slotId + "]=" + iccId); 371 updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_LOCKED); 372 broadcastSimStateChanged(slotId, IccCardConstants.INTENT_VALUE_ICC_LOCKED, reason); 373 } 374 } else { 375 logd("sFh[" + slotId + "] is null, ignore"); 376 } 377 } 378 379 private void handleSimLoaded(int slotId) { 380 logd("handleSimStateLoadedInternal: slotId: " + slotId); 381 382 // The SIM should be loaded at this state, but it is possible in cases such as SIM being 383 // removed or a refresh RESET that the IccRecords could be null. The right behavior is to 384 // not broadcast the SIM loaded. 385 IccRecords records = mPhone[slotId].getIccCard().getIccRecords(); 386 if (records == null) { // Possibly a race condition. 387 logd("onRecieve: IccRecords null"); 388 return; 389 } 390 if (records.getIccId() == null) { 391 logd("onRecieve: IccID null"); 392 return; 393 } 394 mIccId[slotId] = records.getIccId(); 395 396 if (isAllIccIdQueryDone()) { 397 updateSubscriptionInfoByIccId(); 398 int[] subIds = mSubscriptionManager.getActiveSubscriptionIdList(); 399 for (int subId : subIds) { 400 TelephonyManager tm = TelephonyManager.getDefault(); 401 402 String operator = tm.getSimOperatorNumeric(subId); 403 slotId = SubscriptionController.getInstance().getPhoneId(subId); 404 405 if (!TextUtils.isEmpty(operator)) { 406 if (subId == SubscriptionController.getInstance().getDefaultSubId()) { 407 MccTable.updateMccMncConfiguration(mContext, operator, false); 408 } 409 SubscriptionController.getInstance().setMccMnc(operator, subId); 410 } else { 411 logd("EVENT_RECORDS_LOADED Operator name is null"); 412 } 413 414 String msisdn = tm.getLine1Number(subId); 415 ContentResolver contentResolver = mContext.getContentResolver(); 416 417 if (msisdn != null) { 418 ContentValues number = new ContentValues(1); 419 number.put(SubscriptionManager.NUMBER, msisdn); 420 contentResolver.update(SubscriptionManager.CONTENT_URI, number, 421 SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" 422 + Long.toString(subId), null); 423 } 424 425 SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId); 426 String nameToSet; 427 String simCarrierName = tm.getSimOperatorName(subId); 428 ContentValues name = new ContentValues(1); 429 430 if (subInfo != null && subInfo.getNameSource() != 431 SubscriptionManager.NAME_SOURCE_USER_INPUT) { 432 if (!TextUtils.isEmpty(simCarrierName)) { 433 nameToSet = simCarrierName; 434 } else { 435 nameToSet = "CARD " + Integer.toString(slotId + 1); 436 } 437 name.put(SubscriptionManager.DISPLAY_NAME, nameToSet); 438 logd("sim name = " + nameToSet); 439 contentResolver.update(SubscriptionManager.CONTENT_URI, name, 440 SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID 441 + "=" + Long.toString(subId), null); 442 } 443 444 /* Update preferred network type and network selection mode on SIM change. 445 * Storing last subId in SharedPreference for now to detect SIM change. */ 446 SharedPreferences sp = 447 PreferenceManager.getDefaultSharedPreferences(mContext); 448 int storedSubId = sp.getInt(CURR_SUBID + slotId, -1); 449 450 if (storedSubId != subId) { 451 int networkType = RILConstants.PREFERRED_NETWORK_MODE; 452 453 // Set the modem network mode 454 mPhone[slotId].setPreferredNetworkType(networkType, null); 455 Settings.Global.putInt(mPhone[slotId].getContext().getContentResolver(), 456 Settings.Global.PREFERRED_NETWORK_MODE + subId, 457 networkType); 458 459 // Only support automatic selection mode on SIM change. 460 mPhone[slotId].getNetworkSelectionMode( 461 obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, 462 new Integer(slotId))); 463 464 // Update stored subId 465 SharedPreferences.Editor editor = sp.edit(); 466 editor.putInt(CURR_SUBID + slotId, subId); 467 editor.apply(); 468 } 469 470 // Update set of enabled carrier apps now that the privilege rules may have changed. 471 CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), 472 mPackageManager, TelephonyManager.getDefault(), 473 mContext.getContentResolver(), mCurrentlyActiveUserId); 474 475 broadcastSimStateChanged(slotId, IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 476 updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_LOADED); 477 } 478 } 479 } 480 481 private void updateCarrierServices(int slotId, String simState) { 482 CarrierConfigManager configManager = (CarrierConfigManager) 483 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 484 configManager.updateConfigForPhoneId(slotId, simState); 485 mCarrierServiceBindHelper.updateForPhoneId(slotId, simState); 486 } 487 488 private void handleSimAbsent(int slotId) { 489 if (mIccId[slotId] != null && !mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) { 490 logd("SIM" + (slotId + 1) + " hot plug out"); 491 } 492 mIccId[slotId] = ICCID_STRING_FOR_NO_SIM; 493 if (isAllIccIdQueryDone()) { 494 updateSubscriptionInfoByIccId(); 495 } 496 updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_ABSENT); 497 } 498 499 private void handleSimError(int slotId) { 500 if (mIccId[slotId] != null && !mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) { 501 logd("SIM" + (slotId + 1) + " Error "); 502 } 503 mIccId[slotId] = ICCID_STRING_FOR_NO_SIM; 504 if (isAllIccIdQueryDone()) { 505 updateSubscriptionInfoByIccId(); 506 } 507 updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 508 } 509 510 /** 511 * TODO: Simplify more, as no one is interested in what happened 512 * only what the current list contains. 513 */ 514 synchronized private void updateSubscriptionInfoByIccId() { 515 logd("updateSubscriptionInfoByIccId:+ Start"); 516 517 mSubscriptionManager.clearSubscriptionInfo(); 518 519 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 520 mInsertSimState[i] = SIM_NOT_CHANGE; 521 } 522 523 int insertedSimCount = PROJECT_SIM_NUM; 524 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 525 if (ICCID_STRING_FOR_NO_SIM.equals(mIccId[i])) { 526 insertedSimCount--; 527 mInsertSimState[i] = SIM_NOT_INSERT; 528 } 529 } 530 logd("insertedSimCount = " + insertedSimCount); 531 532 int index = 0; 533 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 534 if (mInsertSimState[i] == SIM_NOT_INSERT) { 535 continue; 536 } 537 index = 2; 538 for (int j = i + 1; j < PROJECT_SIM_NUM; j++) { 539 if (mInsertSimState[j] == SIM_NOT_CHANGE && mIccId[i].equals(mIccId[j])) { 540 mInsertSimState[i] = 1; 541 mInsertSimState[j] = index; 542 index++; 543 } 544 } 545 } 546 547 ContentResolver contentResolver = mContext.getContentResolver(); 548 String[] oldIccId = new String[PROJECT_SIM_NUM]; 549 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 550 oldIccId[i] = null; 551 List<SubscriptionInfo> oldSubInfo = 552 SubscriptionController.getInstance().getSubInfoUsingSlotIndexWithCheck(i, false, 553 mContext.getOpPackageName()); 554 if (oldSubInfo != null && oldSubInfo.size() > 0) { 555 oldIccId[i] = oldSubInfo.get(0).getIccId(); 556 logd("updateSubscriptionInfoByIccId: oldSubId = " 557 + oldSubInfo.get(0).getSubscriptionId()); 558 if (mInsertSimState[i] == SIM_NOT_CHANGE && !mIccId[i].equals(oldIccId[i])) { 559 mInsertSimState[i] = SIM_CHANGED; 560 } 561 if (mInsertSimState[i] != SIM_NOT_CHANGE) { 562 ContentValues value = new ContentValues(1); 563 value.put(SubscriptionManager.SIM_SLOT_INDEX, 564 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 565 contentResolver.update(SubscriptionManager.CONTENT_URI, value, 566 SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" 567 + Integer.toString(oldSubInfo.get(0).getSubscriptionId()), null); 568 } 569 } else { 570 if (mInsertSimState[i] == SIM_NOT_CHANGE) { 571 // no SIM inserted last time, but there is one SIM inserted now 572 mInsertSimState[i] = SIM_CHANGED; 573 } 574 oldIccId[i] = ICCID_STRING_FOR_NO_SIM; 575 logd("updateSubscriptionInfoByIccId: No SIM in slot " + i + " last time"); 576 } 577 } 578 579 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 580 logd("updateSubscriptionInfoByIccId: oldIccId[" + i + "] = " + oldIccId[i] + 581 ", sIccId[" + i + "] = " + mIccId[i]); 582 } 583 584 //check if the inserted SIM is new SIM 585 int nNewCardCount = 0; 586 int nNewSimStatus = 0; 587 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 588 if (mInsertSimState[i] == SIM_NOT_INSERT) { 589 logd("updateSubscriptionInfoByIccId: No SIM inserted in slot " + i + " this time"); 590 } else { 591 if (mInsertSimState[i] > 0) { 592 //some special SIMs may have the same IccIds, add suffix to distinguish them 593 //FIXME: addSubInfoRecord can return an error. 594 mSubscriptionManager.addSubscriptionInfoRecord(mIccId[i] 595 + Integer.toString(mInsertSimState[i]), i); 596 logd("SUB" + (i + 1) + " has invalid IccId"); 597 } else /*if (sInsertSimState[i] != SIM_NOT_INSERT)*/ { 598 mSubscriptionManager.addSubscriptionInfoRecord(mIccId[i], i); 599 } 600 if (isNewSim(mIccId[i], oldIccId)) { 601 nNewCardCount++; 602 switch (i) { 603 case PhoneConstants.SUB1: 604 nNewSimStatus |= STATUS_SIM1_INSERTED; 605 break; 606 case PhoneConstants.SUB2: 607 nNewSimStatus |= STATUS_SIM2_INSERTED; 608 break; 609 case PhoneConstants.SUB3: 610 nNewSimStatus |= STATUS_SIM3_INSERTED; 611 break; 612 //case PhoneConstants.SUB3: 613 // nNewSimStatus |= STATUS_SIM4_INSERTED; 614 // break; 615 } 616 617 mInsertSimState[i] = SIM_NEW; 618 } 619 } 620 } 621 622 for (int i = 0; i < PROJECT_SIM_NUM; i++) { 623 if (mInsertSimState[i] == SIM_CHANGED) { 624 mInsertSimState[i] = SIM_REPOSITION; 625 } 626 logd("updateSubscriptionInfoByIccId: sInsertSimState[" + i + "] = " 627 + mInsertSimState[i]); 628 } 629 630 List<SubscriptionInfo> subInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); 631 int nSubCount = (subInfos == null) ? 0 : subInfos.size(); 632 logd("updateSubscriptionInfoByIccId: nSubCount = " + nSubCount); 633 for (int i=0; i < nSubCount; i++) { 634 SubscriptionInfo temp = subInfos.get(i); 635 636 String msisdn = TelephonyManager.getDefault().getLine1Number( 637 temp.getSubscriptionId()); 638 639 if (msisdn != null) { 640 ContentValues value = new ContentValues(1); 641 value.put(SubscriptionManager.NUMBER, msisdn); 642 contentResolver.update(SubscriptionManager.CONTENT_URI, value, 643 SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" 644 + Integer.toString(temp.getSubscriptionId()), null); 645 } 646 } 647 648 // Ensure the modems are mapped correctly 649 mSubscriptionManager.setDefaultDataSubId( 650 mSubscriptionManager.getDefaultDataSubscriptionId()); 651 652 SubscriptionController.getInstance().notifySubscriptionInfoChanged(); 653 logd("updateSubscriptionInfoByIccId:- SsubscriptionInfo update complete"); 654 } 655 656 private boolean isNewSim(String iccId, String[] oldIccId) { 657 boolean newSim = true; 658 for(int i = 0; i < PROJECT_SIM_NUM; i++) { 659 if(iccId.equals(oldIccId[i])) { 660 newSim = false; 661 break; 662 } 663 } 664 logd("newSim = " + newSim); 665 666 return newSim; 667 } 668 669 private void broadcastSimStateChanged(int slotId, String state, String reason) { 670 Intent i = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 671 // TODO - we'd like this intent to have a single snapshot of all sim state, 672 // but until then this should not use REPLACE_PENDING or we may lose 673 // information 674 // i.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 675 // | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 676 i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 677 i.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 678 i.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state); 679 i.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 680 SubscriptionManager.putPhoneIdAndSubIdExtra(i, slotId); 681 logd("Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason " + reason + 682 " for mCardIndex: " + slotId); 683 ActivityManager.broadcastStickyIntent(i, UserHandle.USER_ALL); 684 rebroadcastIntentsOnUnlock.put(slotId, i); 685 } 686 687 public void dispose() { 688 logd("[dispose]"); 689 mContext.unregisterReceiver(sReceiver); 690 } 691 692 private void logd(String message) { 693 Rlog.d(LOG_TAG, message); 694 } 695 696 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 697 pw.println("SubscriptionInfoUpdater:"); 698 mCarrierServiceBindHelper.dump(fd, pw, args); 699 } 700} 701