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