SubscriptionManager.java revision f2090b88b72d89825b9bf9c6ddbf5ae8a7f3116b
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.telephony;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.content.Intent;
22import android.net.Uri;
23import android.provider.BaseColumns;
24import android.telephony.Rlog;
25import android.os.ServiceManager;
26import android.os.RemoteException;
27
28import com.android.internal.telephony.ISub;
29import com.android.internal.telephony.PhoneConstants;
30
31import java.util.ArrayList;
32import java.util.List;
33
34/**
35 * SubscriptionManager is the application interface to SubscriptionController
36 * and provides information about the current Telephony Subscriptions.
37 *
38 * The android.Manifest.permission.READ_PHONE_STATE to retrieve the information, except
39 * getActiveSubIdList and getActiveSubIdCount for which no permission is needed.
40 */
41public class SubscriptionManager implements BaseColumns {
42    private static final String LOG_TAG = "SUB";
43    private static final boolean DBG = true;
44    private static final boolean VDBG = false;
45
46    /** An invalid phone identifier */
47    public static final int INVALID_PHONE_ID = -1000;
48
49    /** Indicates the caller wants the default phone id. */
50    public static final int DEFAULT_PHONE_ID = Integer.MAX_VALUE;
51
52    /** An invalid slot identifier */
53    public static final int INVALID_SLOT_ID = -1000;
54
55    /** Indicates the caller wants the default slot id. */
56    /** @hide */
57    public static final int DEFAULT_SLOT_ID = Integer.MAX_VALUE;
58
59    /** Indicates the user should be asked which subscription to use. */
60    public static final long ASK_USER_SUB_ID = -1001;
61
62    /** An invalid subscription identifier */
63    public static final long INVALID_SUB_ID = -1000;
64
65    /** Indicates the caller wants the default sub id. */
66    public static final long DEFAULT_SUB_ID = Long.MAX_VALUE;
67
68    /** @hide */
69    public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
70
71    /** @hide */
72    public static final int DEFAULT_INT_VALUE = -100;
73
74    /** @hide */
75    public static final String DEFAULT_STRING_VALUE = "N/A";
76
77    /** @hide */
78    public static final int EXTRA_VALUE_NEW_SIM = 1;
79
80    /** @hide */
81    public static final int EXTRA_VALUE_REMOVE_SIM = 2;
82    /** @hide */
83    public static final int EXTRA_VALUE_REPOSITION_SIM = 3;
84    /** @hide */
85    public static final int EXTRA_VALUE_NOCHANGE = 4;
86
87    /** @hide */
88    public static final String INTENT_KEY_DETECT_STATUS = "simDetectStatus";
89    /** @hide */
90    public static final String INTENT_KEY_SIM_COUNT = "simCount";
91    /** @hide */
92    public static final String INTENT_KEY_NEW_SIM_SLOT = "newSIMSlot";
93    /** @hide */
94    public static final String INTENT_KEY_NEW_SIM_STATUS = "newSIMStatus";
95
96    /**
97     * The ICC ID of a SIM.
98     * <P>Type: TEXT (String)</P>
99     */
100    /** @hide */
101    public static final String ICC_ID = "icc_id";
102
103    /**
104     * <P>Type: INTEGER (int)</P>
105     */
106    /** @hide */
107    public static final String SIM_ID = "sim_id";
108
109    /** SIM is not inserted */
110    public static final int SIM_NOT_INSERTED = -1;
111
112    /**
113     * TelephonyProvider column name for user displayed name.
114     * <P>Type: TEXT (String)</P>
115     */
116    /** @hide */
117    public static final String DISPLAY_NAME = "display_name";
118
119    /**
120     * Default name resource
121     * @hide
122     */
123    public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName;
124
125    /**
126     * TelephonyProvider column name for source of the user displayed name.
127     * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below
128     *
129     * @hide
130     */
131    public static final String NAME_SOURCE = "name_source";
132
133    /**
134     * The name_source is undefined
135     * @hide
136     */
137    public static final int NAME_SOURCE_UNDEFINDED = -1;
138
139    /**
140     * The name_source is the default
141     * @hide
142     */
143    public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
144
145    /**
146     * The name_source is from the SIM
147     * @hide
148     */
149    public static final int NAME_SOURCE_SIM_SOURCE = 1;
150
151    /**
152     * The name_source is from the user
153     * @hide
154     */
155    public static final int NAME_SOURCE_USER_INPUT = 2;
156
157    /**
158     * TelephonyProvider column name for the color of a SIM.
159     * <P>Type: INTEGER (int)</P>
160     */
161    /** @hide */
162    public static final String COLOR = "color";
163
164    /** @hide */
165    public static final int COLOR_1 = 0;
166
167    /** @hide */
168    public static final int COLOR_2 = 1;
169
170    /** @hide */
171    public static final int COLOR_3 = 2;
172
173    /** @hide */
174    public static final int COLOR_4 = 3;
175
176    /** @hide */
177    public static final int COLOR_DEFAULT = COLOR_1;
178
179    /**
180     * TelephonyProvider column name for the phone number of a SIM.
181     * <P>Type: TEXT (String)</P>
182     */
183    /** @hide */
184    public static final String NUMBER = "number";
185
186    /**
187     * TelephonyProvider column name for the number display format of a SIM.
188     * <P>Type: INTEGER (int)</P>
189     */
190    /** @hide */
191    public static final String DISPLAY_NUMBER_FORMAT = "display_number_format";
192
193    /** @hide */
194    public static final int DISPLAY_NUMBER_NONE = 0;
195
196    /** @hide */
197    public static final int DISPLAY_NUMBER_FIRST = 1;
198
199    /** @hide */
200    public static final int DISPLAY_NUMBER_LAST = 2;
201
202    /** @hide */
203    public static final int DISLPAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
204
205    /**
206     * TelephonyProvider column name for permission for data roaming of a SIM.
207     * <P>Type: INTEGER (int)</P>
208     */
209    /** @hide */
210    public static final String DATA_ROAMING = "data_roaming";
211
212    /** @hide */
213    public static final int DATA_ROAMING_ENABLE = 1;
214
215    /** @hide */
216    public static final int DATA_ROAMING_DISABLE = 0;
217
218    /** @hide */
219    public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
220
221    /**
222     * TelephonyProvider column name for the MCC associated with a SIM.
223     * <P>Type: INTEGER (int)</P>
224     */
225    public static final String MCC = "mcc";
226
227    /**
228     * TelephonyProvider column name for the MNC associated with a SIM.
229     * <P>Type: INTEGER (int)</P>
230     */
231    public static final String MNC = "mnc";
232
233
234    private static final int RES_TYPE_BACKGROUND_DARK = 0;
235
236    private static final int RES_TYPE_BACKGROUND_LIGHT = 1;
237
238    private static final int[] sSimBackgroundDarkRes = setSimResource(RES_TYPE_BACKGROUND_DARK);
239
240    /**
241     * Broadcast Action: The user has changed one of the default subs related to
242     * data, phone calls, or sms</p>
243     * @hide
244     */
245    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
246    public static final String SUB_DEFAULT_CHANGED_ACTION =
247        "android.intent.action.SUB_DEFAULT_CHANGED";
248
249    /** @hide */
250    public SubscriptionManager() {
251        if (DBG) logd("SubscriptionManager created");
252    }
253
254    /**
255     * Get the SubInfoRecord associated with the subId
256     * @param subId The unique SubInfoRecord index in database
257     * @return SubInfoRecord, maybe null
258     */
259    public static SubInfoRecord getSubInfoForSubscriber(long subId) {
260        if (!isValidSubId(subId)) {
261            logd("[getSubInfoForSubscriberx]- invalid subId");
262            return null;
263        }
264
265        SubInfoRecord subInfo = null;
266
267        try {
268            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
269            if (iSub != null) {
270                subInfo = iSub.getSubInfoForSubscriber(subId);
271            }
272        } catch (RemoteException ex) {
273            // ignore it
274        }
275
276        return subInfo;
277
278    }
279
280    /**
281     * Get the SubInfoRecord according to an IccId
282     * @param iccId the IccId of SIM card
283     * @return SubInfoRecord List, maybe empty but not null
284     * @hide
285     */
286    public static List<SubInfoRecord> getSubInfoUsingIccId(String iccId) {
287        if (VDBG) logd("[getSubInfoUsingIccId]+ iccId=" + iccId);
288        if (iccId == null) {
289            logd("[getSubInfoUsingIccId]- null iccid");
290            return null;
291        }
292
293        List<SubInfoRecord> result = null;
294
295        try {
296            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
297            if (iSub != null) {
298                result = iSub.getSubInfoUsingIccId(iccId);
299            }
300        } catch (RemoteException ex) {
301            // ignore it
302        }
303
304
305        if (result == null) {
306            result = new ArrayList<SubInfoRecord>();
307        }
308        return result;
309    }
310
311    /**
312     * Get the SubInfoRecord according to slotId
313     * @param slotId the slot which the SIM is inserted
314     * @return SubInfoRecord list, maybe empty but not null
315     */
316    public static List<SubInfoRecord> getSubInfoUsingSlotId(int slotId) {
317        // FIXME: Consider never returning null
318        if (!isValidSlotId(slotId)) {
319            logd("[getSubInfoUsingSlotId]- invalid slotId");
320            return null;
321        }
322
323        List<SubInfoRecord> result = null;
324
325        try {
326            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
327            if (iSub != null) {
328                result = iSub.getSubInfoUsingSlotId(slotId);
329            }
330        } catch (RemoteException ex) {
331            // ignore it
332        }
333
334
335        if (result == null) {
336            result = new ArrayList<SubInfoRecord>();
337        }
338        return result;
339    }
340
341    /**
342     * Get all the SubInfoRecord(s) in subInfo database
343     * @return List of all SubInfoRecords in database, include those that were inserted before
344     * maybe empty but not null.
345     * @hide
346     */
347    public static List<SubInfoRecord> getAllSubInfoList() {
348        if (VDBG) logd("[getAllSubInfoList]+");
349
350        List<SubInfoRecord> result = null;
351
352        try {
353            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
354            if (iSub != null) {
355                result = iSub.getAllSubInfoList();
356            }
357        } catch (RemoteException ex) {
358            // ignore it
359        }
360
361        if (result == null) {
362            result = new ArrayList<SubInfoRecord>();
363        }
364        return result;
365    }
366
367    /**
368     * Get the SubInfoRecord(s) of the currently inserted SIM(s)
369     * @return Array list of currently inserted SubInfoRecord(s) maybe empty but not null
370     */
371    public static List<SubInfoRecord> getActiveSubInfoList() {
372        List<SubInfoRecord> result = null;
373
374        try {
375            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
376            if (iSub != null) {
377                result = iSub.getActiveSubInfoList();
378            }
379        } catch (RemoteException ex) {
380            // ignore it
381        }
382
383        if (result == null) {
384            result = new ArrayList<SubInfoRecord>();
385        }
386        return result;
387    }
388
389    /**
390     * Get the SUB count of all SUB(s) in subinfo database
391     * @return all SIM count in database, include what was inserted before
392     * @hide
393     */
394    public static int getAllSubInfoCount() {
395        if (VDBG) logd("[getAllSubInfoCount]+");
396
397        int result = 0;
398
399        try {
400            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
401            if (iSub != null) {
402                result = iSub.getAllSubInfoCount();
403            }
404        } catch (RemoteException ex) {
405            // ignore it
406        }
407
408        return result;
409    }
410
411    /**
412     * Get the count of active SUB(s)
413     * @return active SIM count
414     * @hide
415     */
416    public static int getActiveSubInfoCount() {
417        int result = 0;
418
419        try {
420            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
421            if (iSub != null) {
422                result = iSub.getActiveSubInfoCount();
423            }
424        } catch (RemoteException ex) {
425            // ignore it
426        }
427
428        return result;
429    }
430
431    /**
432     * Add a new SubInfoRecord to subinfo database if needed
433     * @param iccId the IccId of the SIM card
434     * @param slotId the slot which the SIM is inserted
435     * @return the URL of the newly created row or the updated row
436     * @hide
437     */
438    public static Uri addSubInfoRecord(String iccId, int slotId) {
439        if (VDBG) logd("[addSubInfoRecord]+ iccId:" + iccId + " slotId:" + slotId);
440        if (iccId == null) {
441            logd("[addSubInfoRecord]- null iccId");
442        }
443        if (!isValidSlotId(slotId)) {
444            logd("[addSubInfoRecord]- invalid slotId");
445        }
446
447        try {
448            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
449            if (iSub != null) {
450                // FIXME: This returns 1 on success, 0 on error should should we return it?
451                iSub.addSubInfoRecord(iccId, slotId);
452            }
453        } catch (RemoteException ex) {
454            // ignore it
455        }
456
457        // FIXME: Always returns null?
458        return null;
459
460    }
461
462    /**
463     * Set SIM color by simInfo index
464     * @param color the color of the SIM
465     * @param subId the unique SubInfoRecord index in database
466     * @return the number of records updated
467     * @hide
468     */
469    public static int setColor(int color, long subId) {
470        if (VDBG) logd("[setColor]+ color:" + color + " subId:" + subId);
471        int size = sSimBackgroundDarkRes.length;
472        if (!isValidSubId(subId) || color < 0 || color >= size) {
473            logd("[setColor]- fail");
474            return -1;
475        }
476
477        int result = 0;
478
479        try {
480            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
481            if (iSub != null) {
482                result = iSub.setColor(color, subId);
483            }
484        } catch (RemoteException ex) {
485            // ignore it
486        }
487
488        return result;
489
490    }
491
492    /**
493     * Set display name by simInfo index
494     * @param displayName the display name of SIM card
495     * @param subId the unique SubInfoRecord index in database
496     * @return the number of records updated
497     * @hide
498     */
499    public static int setDisplayName(String displayName, long subId) {
500        return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED);
501    }
502
503    /**
504     * Set display name by simInfo index with name source
505     * @param displayName the display name of SIM card
506     * @param subId the unique SubInfoRecord index in database
507     * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
508     *                   2: NAME_SOURCE_USER_INPUT, -1 NAME_SOURCE_UNDEFINED
509     * @return the number of records updated or -1 if invalid subId
510     * @hide
511     */
512    public static int setDisplayName(String displayName, long subId, long nameSource) {
513        if (VDBG) {
514            logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
515                    + " nameSource:" + nameSource);
516        }
517        if (!isValidSubId(subId)) {
518            logd("[setDisplayName]- fail");
519            return -1;
520        }
521
522        int result = 0;
523
524        try {
525            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
526            if (iSub != null) {
527                result = iSub.setDisplayNameUsingSrc(displayName, subId, nameSource);
528            }
529        } catch (RemoteException ex) {
530            // ignore it
531        }
532
533        return result;
534
535    }
536
537    /**
538     * Set phone number by subId
539     * @param number the phone number of the SIM
540     * @param subId the unique SubInfoRecord index in database
541     * @return the number of records updated
542     * @hide
543     */
544    public static int setDisplayNumber(String number, long subId) {
545        if (number == null || !isValidSubId(subId)) {
546            logd("[setDisplayNumber]- fail");
547            return -1;
548        }
549
550        int result = 0;
551
552        try {
553            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
554            if (iSub != null) {
555                result = iSub.setDisplayNumber(number, subId);
556            }
557        } catch (RemoteException ex) {
558            // ignore it
559        }
560
561        return result;
562
563    }
564
565    /**
566     * Set number display format. 0: none, 1: the first four digits, 2: the last four digits
567     * @param format the display format of phone number
568     * @param subId the unique SubInfoRecord index in database
569     * @return the number of records updated
570     * @hide
571     */
572    public static int setDisplayNumberFormat(int format, long subId) {
573        if (VDBG) logd("[setDisplayNumberFormat]+ format:" + format + " subId:" + subId);
574        if (format < 0 || !isValidSubId(subId)) {
575            logd("[setDisplayNumberFormat]- fail, return -1");
576            return -1;
577        }
578
579        int result = 0;
580
581        try {
582            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
583            if (iSub != null) {
584                result = iSub.setDisplayNumberFormat(format, subId);
585            }
586        } catch (RemoteException ex) {
587            // ignore it
588        }
589
590        return result;
591
592    }
593
594    /**
595     * Set data roaming by simInfo index
596     * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
597     * @param subId the unique SubInfoRecord index in database
598     * @return the number of records updated
599     * @hide
600     */
601    public static int setDataRoaming(int roaming, long subId) {
602        if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
603        if (roaming < 0 || !isValidSubId(subId)) {
604            logd("[setDataRoaming]- fail");
605            return -1;
606        }
607
608        int result = 0;
609
610        try {
611            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
612            if (iSub != null) {
613                result = iSub.setDataRoaming(roaming, subId);
614            }
615        } catch (RemoteException ex) {
616            // ignore it
617        }
618
619        return result;
620    }
621
622    /**
623     * Get slotId associated with the subscription.
624     * @return slotId as a positive integer or a negative value if an error either
625     * SIM_NOT_INSERTED or INVALID_SLOT_ID.
626     */
627    public static int getSlotId(long subId) {
628        if (!isValidSubId(subId)) {
629            logd("[getSlotId]- fail");
630        }
631
632        int result = INVALID_SLOT_ID;
633
634        try {
635            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
636            if (iSub != null) {
637                result = iSub.getSlotId(subId);
638            }
639        } catch (RemoteException ex) {
640            // ignore it
641        }
642
643        return result;
644
645    }
646
647    /** @hide */
648    public static long[] getSubId(int slotId) {
649        if (!isValidSlotId(slotId)) {
650            logd("[getSubId]- fail");
651            return null;
652        }
653
654        long[] subId = null;
655
656        try {
657            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
658            if (iSub != null) {
659                subId = iSub.getSubId(slotId);
660            }
661        } catch (RemoteException ex) {
662            // ignore it
663        }
664
665        return subId;
666    }
667
668    /** @hide */
669    public static int getPhoneId(long subId) {
670        if (!isValidSubId(subId)) {
671            logd("[getPhoneId]- fail");
672            return INVALID_PHONE_ID;
673        }
674
675        int result = INVALID_PHONE_ID;
676
677        try {
678            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
679            if (iSub != null) {
680                result = iSub.getPhoneId(subId);
681            }
682        } catch (RemoteException ex) {
683            // ignore it
684        }
685
686        if (VDBG) logd("[getPhoneId]- phoneId=" + result);
687        return result;
688
689    }
690
691    private static int[] setSimResource(int type) {
692        int[] simResource = null;
693
694        switch (type) {
695            case RES_TYPE_BACKGROUND_DARK:
696                simResource = new int[] {
697                    com.android.internal.R.drawable.sim_dark_blue,
698                    com.android.internal.R.drawable.sim_dark_orange,
699                    com.android.internal.R.drawable.sim_dark_green,
700                    com.android.internal.R.drawable.sim_dark_purple
701                };
702                break;
703            case RES_TYPE_BACKGROUND_LIGHT:
704                simResource = new int[] {
705                    com.android.internal.R.drawable.sim_light_blue,
706                    com.android.internal.R.drawable.sim_light_orange,
707                    com.android.internal.R.drawable.sim_light_green,
708                    com.android.internal.R.drawable.sim_light_purple
709                };
710                break;
711        }
712
713        return simResource;
714    }
715
716    private static void logd(String msg) {
717        Rlog.d(LOG_TAG, "[SubManager] " + msg);
718    }
719
720    /**
721     * @return the "system" defaultSubId on a voice capable device this
722     * will be getDefaultVoiceSubId() and on a data only device it will be
723     * getDefaultDataSubId().
724     * @hide
725     */
726    public static long getDefaultSubId() {
727        long subId = INVALID_SUB_ID;
728
729        try {
730            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
731            if (iSub != null) {
732                subId = iSub.getDefaultSubId();
733            }
734        } catch (RemoteException ex) {
735            // ignore it
736        }
737
738        if (VDBG) logd("getDefaultSubId=" + subId);
739        return subId;
740    }
741
742    /** @hide */
743    public static long getDefaultVoiceSubId() {
744        long subId = INVALID_SUB_ID;
745
746        try {
747            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
748            if (iSub != null) {
749                subId = iSub.getDefaultVoiceSubId();
750            }
751        } catch (RemoteException ex) {
752            // ignore it
753        }
754
755        if (VDBG) logd("getDefaultVoiceSubId, sub id = " + subId);
756        return subId;
757    }
758
759    /** @hide */
760    public static void setDefaultVoiceSubId(long subId) {
761        if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId);
762        try {
763            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
764            if (iSub != null) {
765                iSub.setDefaultVoiceSubId(subId);
766            }
767        } catch (RemoteException ex) {
768            // ignore it
769        }
770    }
771
772    /** @hide */
773    public static SubInfoRecord getDefaultVoiceSubInfo() {
774        return getSubInfoForSubscriber(getDefaultVoiceSubId());
775    }
776
777    /** @hide */
778    public static int getDefaultVoicePhoneId() {
779        return getPhoneId(getDefaultVoiceSubId());
780    }
781
782    /**
783     * @return subId of the DefaultSms subscription or the value INVALID_SUB_ID if an error.
784     */
785    public static long getDefaultSmsSubId() {
786        long subId = INVALID_SUB_ID;
787
788        try {
789            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
790            if (iSub != null) {
791                subId = iSub.getDefaultSmsSubId();
792            }
793        } catch (RemoteException ex) {
794            // ignore it
795        }
796
797        if (VDBG) logd("getDefaultSmsSubId, sub id = " + subId);
798        return subId;
799    }
800
801    /** @hide */
802    public static void setDefaultSmsSubId(long subId) {
803        if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
804        try {
805            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
806            if (iSub != null) {
807                iSub.setDefaultSmsSubId(subId);
808            }
809        } catch (RemoteException ex) {
810            // ignore it
811        }
812    }
813
814    /** @hide */
815    public static SubInfoRecord getDefaultSmsSubInfo() {
816        return getSubInfoForSubscriber(getDefaultSmsSubId());
817    }
818
819    /** @hide */
820    public static int getDefaultSmsPhoneId() {
821        return getPhoneId(getDefaultSmsSubId());
822    }
823
824    /** @hide */
825    public static long getDefaultDataSubId() {
826        long subId = INVALID_SUB_ID;
827
828        try {
829            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
830            if (iSub != null) {
831                subId = iSub.getDefaultDataSubId();
832            }
833        } catch (RemoteException ex) {
834            // ignore it
835        }
836
837        if (VDBG) logd("getDefaultDataSubId, sub id = " + subId);
838        return subId;
839    }
840
841    /** @hide */
842    public static void setDefaultDataSubId(long subId) {
843        if (VDBG) logd("setDataSubscription sub id = " + subId);
844        try {
845            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
846            if (iSub != null) {
847                iSub.setDefaultDataSubId(subId);
848            }
849        } catch (RemoteException ex) {
850            // ignore it
851        }
852    }
853
854    /** @hide */
855    public static SubInfoRecord getDefaultDataSubInfo() {
856        return getSubInfoForSubscriber(getDefaultDataSubId());
857    }
858
859    /** @hide */
860    public static int getDefaultDataPhoneId() {
861        return getPhoneId(getDefaultDataSubId());
862    }
863
864    /** @hide */
865    public static void clearSubInfo() {
866        try {
867            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
868            if (iSub != null) {
869                iSub.clearSubInfo();
870            }
871        } catch (RemoteException ex) {
872            // ignore it
873        }
874
875        return;
876    }
877
878    //FIXME this is vulnerable to race conditions
879    /** @hide */
880    public static boolean allDefaultsSelected() {
881        if (getDefaultDataSubId() == INVALID_SUB_ID) {
882            return false;
883        }
884        if (getDefaultSmsSubId() == INVALID_SUB_ID) {
885            return false;
886        }
887        if (getDefaultVoiceSubId() == INVALID_SUB_ID) {
888            return false;
889        }
890        return true;
891    }
892
893    /**
894     * If a default is set to subscription which is not active, this will reset that default back to
895     * INVALID_SUB_ID.
896     * @hide
897     */
898    public static void clearDefaultsForInactiveSubIds() {
899        if (VDBG) logd("clearDefaultsForInactiveSubIds");
900        try {
901            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
902            if (iSub != null) {
903                iSub.clearDefaultsForInactiveSubIds();
904            }
905        } catch (RemoteException ex) {
906            // ignore it
907        }
908    }
909
910    /**
911     * @return true if a valid subId else false
912     */
913    public static boolean isValidSubId(long subId) {
914        return subId > INVALID_SUB_ID ;
915    }
916
917    /** @hide */
918    public static boolean isValidSlotId(int slotId) {
919        return slotId > INVALID_SLOT_ID && slotId < TelephonyManager.getDefault().getSimCount();
920    }
921
922    /** @hide */
923    public static boolean isValidPhoneId(int phoneId) {
924        return phoneId > INVALID_PHONE_ID
925                && phoneId < TelephonyManager.getDefault().getPhoneCount();
926    }
927
928    /** @hide */
929    public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
930        long[] subIds = SubscriptionManager.getSubId(phoneId);
931        if (subIds != null && subIds.length > 0) {
932            putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
933        } else {
934            logd("putPhoneIdAndSubIdExtra: no valid subs");
935        }
936    }
937
938    /** @hide */
939    public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, long subId) {
940        if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
941        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
942        intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
943        //FIXME this is using phoneId and slotId interchangeably
944        //Eventually, this should be removed as it is not the slot id
945        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
946    }
947
948    /**
949     * @return the list of subId's that are active,
950     *         is never null but the length maybe 0.
951     * @hide
952     */
953    public static long[] getActiveSubIdList() {
954        long[] subId = null;
955
956        try {
957            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
958            if (iSub != null) {
959                subId = iSub.getActiveSubIdList();
960            }
961        } catch (RemoteException ex) {
962            // ignore it
963        }
964
965        if (subId == null) {
966            subId = new long[0];
967        }
968
969        return subId;
970
971    }
972}
973
974