1 /*
2  * Copyright (C) 2006, 2012 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.uicc;
18 
19 import static android.Manifest.permission.READ_PHONE_STATE;
20 import android.app.ActivityManagerNative;
21 import android.app.AlertDialog;
22 import android.content.Context;
23 import android.content.DialogInterface;
24 import android.content.Intent;
25 import android.content.SharedPreferences;
26 import android.content.pm.PackageManager;
27 import android.content.pm.Signature;
28 import android.content.res.Resources;
29 import android.os.AsyncResult;
30 import android.os.Binder;
31 import android.os.Handler;
32 import android.os.Message;
33 import android.os.PowerManager;
34 import android.os.Registrant;
35 import android.os.RegistrantList;
36 import android.preference.PreferenceManager;
37 import android.telephony.Rlog;
38 import android.telephony.TelephonyManager;
39 import android.text.TextUtils;
40 import android.util.LocalLog;
41 import android.view.WindowManager;
42 
43 import com.android.internal.telephony.CommandsInterface;
44 import com.android.internal.telephony.PhoneBase;
45 import com.android.internal.telephony.CommandsInterface.RadioState;
46 import com.android.internal.telephony.IccCardConstants.State;
47 import com.android.internal.telephony.gsm.GSMPhone;
48 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
49 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
50 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
51 import com.android.internal.telephony.cat.CatService;
52 import com.android.internal.telephony.cdma.CDMALTEPhone;
53 import com.android.internal.telephony.cdma.CDMAPhone;
54 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
55 
56 import android.os.SystemProperties;
57 
58 import com.android.internal.R;
59 
60 import java.io.FileDescriptor;
61 import java.io.PrintWriter;
62 import java.util.List;
63 
64 /**
65  * {@hide}
66  */
67 public class UiccCard {
68     protected static final String LOG_TAG = "UiccCard";
69     protected static final boolean DBG = true;
70 
71     private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_";
72 
73     private final Object mLock = new Object();
74     private CardState mCardState;
75     private PinState mUniversalPinState;
76     private int mGsmUmtsSubscriptionAppIndex;
77     private int mCdmaSubscriptionAppIndex;
78     private int mImsSubscriptionAppIndex;
79     private UiccCardApplication[] mUiccApplications =
80             new UiccCardApplication[IccCardStatus.CARD_MAX_APPS];
81     private Context mContext;
82     private CommandsInterface mCi;
83     private CatService mCatService;
84     private RadioState mLastRadioState =  RadioState.RADIO_UNAVAILABLE;
85     private UiccCarrierPrivilegeRules mCarrierPrivilegeRules;
86 
87     private RegistrantList mAbsentRegistrants = new RegistrantList();
88     private RegistrantList mCarrierPrivilegeRegistrants = new RegistrantList();
89 
90     private static final int EVENT_CARD_REMOVED = 13;
91     private static final int EVENT_CARD_ADDED = 14;
92     private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 15;
93     private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 16;
94     private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 17;
95     private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 18;
96     private static final int EVENT_SIM_IO_DONE = 19;
97     private static final int EVENT_CARRIER_PRIVILIGES_LOADED = 20;
98 
99     private static final LocalLog mLocalLog = new LocalLog(100);
100 
101     private int mPhoneId;
102 
UiccCard(Context c, CommandsInterface ci, IccCardStatus ics)103     public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics) {
104         if (DBG) log("Creating");
105         mCardState = ics.mCardState;
106         update(c, ci, ics);
107     }
108 
UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId)109     public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) {
110         mCardState = ics.mCardState;
111         mPhoneId = phoneId;
112         update(c, ci, ics);
113     }
114 
UiccCard()115     protected UiccCard() {
116     }
117 
dispose()118     public void dispose() {
119         synchronized (mLock) {
120             if (DBG) log("Disposing card");
121             if (mCatService != null) mCatService.dispose();
122             for (UiccCardApplication app : mUiccApplications) {
123                 if (app != null) {
124                     app.dispose();
125                 }
126             }
127             mCatService = null;
128             mUiccApplications = null;
129             mCarrierPrivilegeRules = null;
130         }
131     }
132 
update(Context c, CommandsInterface ci, IccCardStatus ics)133     public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
134         synchronized (mLock) {
135             CardState oldState = mCardState;
136             mCardState = ics.mCardState;
137             mUniversalPinState = ics.mUniversalPinState;
138             mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
139             mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
140             mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
141             mContext = c;
142             mCi = ci;
143 
144             //update applications
145             if (DBG) log(ics.mApplications.length + " applications");
146             for ( int i = 0; i < mUiccApplications.length; i++) {
147                 if (mUiccApplications[i] == null) {
148                     //Create newly added Applications
149                     if (i < ics.mApplications.length) {
150                         mUiccApplications[i] = new UiccCardApplication(this,
151                                 ics.mApplications[i], mContext, mCi);
152                     }
153                 } else if (i >= ics.mApplications.length) {
154                     //Delete removed applications
155                     mUiccApplications[i].dispose();
156                     mUiccApplications[i] = null;
157                 } else {
158                     //Update the rest
159                     mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
160                 }
161             }
162 
163             createAndUpdateCatService();
164 
165             // Reload the carrier privilege rules if necessary.
166             log("Before privilege rules: " + mCarrierPrivilegeRules + " : " + mCardState);
167             if (mCarrierPrivilegeRules == null && mCardState == CardState.CARDSTATE_PRESENT) {
168                 mCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(this,
169                         mHandler.obtainMessage(EVENT_CARRIER_PRIVILIGES_LOADED));
170             } else if (mCarrierPrivilegeRules != null && mCardState != CardState.CARDSTATE_PRESENT) {
171                 mCarrierPrivilegeRules = null;
172             }
173 
174             sanitizeApplicationIndexes();
175 
176             RadioState radioState = mCi.getRadioState();
177             if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
178                     + mLastRadioState);
179             // No notifications while radio is off or we just powering up
180             if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
181                 if (oldState != CardState.CARDSTATE_ABSENT &&
182                         mCardState == CardState.CARDSTATE_ABSENT) {
183                     if (DBG) log("update: notify card removed");
184                     mAbsentRegistrants.notifyRegistrants();
185                     mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
186                 } else if (oldState == CardState.CARDSTATE_ABSENT &&
187                         mCardState != CardState.CARDSTATE_ABSENT) {
188                     if (DBG) log("update: notify card added");
189                     mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
190                 }
191             }
192             mLastRadioState = radioState;
193         }
194     }
195 
createAndUpdateCatService()196     protected void createAndUpdateCatService() {
197         if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
198             // Initialize or Reinitialize CatService
199             if (mCatService == null) {
200                 mCatService = CatService.getInstance(mCi, mContext, this, mPhoneId);
201             } else {
202                 ((CatService)mCatService).update(mCi, mContext, this);
203             }
204         } else {
205             if (mCatService != null) {
206                 mCatService.dispose();
207             }
208             mCatService = null;
209         }
210     }
211 
getCatService()212     public CatService getCatService() {
213         return mCatService;
214     }
215 
216     @Override
finalize()217     protected void finalize() {
218         if (DBG) log("UiccCard finalized");
219     }
220 
221     /**
222      * This function makes sure that application indexes are valid
223      * and resets invalid indexes. (This should never happen, but in case
224      * RIL misbehaves we need to manage situation gracefully)
225      */
sanitizeApplicationIndexes()226     private void sanitizeApplicationIndexes() {
227         mGsmUmtsSubscriptionAppIndex =
228                 checkIndex(mGsmUmtsSubscriptionAppIndex, AppType.APPTYPE_SIM, AppType.APPTYPE_USIM);
229         mCdmaSubscriptionAppIndex =
230                 checkIndex(mCdmaSubscriptionAppIndex, AppType.APPTYPE_RUIM, AppType.APPTYPE_CSIM);
231         mImsSubscriptionAppIndex =
232                 checkIndex(mImsSubscriptionAppIndex, AppType.APPTYPE_ISIM, null);
233     }
234 
checkIndex(int index, AppType expectedAppType, AppType altExpectedAppType)235     private int checkIndex(int index, AppType expectedAppType, AppType altExpectedAppType) {
236         if (mUiccApplications == null || index >= mUiccApplications.length) {
237             loge("App index " + index + " is invalid since there are no applications");
238             return -1;
239         }
240 
241         if (index < 0) {
242             // This is normal. (i.e. no application of this type)
243             return -1;
244         }
245 
246         if (mUiccApplications[index].getType() != expectedAppType &&
247             mUiccApplications[index].getType() != altExpectedAppType) {
248             loge("App index " + index + " is invalid since it's not " +
249                     expectedAppType + " and not " + altExpectedAppType);
250             return -1;
251         }
252 
253         // Seems to be valid
254         return index;
255     }
256 
257     /**
258      * Notifies handler of any transition into State.ABSENT
259      */
registerForAbsent(Handler h, int what, Object obj)260     public void registerForAbsent(Handler h, int what, Object obj) {
261         synchronized (mLock) {
262             Registrant r = new Registrant (h, what, obj);
263 
264             mAbsentRegistrants.add(r);
265 
266             if (mCardState == CardState.CARDSTATE_ABSENT) {
267                 r.notifyRegistrant();
268             }
269         }
270     }
271 
unregisterForAbsent(Handler h)272     public void unregisterForAbsent(Handler h) {
273         synchronized (mLock) {
274             mAbsentRegistrants.remove(h);
275         }
276     }
277 
278     /**
279      * Notifies handler when carrier privilege rules are loaded.
280      */
registerForCarrierPrivilegeRulesLoaded(Handler h, int what, Object obj)281     public void registerForCarrierPrivilegeRulesLoaded(Handler h, int what, Object obj) {
282         synchronized (mLock) {
283             Registrant r = new Registrant (h, what, obj);
284 
285             mCarrierPrivilegeRegistrants.add(r);
286 
287             if (areCarrierPriviligeRulesLoaded()) {
288                 r.notifyRegistrant();
289             }
290         }
291     }
292 
unregisterForCarrierPrivilegeRulesLoaded(Handler h)293     public void unregisterForCarrierPrivilegeRulesLoaded(Handler h) {
294         synchronized (mLock) {
295             mCarrierPrivilegeRegistrants.remove(h);
296         }
297     }
298 
onIccSwap(boolean isAdded)299     private void onIccSwap(boolean isAdded) {
300 
301         boolean isHotSwapSupported = mContext.getResources().getBoolean(
302                 com.android.internal.R.bool.config_hotswapCapable);
303 
304         if (isHotSwapSupported) {
305             log("onIccSwap: isHotSwapSupported is true, don't prompt for rebooting");
306             return;
307         }
308         log("onIccSwap: isHotSwapSupported is false, prompt for rebooting");
309 
310         synchronized (mLock) {
311             // TODO: Here we assume the device can't handle SIM hot-swap
312             //      and has to reboot. We may want to add a property,
313             //      e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support
314             //      hot-swap.
315             DialogInterface.OnClickListener listener = null;
316 
317 
318             // TODO: SimRecords is not reset while SIM ABSENT (only reset while
319             //       Radio_off_or_not_available). Have to reset in both both
320             //       added or removed situation.
321             listener = new DialogInterface.OnClickListener() {
322                 @Override
323                 public void onClick(DialogInterface dialog, int which) {
324                     synchronized (mLock) {
325                         if (which == DialogInterface.BUTTON_POSITIVE) {
326                             if (DBG) log("Reboot due to SIM swap");
327                             PowerManager pm = (PowerManager) mContext
328                                     .getSystemService(Context.POWER_SERVICE);
329                             pm.reboot("SIM is added.");
330                         }
331                     }
332                 }
333 
334             };
335 
336             Resources r = Resources.getSystem();
337 
338             String title = (isAdded) ? r.getString(R.string.sim_added_title) :
339                 r.getString(R.string.sim_removed_title);
340             String message = (isAdded) ? r.getString(R.string.sim_added_message) :
341                 r.getString(R.string.sim_removed_message);
342             String buttonTxt = r.getString(R.string.sim_restart_button);
343 
344             AlertDialog dialog = new AlertDialog.Builder(mContext)
345             .setTitle(title)
346             .setMessage(message)
347             .setPositiveButton(buttonTxt, listener)
348             .create();
349             dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
350             dialog.show();
351         }
352     }
353 
354     protected Handler mHandler = new Handler() {
355         @Override
356         public void handleMessage(Message msg){
357             switch (msg.what) {
358                 case EVENT_CARD_REMOVED:
359                     onIccSwap(false);
360                     break;
361                 case EVENT_CARD_ADDED:
362                     onIccSwap(true);
363                     break;
364                 case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
365                 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
366                 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
367                 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
368                 case EVENT_SIM_IO_DONE:
369                     AsyncResult ar = (AsyncResult)msg.obj;
370                     if (ar.exception != null) {
371                         loglocal("Exception: " + ar.exception);
372                         log("Error in SIM access with exception" + ar.exception);
373                     }
374                     AsyncResult.forMessage((Message)ar.userObj, ar.result, ar.exception);
375                     ((Message)ar.userObj).sendToTarget();
376                     break;
377                 case EVENT_CARRIER_PRIVILIGES_LOADED:
378                     onCarrierPriviligesLoadedMessage();
379                     break;
380                 default:
381                     loge("Unknown Event " + msg.what);
382             }
383         }
384     };
385 
onCarrierPriviligesLoadedMessage()386     private void onCarrierPriviligesLoadedMessage() {
387         synchronized (mLock) {
388             mCarrierPrivilegeRegistrants.notifyRegistrants();
389         }
390     }
391 
isApplicationOnIcc(IccCardApplicationStatus.AppType type)392     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
393         synchronized (mLock) {
394             for (int i = 0 ; i < mUiccApplications.length; i++) {
395                 if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) {
396                     return true;
397                 }
398             }
399             return false;
400         }
401     }
402 
getCardState()403     public CardState getCardState() {
404         synchronized (mLock) {
405             return mCardState;
406         }
407     }
408 
getUniversalPinState()409     public PinState getUniversalPinState() {
410         synchronized (mLock) {
411             return mUniversalPinState;
412         }
413     }
414 
getApplication(int family)415     public UiccCardApplication getApplication(int family) {
416         synchronized (mLock) {
417             int index = IccCardStatus.CARD_MAX_APPS;
418             switch (family) {
419                 case UiccController.APP_FAM_3GPP:
420                     index = mGsmUmtsSubscriptionAppIndex;
421                     break;
422                 case UiccController.APP_FAM_3GPP2:
423                     index = mCdmaSubscriptionAppIndex;
424                     break;
425                 case UiccController.APP_FAM_IMS:
426                     index = mImsSubscriptionAppIndex;
427                     break;
428             }
429             if (index >= 0 && index < mUiccApplications.length) {
430                 return mUiccApplications[index];
431             }
432             return null;
433         }
434     }
435 
getApplicationIndex(int index)436     public UiccCardApplication getApplicationIndex(int index) {
437         synchronized (mLock) {
438             if (index >= 0 && index < mUiccApplications.length) {
439                 return mUiccApplications[index];
440             }
441             return null;
442         }
443     }
444 
445     /**
446      * Returns the SIM application of the specified type.
447      *
448      * @param type ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
449      * @return application corresponding to type or a null if no match found
450      */
getApplicationByType(int type)451     public UiccCardApplication getApplicationByType(int type) {
452         synchronized (mLock) {
453             for (int i = 0 ; i < mUiccApplications.length; i++) {
454                 if (mUiccApplications[i] != null &&
455                         mUiccApplications[i].getType().ordinal() == type) {
456                     return mUiccApplications[i];
457                 }
458             }
459             return null;
460         }
461     }
462 
463     /**
464      * Resets the application with the input AID. Returns true if any changes were made.
465      *
466      * A null aid implies a card level reset - all applications must be reset.
467      */
resetAppWithAid(String aid)468     public boolean resetAppWithAid(String aid) {
469         synchronized (mLock) {
470             boolean changed = false;
471             for (int i = 0; i < mUiccApplications.length; i++) {
472                 if (mUiccApplications[i] != null &&
473                     (aid == null || aid.equals(mUiccApplications[i].getAid()))) {
474                     // Delete removed applications
475                     mUiccApplications[i].dispose();
476                     mUiccApplications[i] = null;
477                     changed = true;
478                 }
479             }
480             return changed;
481         }
482         // TODO: For a card level notification, we should delete the CarrierPrivilegeRules and the
483         // CAT service.
484     }
485 
486     /**
487      * Exposes {@link CommandsInterface.iccOpenLogicalChannel}
488      */
iccOpenLogicalChannel(String AID, Message response)489     public void iccOpenLogicalChannel(String AID, Message response) {
490         loglocal("Open Logical Channel: " + AID + " by pid:" + Binder.getCallingPid()
491                 + " uid:" + Binder.getCallingUid());
492         mCi.iccOpenLogicalChannel(AID,
493                 mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, response));
494     }
495 
496     /**
497      * Exposes {@link CommandsInterface.iccCloseLogicalChannel}
498      */
iccCloseLogicalChannel(int channel, Message response)499     public void iccCloseLogicalChannel(int channel, Message response) {
500         loglocal("Close Logical Channel: " + channel);
501         mCi.iccCloseLogicalChannel(channel,
502                 mHandler.obtainMessage(EVENT_CLOSE_LOGICAL_CHANNEL_DONE, response));
503     }
504 
505     /**
506      * Exposes {@link CommandsInterface.iccTransmitApduLogicalChannel}
507      */
iccTransmitApduLogicalChannel(int channel, int cla, int command, int p1, int p2, int p3, String data, Message response)508     public void iccTransmitApduLogicalChannel(int channel, int cla, int command,
509             int p1, int p2, int p3, String data, Message response) {
510         mCi.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3,
511                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, response));
512     }
513 
514     /**
515      * Exposes {@link CommandsInterface.iccTransmitApduBasicChannel}
516      */
iccTransmitApduBasicChannel(int cla, int command, int p1, int p2, int p3, String data, Message response)517     public void iccTransmitApduBasicChannel(int cla, int command,
518             int p1, int p2, int p3, String data, Message response) {
519         mCi.iccTransmitApduBasicChannel(cla, command, p1, p2, p3,
520                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, response));
521     }
522 
523     /**
524      * Exposes {@link CommandsInterface.iccIO}
525      */
iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3, String pathID, Message response)526     public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
527             String pathID, Message response) {
528         mCi.iccIO(command, fileID, pathID, p1, p2, p3, null, null,
529                 mHandler.obtainMessage(EVENT_SIM_IO_DONE, response));
530     }
531 
532     /**
533      * Exposes {@link CommandsInterface.sendEnvelopeWithStatus}
534      */
sendEnvelopeWithStatus(String contents, Message response)535     public void sendEnvelopeWithStatus(String contents, Message response) {
536         mCi.sendEnvelopeWithStatus(contents, response);
537     }
538 
539     /* Returns number of applications on this card */
getNumApplications()540     public int getNumApplications() {
541         int count = 0;
542         for (UiccCardApplication a : mUiccApplications) {
543             if (a != null) {
544                 count++;
545             }
546         }
547         return count;
548     }
549 
getPhoneId()550     public int getPhoneId() {
551         return mPhoneId;
552     }
553 
554     /**
555      * Returns true iff carrier priveleges rules are null (dont need to be loaded) or loaded.
556      */
areCarrierPriviligeRulesLoaded()557     public boolean areCarrierPriviligeRulesLoaded() {
558         return mCarrierPrivilegeRules == null
559             || mCarrierPrivilegeRules.areCarrierPriviligeRulesLoaded();
560     }
561 
562     /**
563      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}.
564      */
getCarrierPrivilegeStatus(Signature signature, String packageName)565     public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
566         return mCarrierPrivilegeRules == null ?
567             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
568             mCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature, packageName);
569     }
570 
571     /**
572      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}.
573      */
getCarrierPrivilegeStatus(PackageManager packageManager, String packageName)574     public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) {
575         return mCarrierPrivilegeRules == null ?
576             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
577             mCarrierPrivilegeRules.getCarrierPrivilegeStatus(packageManager, packageName);
578     }
579 
580     /**
581      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction}.
582      */
getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager)583     public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) {
584         return mCarrierPrivilegeRules == null ?
585             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
586             mCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction(packageManager);
587     }
588 
589     /**
590      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPackageNamesForIntent}.
591      */
getCarrierPackageNamesForIntent( PackageManager packageManager, Intent intent)592     public List<String> getCarrierPackageNamesForIntent(
593             PackageManager packageManager, Intent intent) {
594         return mCarrierPrivilegeRules == null ? null :
595             mCarrierPrivilegeRules.getCarrierPackageNamesForIntent(
596                     packageManager, intent);
597     }
598 
setOperatorBrandOverride(String brand)599     public boolean setOperatorBrandOverride(String brand) {
600         log("setOperatorBrandOverride: " + brand);
601         log("current iccId: " + getIccId());
602 
603         String iccId = getIccId();
604         if (TextUtils.isEmpty(iccId)) {
605             return false;
606         }
607 
608         SharedPreferences.Editor spEditor =
609                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
610         String key = OPERATOR_BRAND_OVERRIDE_PREFIX + iccId;
611         if (brand == null) {
612             spEditor.remove(key).commit();
613         } else {
614             spEditor.putString(key, brand).commit();
615         }
616         return true;
617     }
618 
getOperatorBrandOverride()619     public String getOperatorBrandOverride() {
620         String iccId = getIccId();
621         if (TextUtils.isEmpty(iccId)) {
622             return null;
623         }
624         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
625         return sp.getString(OPERATOR_BRAND_OVERRIDE_PREFIX + iccId, null);
626     }
627 
getIccId()628     public String getIccId() {
629         // ICCID should be same across all the apps.
630         for (UiccCardApplication app : mUiccApplications) {
631             if (app != null) {
632                 IccRecords ir = app.getIccRecords();
633                 if (ir != null && ir.getIccId() != null) {
634                     return ir.getIccId();
635                 }
636             }
637         }
638         return null;
639     }
640 
log(String msg)641     private void log(String msg) {
642         Rlog.d(LOG_TAG, msg);
643     }
644 
loge(String msg)645     private void loge(String msg) {
646         Rlog.e(LOG_TAG, msg);
647     }
648 
loglocal(String msg)649     private void loglocal(String msg) {
650         if (DBG) mLocalLog.log(msg);
651     }
652 
dump(FileDescriptor fd, PrintWriter pw, String[] args)653     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
654         pw.println("UiccCard:");
655         pw.println(" mCi=" + mCi);
656         pw.println(" mLastRadioState=" + mLastRadioState);
657         pw.println(" mCatService=" + mCatService);
658         pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
659         for (int i = 0; i < mAbsentRegistrants.size(); i++) {
660             pw.println("  mAbsentRegistrants[" + i + "]="
661                     + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
662         }
663         for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) {
664             pw.println("  mCarrierPrivilegeRegistrants[" + i + "]="
665                     + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler());
666         }
667         pw.println(" mCardState=" + mCardState);
668         pw.println(" mUniversalPinState=" + mUniversalPinState);
669         pw.println(" mGsmUmtsSubscriptionAppIndex=" + mGsmUmtsSubscriptionAppIndex);
670         pw.println(" mCdmaSubscriptionAppIndex=" + mCdmaSubscriptionAppIndex);
671         pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
672         pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
673         pw.println(" mUiccApplications: length=" + mUiccApplications.length);
674         for (int i = 0; i < mUiccApplications.length; i++) {
675             if (mUiccApplications[i] == null) {
676                 pw.println("  mUiccApplications[" + i + "]=" + null);
677             } else {
678                 pw.println("  mUiccApplications[" + i + "]="
679                         + mUiccApplications[i].getType() + " " + mUiccApplications[i]);
680             }
681         }
682         pw.println();
683         // Print details of all applications
684         for (UiccCardApplication app : mUiccApplications) {
685             if (app != null) {
686                 app.dump(fd, pw, args);
687                 pw.println();
688             }
689         }
690         // Print details of all IccRecords
691         for (UiccCardApplication app : mUiccApplications) {
692             if (app != null) {
693                 IccRecords ir = app.getIccRecords();
694                 if (ir != null) {
695                     ir.dump(fd, pw, args);
696                     pw.println();
697                 }
698             }
699         }
700         // Print UiccCarrierPrivilegeRules and registrants.
701         if (mCarrierPrivilegeRules == null) {
702             pw.println(" mCarrierPrivilegeRules: null");
703         } else {
704             pw.println(" mCarrierPrivilegeRules: " + mCarrierPrivilegeRules);
705             mCarrierPrivilegeRules.dump(fd, pw, args);
706         }
707         pw.println(" mCarrierPrivilegeRegistrants: size=" + mCarrierPrivilegeRegistrants.size());
708         for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) {
709             pw.println("  mCarrierPrivilegeRegistrants[" + i + "]="
710                     + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler());
711         }
712         pw.flush();
713         pw.println("mLocalLog:");
714         mLocalLog.dump(fd, pw, args);
715         pw.flush();
716     }
717 }
718