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