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