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