PhoneSubInfo.java revision cf916cfb2b4d8282def13e4553abff2ea73aca2b
1/*
2 * Copyright (C) 2007 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 */
16package com.android.internal.telephony;
17
18import java.io.FileDescriptor;
19import java.io.PrintWriter;
20
21import android.content.Context;
22import android.content.pm.PackageManager;
23import android.os.Binder;
24import android.os.RemoteException;
25import android.telephony.PhoneNumberUtils;
26import android.telephony.Rlog;
27
28import com.android.internal.telephony.uicc.IsimRecords;
29import com.android.internal.telephony.uicc.UiccCard;
30import com.android.internal.telephony.uicc.UiccCardApplication;
31
32public class PhoneSubInfo {
33    static final String LOG_TAG = "PhoneSubInfo";
34    private static final boolean DBG = true;
35    private static final boolean VDBG = false; // STOPSHIP if true
36
37    private Phone mPhone;
38    private Context mContext;
39    private static final String READ_PHONE_STATE =
40        android.Manifest.permission.READ_PHONE_STATE;
41    // TODO: change getCompleteVoiceMailNumber() to require READ_PRIVILEGED_PHONE_STATE
42    private static final String CALL_PRIVILEGED =
43        android.Manifest.permission.CALL_PRIVILEGED;
44    private static final String READ_PRIVILEGED_PHONE_STATE =
45        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
46
47    public PhoneSubInfo(Phone phone) {
48        mPhone = phone;
49        mContext = phone.getContext();
50    }
51
52    public void dispose() {
53    }
54
55    @Override
56    protected void finalize() {
57        try {
58            super.finalize();
59        } catch (Throwable throwable) {
60            loge("Error while finalizing:", throwable);
61        }
62        if (DBG) log("PhoneSubInfo finalized");
63    }
64
65    /**
66     * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
67     */
68    public String getDeviceId() {
69        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
70        return mPhone.getDeviceId();
71    }
72
73    /**
74     * Retrieves the software version number for the device, e.g., IMEI/SV
75     * for GSM phones.
76     */
77    public String getDeviceSvn() {
78        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
79        return mPhone.getDeviceSvn();
80    }
81
82    /**
83     * Retrieves the unique subscriber ID, e.g., IMSI for GSM phones.
84     */
85    public String getSubscriberId() {
86        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
87        return mPhone.getSubscriberId();
88    }
89
90    /**
91     * Retrieves the Group Identifier Level1 for GSM phones.
92     */
93    public String getGroupIdLevel1() {
94        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
95        return mPhone.getGroupIdLevel1();
96    }
97
98    /**
99     * Retrieves the serial number of the ICC, if applicable.
100     */
101    public String getIccSerialNumber() {
102        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
103        return mPhone.getIccSerialNumber();
104    }
105
106    /**
107     * Retrieves the phone number string for line 1.
108     */
109    public String getLine1Number() {
110        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
111        return mPhone.getLine1Number();
112    }
113
114    /**
115     * Retrieves the alpha identifier for line 1.
116     */
117    public String getLine1AlphaTag() {
118        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
119        return mPhone.getLine1AlphaTag();
120    }
121
122    /**
123     * Retrieves the MSISDN string.
124     */
125    public String getMsisdn() {
126        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
127        return mPhone.getMsisdn();
128    }
129
130    /**
131     * Retrieves the voice mail number.
132     */
133    public String getVoiceMailNumber() {
134        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
135        String number = PhoneNumberUtils.extractNetworkPortion(mPhone.getVoiceMailNumber());
136        if (VDBG) log("VM: PhoneSubInfo.getVoiceMailNUmber: " + number);
137        return number;
138    }
139
140    /**
141     * Retrieves the complete voice mail number.
142     *
143     * @hide
144     */
145    public String getCompleteVoiceMailNumber() {
146        mContext.enforceCallingOrSelfPermission(CALL_PRIVILEGED,
147                "Requires CALL_PRIVILEGED");
148        String number = mPhone.getVoiceMailNumber();
149        if (VDBG) log("VM: PhoneSubInfo.getCompleteVoiceMailNUmber: " + number);
150        return number;
151    }
152
153    /**
154     * Retrieves the alpha identifier associated with the voice mail number.
155     */
156    public String getVoiceMailAlphaTag() {
157        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
158        return mPhone.getVoiceMailAlphaTag();
159    }
160
161    /**
162     * Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
163     * @return the IMPI, or null if not present or not loaded
164     */
165    public String getIsimImpi() {
166        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
167                "Requires READ_PRIVILEGED_PHONE_STATE");
168        IsimRecords isim = mPhone.getIsimRecords();
169        if (isim != null) {
170            return isim.getIsimImpi();
171        } else {
172            return null;
173        }
174    }
175
176    /**
177     * Returns the IMS home network domain name that was loaded from the ISIM.
178     * @return the IMS domain name, or null if not present or not loaded
179     */
180    public String getIsimDomain() {
181        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
182                "Requires READ_PRIVILEGED_PHONE_STATE");
183        IsimRecords isim = mPhone.getIsimRecords();
184        if (isim != null) {
185            return isim.getIsimDomain();
186        } else {
187            return null;
188        }
189    }
190
191    /**
192     * Returns the IMS public user identities (IMPU) that were loaded from the ISIM.
193     * @return an array of IMPU strings, with one IMPU per string, or null if
194     *      not present or not loaded
195     */
196    public String[] getIsimImpu() {
197        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
198                "Requires READ_PRIVILEGED_PHONE_STATE");
199        IsimRecords isim = mPhone.getIsimRecords();
200        if (isim != null) {
201            return isim.getIsimImpu();
202        } else {
203            return null;
204        }
205    }
206
207    /**
208     * Returns the IMS Service Table (IST) that was loaded from the ISIM.
209     * @return IMS Service Table or null if not present or not loaded
210     */
211    public String getIsimIst(){
212        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
213                "Requires READ_PRIVILEGED_PHONE_STATE");
214        IsimRecords isim = mPhone.getIsimRecords();
215        if (isim != null) {
216            return isim.getIsimIst();
217        } else {
218            return null;
219        }
220     }
221
222    /**
223     * Returns the IMS Proxy Call Session Control Function(PCSCF) that were loaded from the ISIM.
224     * @return an array of  PCSCF strings with one PCSCF per string, or null if
225     *      not present or not loaded
226     */
227    public String[] getIsimPcscf() {
228        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
229                "Requires READ_PRIVILEGED_PHONE_STATE");
230        IsimRecords isim = mPhone.getIsimRecords();
231        if (isim != null) {
232            return isim.getIsimPcscf();
233        } else {
234            return null;
235        }
236    }
237
238    /**
239     * Returns the response of ISIM Authetification through RIL.
240     * Returns null if the Authentification hasn't been successed or isn't present iphonesubinfo.
241     * @return the response of ISIM Authetification, or null if not available
242     */
243    public String getIsimChallengeResponse(String nonce){
244        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
245                "Requires READ_PRIVILEGED_PHONE_STATE");
246        IsimRecords isim = mPhone.getIsimRecords();
247        if (isim != null) {
248            return isim.getIsimChallengeResponse(nonce);
249        } else {
250            return null;
251        }
252    }
253
254    /**
255     * Returns the response of the SIM application on the UICC to authentication
256     * challenge/response algorithm. The data string and challenge response are
257     * Base64 encoded Strings.
258     * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102.
259     *
260     * @param appType ICC application family (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
261     * @param data authentication challenge data
262     * @return challenge response
263     */
264    public String getIccSimChallengeResponse(long subId, int appType, String data) {
265        // FIXME: use subId!!
266        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
267                "Requires READ_PRIVILEGED_PHONE_STATE");
268
269        UiccCard uiccCard = mPhone.getUiccCard();
270        if (uiccCard == null) {
271            Rlog.e(LOG_TAG, "getIccSimChallengeResponse() UiccCard is null");
272            return null;
273        }
274
275        UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
276        if (uiccApp == null) {
277            Rlog.e(LOG_TAG, "getIccSimChallengeResponse() no app with specified type -- " +
278                    appType);
279            return null;
280        } else {
281            Rlog.e(LOG_TAG, "getIccSimChallengeResponse() found app " + uiccApp.getAid()
282                    + "specified type -- " + appType);
283        }
284
285        int authContext = uiccApp.getAuthContext();
286
287        if (data.length() < 32) {
288            /* must use EAP_SIM context */
289            Rlog.e(LOG_TAG, "data is too small to use EAP_AKA, using EAP_SIM instead");
290            authContext = UiccCardApplication.AUTH_CONTEXT_EAP_SIM;
291        }
292
293        if(authContext == UiccCardApplication.AUTH_CONTEXT_UNDEFINED) {
294            Rlog.e(LOG_TAG, "getIccSimChallengeResponse() authContext undefined for app type " +
295                    appType);
296            return null;
297        }
298
299        return uiccApp.getIccRecords().getIccSimChallengeResponse(authContext, data);
300    }
301
302    private void log(String s) {
303        Rlog.d(LOG_TAG, s);
304    }
305
306    private void loge(String s, Throwable e) {
307        Rlog.e(LOG_TAG, s, e);
308    }
309
310    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
311        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
312                != PackageManager.PERMISSION_GRANTED) {
313            pw.println("Permission Denial: can't dump PhoneSubInfo from from pid="
314                    + Binder.getCallingPid()
315                    + ", uid=" + Binder.getCallingUid());
316            return;
317        }
318
319        pw.println("Phone Subscriber Info:");
320        pw.println("  Phone Type = " + mPhone.getPhoneName());
321        pw.println("  Device ID = " + mPhone.getDeviceId());
322    }
323}
324