• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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