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