Home | History | Annotate | Download | only in telephony
      1 /*
      2 * Copyright (C) 2011-2014 MediaTek Inc.
      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 static android.Manifest.permission.READ_PHONE_STATE;
     20 import android.app.ActivityManagerNative;
     21 import android.content.BroadcastReceiver;
     22 import android.content.Context;
     23 import android.content.ContentResolver;
     24 import android.content.ContentValues;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.os.AsyncResult;
     28 import android.os.Handler;
     29 import android.os.Message;
     30 import android.os.UserHandle;
     31 import android.telephony.Rlog;
     32 import android.telephony.SubscriptionManager;
     33 import android.telephony.SubInfoRecord;
     34 import android.telephony.TelephonyManager;
     35 import com.android.internal.telephony.CommandsInterface;
     36 import com.android.internal.telephony.IccCardConstants;
     37 import com.android.internal.telephony.Phone;
     38 import com.android.internal.telephony.PhoneConstants;
     39 import com.android.internal.telephony.PhoneProxy;
     40 import com.android.internal.telephony.TelephonyIntents;
     41 import com.android.internal.telephony.uicc.IccConstants;
     42 import com.android.internal.telephony.uicc.IccFileHandler;
     43 import com.android.internal.telephony.uicc.IccUtils;
     44 import com.android.internal.telephony.uicc.SpnOverride;
     45 
     46 import java.util.List;
     47 
     48 /**
     49  *@hide
     50  */
     51 public class SubInfoRecordUpdater extends Handler {
     52     private static final String LOG_TAG = "SUB";
     53     private static final int PROJECT_SIM_NUM = TelephonyManager.getDefault().getPhoneCount();
     54     private static final int EVENT_OFFSET = 8;
     55     private static final int EVENT_QUERY_ICCID_DONE = 1;
     56     private static final String ICCID_STRING_FOR_NO_SIM = "";
     57     /**
     58      *  int[] sInsertSimState maintains all slots' SIM inserted status currently,
     59      *  it may contain 4 kinds of values:
     60      *    SIM_NOT_INSERT : no SIM inserted in slot i now
     61      *    SIM_CHANGED    : a valid SIM insert in slot i and is different SIM from last time
     62      *                     it will later become SIM_NEW or SIM_REPOSITION during update procedure
     63      *    SIM_NOT_CHANGE : a valid SIM insert in slot i and is the same SIM as last time
     64      *    SIM_NEW        : a valid SIM insert in slot i and is a new SIM
     65      *    SIM_REPOSITION : a valid SIM insert in slot i and is inserted in different slot last time
     66      *    positive integer #: index to distinguish SIM cards with the same IccId
     67      */
     68     public static final int SIM_NOT_CHANGE = 0;
     69     public static final int SIM_CHANGED    = -1;
     70     public static final int SIM_NEW        = -2;
     71     public static final int SIM_REPOSITION = -3;
     72     public static final int SIM_NOT_INSERT = -99;
     73 
     74     public static final int STATUS_NO_SIM_INSERTED = 0x00;
     75     public static final int STATUS_SIM1_INSERTED = 0x01;
     76     public static final int STATUS_SIM2_INSERTED = 0x02;
     77     public static final int STATUS_SIM3_INSERTED = 0x04;
     78     public static final int STATUS_SIM4_INSERTED = 0x08;
     79 
     80     private static Phone[] sPhone;
     81     private static Context sContext = null;
     82     private static IccFileHandler[] sFh = new IccFileHandler[PROJECT_SIM_NUM];
     83     private static String sIccId[] = new String[PROJECT_SIM_NUM];
     84     private static int[] sInsertSimState = new int[PROJECT_SIM_NUM];
     85     private static TelephonyManager sTelephonyMgr = null;
     86     // To prevent repeatedly update flow every time receiver SIM_STATE_CHANGE
     87     private static boolean sNeedUpdate = true;
     88 
     89     public SubInfoRecordUpdater(Context context, Phone[] phoneProxy, CommandsInterface[] ci) {
     90         logd("Constructor invoked");
     91 
     92         sContext = context;
     93         sPhone = phoneProxy;
     94         IntentFilter intentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
     95         sContext.registerReceiver(sReceiver, intentFilter);
     96     }
     97 
     98     private static int encodeEventId(int event, int slotId) {
     99         return event << (slotId * EVENT_OFFSET);
    100     }
    101 
    102     private final BroadcastReceiver sReceiver = new  BroadcastReceiver() {
    103         @Override
    104         public void onReceive(Context context, Intent intent) {
    105             logd("[Receiver]+");
    106             String action = intent.getAction();
    107             int slotId;
    108             logd("Action: " + action);
    109             if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
    110                 String simStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
    111                 slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY,
    112                         SubscriptionManager.INVALID_SLOT_ID);
    113                 logd("slotId: " + slotId + " simStatus: " + simStatus);
    114                 if (slotId == SubscriptionManager.INVALID_SLOT_ID) {
    115                     return;
    116                 }
    117                 if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(simStatus)
    118                         || IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(simStatus)) {
    119                     if (sIccId[slotId] != null && sIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) {
    120                         logd("SIM" + (slotId + 1) + " hot plug in");
    121                         sIccId[slotId] = null;
    122                         sNeedUpdate = true;
    123                     }
    124                     queryIccId(slotId);
    125                 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(simStatus)) {
    126                     queryIccId(slotId);
    127                     if (sTelephonyMgr == null) {
    128                         sTelephonyMgr = TelephonyManager.from(sContext);
    129                     }
    130 
    131                     long subId = intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY,
    132                             SubscriptionManager.INVALID_SUB_ID);
    133 
    134                     if (SubscriptionManager.isValidSubId(subId)) {
    135                         String msisdn = TelephonyManager.getDefault().getLine1NumberForSubscriber(subId);
    136                         ContentResolver contentResolver = sContext.getContentResolver();
    137 
    138                         if (msisdn != null) {
    139                             ContentValues number = new ContentValues(1);
    140                             number.put(SubscriptionManager.NUMBER, msisdn);
    141                             contentResolver.update(SubscriptionManager.CONTENT_URI, number,
    142                                     SubscriptionManager._ID + "=" + Long.toString(subId), null);
    143                         }
    144 
    145                         SubInfoRecord subInfo =
    146                                 SubscriptionManager.getSubInfoForSubscriber(subId);
    147 
    148                         if (subInfo != null
    149                                 && subInfo.nameSource != SubscriptionManager.NAME_SOURCE_USER_INPUT) {
    150                             SpnOverride mSpnOverride = new SpnOverride();
    151                             String nameToSet;
    152                             String CarrierName =
    153                                     TelephonyManager.getDefault().getSimOperator(subId);
    154                             logd("CarrierName = " + CarrierName);
    155 
    156                             if (mSpnOverride.containsCarrier(CarrierName)) {
    157                                 nameToSet = mSpnOverride.getSpn(CarrierName) + " 0"
    158                                         + Integer.toString(slotId + 1);
    159                                 logd("Found, name = " + nameToSet);
    160                             } else {
    161                                 nameToSet = "SUB 0" + Integer.toString(slotId + 1);
    162                                 logd("Not found, name = " + nameToSet);
    163                             }
    164 
    165                             ContentValues name = new ContentValues(1);
    166                             name.put(SubscriptionManager.DISPLAY_NAME, nameToSet);
    167                             contentResolver.update(SubscriptionManager.CONTENT_URI, name,
    168                                     SubscriptionManager._ID + "=" + Long.toString(subId), null);
    169                         }
    170                     } else {
    171                         logd("[Receiver] Invalid subId, could not update ContentResolver");
    172                     }
    173                 } else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(simStatus)) {
    174                     if (sIccId[slotId] != null && !sIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) {
    175                         logd("SIM" + (slotId + 1) + " hot plug out");
    176                         sNeedUpdate = true;
    177                     }
    178                     sFh[slotId] = null;
    179                     sIccId[slotId] = ICCID_STRING_FOR_NO_SIM;
    180                     if (isAllIccIdQueryDone() && sNeedUpdate) {
    181                         updateSimInfoByIccId();
    182                     }
    183                 }
    184             }
    185             logd("[Receiver]-");
    186         }
    187     };
    188 
    189     private boolean isAllIccIdQueryDone() {
    190         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    191             if (sIccId[i] == null) {
    192                 logd("Wait for SIM" + (i + 1) + " IccId");
    193                 return false;
    194             }
    195         }
    196         logd("All IccIds query complete");
    197 
    198         return true;
    199     }
    200 
    201     public static void setDisplayNameForNewSub(String newSubName, int subId, int newNameSource) {
    202         SubInfoRecord subInfo = SubscriptionManager.getSubInfoForSubscriber(subId);
    203         if (subInfo != null) {
    204             // overwrite SIM display name if it is not assigned by user
    205             int oldNameSource = subInfo.nameSource;
    206             String oldSubName = subInfo.displayName;
    207             logd("[setDisplayNameForNewSub] mSubInfoIdx = " + subInfo.subId + ", oldSimName = "
    208                     + oldSubName + ", oldNameSource = " + oldNameSource + ", newSubName = "
    209                     + newSubName + ", newNameSource = " + newNameSource);
    210             if (oldSubName == null ||
    211                 (oldNameSource == SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE && newSubName != null) ||
    212                 (oldNameSource == SubscriptionManager.NAME_SOURCE_SIM_SOURCE && newSubName != null
    213                         && !newSubName.equals(oldSubName))) {
    214                 SubscriptionManager.setDisplayName(newSubName,
    215                         subInfo.subId, newNameSource);
    216             }
    217         } else {
    218             logd("SUB" + (subId + 1) + " SubInfo not created yet");
    219         }
    220     }
    221 
    222     @Override
    223     public void handleMessage(Message msg) {
    224         AsyncResult ar = (AsyncResult)msg.obj;
    225         int msgNum = msg.what;
    226         int slotId;
    227         for (slotId = PhoneConstants.SUB1; slotId <= PhoneConstants.SUB3; slotId++) {
    228             int pivot = 1 << (slotId * EVENT_OFFSET);
    229             if (msgNum >= pivot) {
    230                 continue;
    231             } else {
    232                 break;
    233             }
    234         }
    235         slotId--;
    236         int event = msgNum >> (slotId * EVENT_OFFSET);
    237         switch (event) {
    238             case EVENT_QUERY_ICCID_DONE:
    239                 logd("handleMessage : <EVENT_QUERY_ICCID_DONE> SIM" + (slotId + 1));
    240                 if (ar.exception == null) {
    241                     if (ar.result != null) {
    242                         byte[] data = (byte[])ar.result;
    243                         sIccId[slotId] = IccUtils.bcdToString(data, 0, data.length);
    244                     } else {
    245                         logd("Null ar");
    246                         sIccId[slotId] = ICCID_STRING_FOR_NO_SIM;
    247                     }
    248                 } else {
    249                     sIccId[slotId] = ICCID_STRING_FOR_NO_SIM;
    250                     logd("Query IccId fail: " + ar.exception);
    251                 }
    252                 logd("sIccId[" + slotId + "] = " + sIccId[slotId]);
    253                 if (isAllIccIdQueryDone() && sNeedUpdate) {
    254                     updateSimInfoByIccId();
    255                 }
    256                 break;
    257             default:
    258                 logd("Unknown msg:" + msg.what);
    259         }
    260     }
    261 
    262     private void queryIccId(int slotId) {
    263         logd("queryIccId: slotid=" + slotId);
    264         if (sFh[slotId] == null) {
    265             logd("Getting IccFileHandler");
    266             sFh[slotId] = ((PhoneProxy)sPhone[slotId]).getIccFileHandler();
    267         }
    268         if (sFh[slotId] != null) {
    269             String iccId = sIccId[slotId];
    270             if (iccId == null) {
    271                 logd("Querying IccId");
    272                 sFh[slotId].loadEFTransparent(IccConstants.EF_ICCID, obtainMessage(encodeEventId(EVENT_QUERY_ICCID_DONE, slotId)));
    273             } else {
    274                 logd("NOT Querying IccId its already set sIccid[" + slotId + "]=" + iccId);
    275             }
    276         } else {
    277             logd("sFh[" + slotId + "] is null, ignore");
    278         }
    279     }
    280 
    281     synchronized public void updateSimInfoByIccId() {
    282         logd("[updateSimInfoByIccId]+ Start");
    283         sNeedUpdate = false;
    284 
    285         SubscriptionManager.clearSubInfo();
    286 
    287         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    288             sInsertSimState[i] = SIM_NOT_CHANGE;
    289         }
    290 
    291         int insertedSimCount = PROJECT_SIM_NUM;
    292         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    293             if (ICCID_STRING_FOR_NO_SIM.equals(sIccId[i])) {
    294                 insertedSimCount--;
    295                 sInsertSimState[i] = SIM_NOT_INSERT;
    296             }
    297         }
    298         logd("insertedSimCount = " + insertedSimCount);
    299 
    300         int index = 0;
    301         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    302             if (sInsertSimState[i] == SIM_NOT_INSERT) {
    303                 continue;
    304             }
    305             index = 2;
    306             for (int j = i + 1; j < PROJECT_SIM_NUM; j++) {
    307                 if (sInsertSimState[j] == SIM_NOT_CHANGE && sIccId[i].equals(sIccId[j])) {
    308                     sInsertSimState[i] = 1;
    309                     sInsertSimState[j] = index;
    310                     index++;
    311                 }
    312             }
    313         }
    314 
    315         ContentResolver contentResolver = sContext.getContentResolver();
    316         String[] oldIccId = new String[PROJECT_SIM_NUM];
    317         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    318             oldIccId[i] = null;
    319             List<SubInfoRecord> oldSubInfo =
    320                     SubscriptionController.getInstance().getSubInfoUsingSlotIdWithCheck(i, false);
    321             if (oldSubInfo != null) {
    322                 oldIccId[i] = oldSubInfo.get(0).iccId;
    323                 logd("oldSubId = " + oldSubInfo.get(0).subId);
    324                 if (sInsertSimState[i] == SIM_NOT_CHANGE && !sIccId[i].equals(oldIccId[i])) {
    325                     sInsertSimState[i] = SIM_CHANGED;
    326                 }
    327                 if (sInsertSimState[i] != SIM_NOT_CHANGE) {
    328                     ContentValues value = new ContentValues(1);
    329                     value.put(SubscriptionManager.SIM_ID, SubscriptionManager.INVALID_SLOT_ID);
    330                     contentResolver.update(SubscriptionManager.CONTENT_URI, value,
    331                             SubscriptionManager._ID + "="
    332                             + Long.toString(oldSubInfo.get(0).subId), null);
    333                 }
    334             } else {
    335                 if (sInsertSimState[i] == SIM_NOT_CHANGE) {
    336                     // no SIM inserted last time, but there is one SIM inserted now
    337                     sInsertSimState[i] = SIM_CHANGED;
    338                 }
    339                 oldIccId[i] = ICCID_STRING_FOR_NO_SIM;
    340                 logd("No SIM in slot " + i + " last time");
    341             }
    342         }
    343 
    344         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    345             logd("oldIccId[" + i + "] = " + oldIccId[i] + ", sIccId[" + i + "] = " + sIccId[i]);
    346         }
    347 
    348         //check if the inserted SIM is new SIM
    349         int nNewCardCount = 0;
    350         int nNewSimStatus = 0;
    351         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    352             if (sInsertSimState[i] == SIM_NOT_INSERT) {
    353                 logd("No SIM inserted in slot " + i + " this time");
    354             } else {
    355                 if (sInsertSimState[i] > 0) {
    356                     //some special SIMs may have the same IccIds, add suffix to distinguish them
    357                     //FIXME: addSubInfoRecord can return an error.
    358                     SubscriptionManager.addSubInfoRecord(sIccId[i]
    359                             + Integer.toString(sInsertSimState[i]), i);
    360                     logd("SUB" + (i + 1) + " has invalid IccId");
    361                 } else /*if (sInsertSimState[i] != SIM_NOT_INSERT)*/ {
    362                     SubscriptionManager.addSubInfoRecord(sIccId[i], i);
    363                 }
    364                 if (isNewSim(sIccId[i], oldIccId)) {
    365                     nNewCardCount++;
    366                     switch (i) {
    367                         case PhoneConstants.SUB1:
    368                             nNewSimStatus |= STATUS_SIM1_INSERTED;
    369                             break;
    370                         case PhoneConstants.SUB2:
    371                             nNewSimStatus |= STATUS_SIM2_INSERTED;
    372                             break;
    373                         case PhoneConstants.SUB3:
    374                             nNewSimStatus |= STATUS_SIM3_INSERTED;
    375                             break;
    376                         //case PhoneConstants.SUB3:
    377                         //    nNewSimStatus |= STATUS_SIM4_INSERTED;
    378                         //    break;
    379                     }
    380 
    381                     sInsertSimState[i] = SIM_NEW;
    382                 }
    383             }
    384         }
    385 
    386         for (int i = 0; i < PROJECT_SIM_NUM; i++) {
    387             if (sInsertSimState[i] == SIM_CHANGED) {
    388                 sInsertSimState[i] = SIM_REPOSITION;
    389             }
    390             logd("sInsertSimState[" + i + "] = " + sInsertSimState[i]);
    391         }
    392 
    393         List<SubInfoRecord> subInfos = SubscriptionManager.getActiveSubInfoList();
    394         int nSubCount = (subInfos == null) ? 0 : subInfos.size();
    395         logd("nSubCount = " + nSubCount);
    396         for (int i=0; i<nSubCount; i++) {
    397             SubInfoRecord temp = subInfos.get(i);
    398 
    399             String msisdn = TelephonyManager.getDefault().getLine1NumberForSubscriber(temp.subId);
    400 
    401             if (msisdn != null) {
    402                 ContentValues value = new ContentValues(1);
    403                 value.put(SubscriptionManager.NUMBER, msisdn);
    404                 contentResolver.update(SubscriptionManager.CONTENT_URI, value,
    405                         SubscriptionManager._ID + "=" + Long.toString(temp.subId), null);
    406             }
    407         }
    408 
    409         // true if any slot has no SIM this time, but has SIM last time
    410         boolean hasSimRemoved = false;
    411         for (int i=0; i < PROJECT_SIM_NUM; i++) {
    412             if (sIccId[i] != null && sIccId[i].equals(ICCID_STRING_FOR_NO_SIM)
    413                     && !oldIccId[i].equals("")) {
    414                 hasSimRemoved = true;
    415                 break;
    416             }
    417         }
    418 
    419         if (nNewCardCount == 0) {
    420             int i;
    421             if (hasSimRemoved) {
    422                 // no new SIM, at least one SIM is removed, check if any SIM is repositioned first
    423                 for (i=0; i < PROJECT_SIM_NUM; i++) {
    424                     if (sInsertSimState[i] == SIM_REPOSITION) {
    425                         logd("No new SIM detected and SIM repositioned");
    426                         setUpdatedData(SubscriptionManager.EXTRA_VALUE_REPOSITION_SIM,
    427                                 nSubCount, nNewSimStatus);
    428                         break;
    429                     }
    430                 }
    431                 if (i == PROJECT_SIM_NUM) {
    432                     // no new SIM, no SIM is repositioned => at least one SIM is removed
    433                     logd("No new SIM detected and SIM removed");
    434                     setUpdatedData(SubscriptionManager.EXTRA_VALUE_REMOVE_SIM,
    435                             nSubCount, nNewSimStatus);
    436                 }
    437             } else {
    438                 // no SIM is removed, no new SIM, just check if any SIM is repositioned
    439                 for (i=0; i< PROJECT_SIM_NUM; i++) {
    440                     if (sInsertSimState[i] == SIM_REPOSITION) {
    441                         logd("No new SIM detected and SIM repositioned");
    442                         setUpdatedData(SubscriptionManager.EXTRA_VALUE_REPOSITION_SIM,
    443                                 nSubCount, nNewSimStatus);
    444                         break;
    445                     }
    446                 }
    447                 if (i == PROJECT_SIM_NUM) {
    448                     // all status remain unchanged
    449                     logd("[updateSimInfoByIccId] All SIM inserted into the same slot");
    450                     setUpdatedData(SubscriptionManager.EXTRA_VALUE_NOCHANGE,
    451                             nSubCount, nNewSimStatus);
    452                 }
    453             }
    454         } else {
    455             logd("New SIM detected");
    456             setUpdatedData(SubscriptionManager.EXTRA_VALUE_NEW_SIM, nSubCount, nNewSimStatus);
    457         }
    458 
    459         logd("[updateSimInfoByIccId]- SimInfo update complete");
    460     }
    461 
    462     private static void setUpdatedData(int detectedType, int subCount, int newSimStatus) {
    463 
    464         Intent intent = new Intent(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
    465 
    466         logd("[setUpdatedData]+ ");
    467 
    468         if (detectedType == SubscriptionManager.EXTRA_VALUE_NEW_SIM ) {
    469             intent.putExtra(SubscriptionManager.INTENT_KEY_DETECT_STATUS,
    470                     SubscriptionManager.EXTRA_VALUE_NEW_SIM);
    471             intent.putExtra(SubscriptionManager.INTENT_KEY_SIM_COUNT, subCount);
    472             intent.putExtra(SubscriptionManager.INTENT_KEY_NEW_SIM_SLOT, newSimStatus);
    473         } else if (detectedType == SubscriptionManager.EXTRA_VALUE_REPOSITION_SIM) {
    474             intent.putExtra(SubscriptionManager.INTENT_KEY_DETECT_STATUS,
    475                     SubscriptionManager.EXTRA_VALUE_REPOSITION_SIM);
    476             intent.putExtra(SubscriptionManager.INTENT_KEY_SIM_COUNT, subCount);
    477         } else if (detectedType == SubscriptionManager.EXTRA_VALUE_REMOVE_SIM) {
    478             intent.putExtra(SubscriptionManager.INTENT_KEY_DETECT_STATUS,
    479                     SubscriptionManager.EXTRA_VALUE_REMOVE_SIM);
    480             intent.putExtra(SubscriptionManager.INTENT_KEY_SIM_COUNT, subCount);
    481         } else if (detectedType == SubscriptionManager.EXTRA_VALUE_NOCHANGE) {
    482             intent.putExtra(SubscriptionManager.INTENT_KEY_DETECT_STATUS,
    483                     SubscriptionManager.EXTRA_VALUE_NOCHANGE);
    484         }
    485 
    486         logd("broadcast intent ACTION_SUBINFO_RECORD_UPDATED : [" + detectedType + ", "
    487                 + subCount + ", " + newSimStatus+ "]");
    488         ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE, UserHandle.USER_ALL);
    489         logd("[setUpdatedData]- ");
    490     }
    491 
    492     private static boolean isNewSim(String iccId, String[] oldIccId) {
    493         boolean newSim = true;
    494         for(int i = 0; i < PROJECT_SIM_NUM; i++) {
    495             if(iccId.equals(oldIccId[i])) {
    496                 newSim = false;
    497                 break;
    498             }
    499         }
    500         logd("newSim = " + newSim);
    501 
    502         return newSim;
    503     }
    504 
    505     public void dispose() {
    506         logd("[dispose]");
    507         sContext.unregisterReceiver(sReceiver);
    508     }
    509 
    510     private static void logd(String message) {
    511         Rlog.d(LOG_TAG, "[SubInfoRecordUpdater]" + message);
    512     }
    513 }
    514 
    515