• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
4  * Not a Contribution.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 package com.android.internal.telephony;
20 
21 import static android.Manifest.permission.CALL_PRIVILEGED;
22 import static android.Manifest.permission.MODIFY_PHONE_STATE;
23 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
24 
25 import android.app.AppOpsManager;
26 import android.content.Context;
27 import android.content.pm.PackageManager;
28 import android.os.RemoteException;
29 import android.os.ServiceManager;
30 import android.telephony.ImsiEncryptionInfo;
31 import android.telephony.PhoneNumberUtils;
32 import android.telephony.Rlog;
33 import android.telephony.SubscriptionManager;
34 
35 import com.android.internal.telephony.uicc.IsimRecords;
36 import com.android.internal.telephony.uicc.UiccCard;
37 import com.android.internal.telephony.uicc.UiccCardApplication;
38 
39 public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
40     private static final String TAG = "PhoneSubInfoController";
41     private static final boolean DBG = true;
42     private static final boolean VDBG = false; // STOPSHIP if true
43 
44     private final Phone[] mPhone;
45     private final Context mContext;
46     private final AppOpsManager mAppOps;
47 
PhoneSubInfoController(Context context, Phone[] phone)48     public PhoneSubInfoController(Context context, Phone[] phone) {
49         mPhone = phone;
50         if (ServiceManager.getService("iphonesubinfo") == null) {
51             ServiceManager.addService("iphonesubinfo", this);
52         }
53         mContext = context;
54         mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
55     }
56 
getDeviceId(String callingPackage)57     public String getDeviceId(String callingPackage) {
58         return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()),
59                 callingPackage);
60     }
61 
getDeviceIdForPhone(int phoneId, String callingPackage)62     public String getDeviceIdForPhone(int phoneId, String callingPackage) {
63         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
64             phoneId = 0;
65         }
66         final Phone phone = mPhone[phoneId];
67         if (phone != null) {
68             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
69                     mContext, phone.getSubId(), callingPackage, "getDeviceId")) {
70                 return null;
71             }
72             return phone.getDeviceId();
73         } else {
74             loge("getDeviceIdForPhone phone " + phoneId + " is null");
75             return null;
76         }
77     }
78 
getNaiForSubscriber(int subId, String callingPackage)79     public String getNaiForSubscriber(int subId, String callingPackage) {
80         Phone phone = getPhone(subId);
81         if (phone != null) {
82             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
83                     mContext, subId, callingPackage, "getNai")) {
84                 return null;
85             }
86             return phone.getNai();
87         } else {
88             loge("getNai phone is null for Subscription:" + subId);
89             return null;
90         }
91     }
92 
getImeiForSubscriber(int subId, String callingPackage)93     public String getImeiForSubscriber(int subId, String callingPackage) {
94         Phone phone = getPhone(subId);
95         if (phone != null) {
96             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
97                     mContext, subId, callingPackage, "getImei")) {
98                 return null;
99             }
100             return phone.getImei();
101         } else {
102             loge("getDeviceId phone is null for Subscription:" + subId);
103             return null;
104         }
105     }
106 
getCarrierInfoForImsiEncryption(int subId, int keyType, String callingPackage)107     public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
108                                                               String callingPackage) {
109         Phone phone = getPhone(subId);
110         if (phone != null) {
111             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
112                     mContext, subId, callingPackage,
113                     "getCarrierInfoForImsiEncryption")) {
114                 return null;
115             }
116             return phone.getCarrierInfoForImsiEncryption(keyType);
117         } else {
118             loge("getCarrierInfoForImsiEncryption phone is null for Subscription:" + subId);
119             return null;
120         }
121     }
122 
setCarrierInfoForImsiEncryption(int subId, String callingPackage, ImsiEncryptionInfo imsiEncryptionInfo)123     public void setCarrierInfoForImsiEncryption(int subId, String callingPackage,
124                                                 ImsiEncryptionInfo imsiEncryptionInfo) {
125         Phone phone = getPhone(subId);
126         if (phone != null) {
127             enforceModifyPermission();
128             phone.setCarrierInfoForImsiEncryption(imsiEncryptionInfo);
129         } else {
130             loge("setCarrierInfoForImsiEncryption phone is null for Subscription:" + subId);
131             return;
132         }
133     }
134 
135     /**
136      *  Resets the Carrier Keys in the database. This involves 2 steps:
137      *  1. Delete the keys from the database.
138      *  2. Send an intent to download new Certificates.
139      *  @param subId
140      *  @param callingPackage
141      */
resetCarrierKeysForImsiEncryption(int subId, String callingPackage)142     public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) {
143         Phone phone = getPhone(subId);
144         if (phone != null) {
145             enforceModifyPermission();
146             phone.resetCarrierKeysForImsiEncryption();
147             return;
148         } else {
149             loge("resetCarrierKeysForImsiEncryption phone is null for Subscription:" + subId);
150             return;
151         }
152     }
153 
154 
getDeviceSvn(String callingPackage)155     public String getDeviceSvn(String callingPackage) {
156         return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage);
157     }
158 
getDeviceSvnUsingSubId(int subId, String callingPackage)159     public String getDeviceSvnUsingSubId(int subId, String callingPackage) {
160         Phone phone = getPhone(subId);
161         if (phone != null) {
162             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
163                     mContext, subId, callingPackage, "getDeviceSvn")) {
164                 return null;
165             }
166             return phone.getDeviceSvn();
167         } else {
168             loge("getDeviceSvn phone is null");
169             return null;
170         }
171     }
172 
getSubscriberId(String callingPackage)173     public String getSubscriberId(String callingPackage) {
174         return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage);
175     }
176 
getSubscriberIdForSubscriber(int subId, String callingPackage)177     public String getSubscriberIdForSubscriber(int subId, String callingPackage) {
178         Phone phone = getPhone(subId);
179         if (phone != null) {
180             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
181                     mContext, subId, callingPackage, "getSubscriberId")) {
182                 return null;
183             }
184             return phone.getSubscriberId();
185         } else {
186             loge("getSubscriberId phone is null for Subscription:" + subId);
187             return null;
188         }
189     }
190 
191     /**
192      * Retrieves the serial number of the ICC, if applicable.
193      */
getIccSerialNumber(String callingPackage)194     public String getIccSerialNumber(String callingPackage) {
195         return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage);
196     }
197 
getIccSerialNumberForSubscriber(int subId, String callingPackage)198     public String getIccSerialNumberForSubscriber(int subId, String callingPackage) {
199         Phone phone = getPhone(subId);
200         if (phone != null) {
201             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
202                     mContext, subId, callingPackage, "getIccSerialNumber")) {
203                 return null;
204             }
205             return phone.getIccSerialNumber();
206         } else {
207             loge("getIccSerialNumber phone is null for Subscription:" + subId);
208             return null;
209         }
210     }
211 
getLine1Number(String callingPackage)212     public String getLine1Number(String callingPackage) {
213         return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage);
214     }
215 
getLine1NumberForSubscriber(int subId, String callingPackage)216     public String getLine1NumberForSubscriber(int subId, String callingPackage) {
217         Phone phone = getPhone(subId);
218         if (phone != null) {
219             // This is open to apps with WRITE_SMS.
220             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
221                     mContext, subId, callingPackage, "getLine1Number")) {
222                 return null;
223             }
224             return phone.getLine1Number();
225         } else {
226             loge("getLine1Number phone is null for Subscription:" + subId);
227             return null;
228         }
229     }
230 
getLine1AlphaTag(String callingPackage)231     public String getLine1AlphaTag(String callingPackage) {
232         return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage);
233     }
234 
getLine1AlphaTagForSubscriber(int subId, String callingPackage)235     public String getLine1AlphaTagForSubscriber(int subId, String callingPackage) {
236         Phone phone = getPhone(subId);
237         if (phone != null) {
238             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
239                     mContext, subId, callingPackage, "getLine1AlphaTag")) {
240                 return null;
241             }
242             return phone.getLine1AlphaTag();
243         } else {
244             loge("getLine1AlphaTag phone is null for Subscription:" + subId);
245             return null;
246         }
247     }
248 
getMsisdn(String callingPackage)249     public String getMsisdn(String callingPackage) {
250         return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage);
251     }
252 
getMsisdnForSubscriber(int subId, String callingPackage)253     public String getMsisdnForSubscriber(int subId, String callingPackage) {
254         Phone phone = getPhone(subId);
255         if (phone != null) {
256             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
257                     mContext, subId, callingPackage, "getMsisdn")) {
258                 return null;
259             }
260             return phone.getMsisdn();
261         } else {
262             loge("getMsisdn phone is null for Subscription:" + subId);
263             return null;
264         }
265     }
266 
getVoiceMailNumber(String callingPackage)267     public String getVoiceMailNumber(String callingPackage) {
268         return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage);
269     }
270 
getVoiceMailNumberForSubscriber(int subId, String callingPackage)271     public String getVoiceMailNumberForSubscriber(int subId, String callingPackage) {
272         Phone phone = getPhone(subId);
273         if (phone != null) {
274             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
275                     mContext, subId, callingPackage, "getVoiceMailNumber")) {
276                 return null;
277             }
278             String number = PhoneNumberUtils.extractNetworkPortion(phone.getVoiceMailNumber());
279             if (VDBG) log("VM: getVoiceMailNUmber: " + number);
280             return number;
281         } else {
282             loge("getVoiceMailNumber phone is null for Subscription:" + subId);
283             return null;
284         }
285     }
286 
287     // TODO: change getCompleteVoiceMailNumber() to require READ_PRIVILEGED_PHONE_STATE
getCompleteVoiceMailNumber()288     public String getCompleteVoiceMailNumber() {
289         return getCompleteVoiceMailNumberForSubscriber(getDefaultSubscription());
290     }
291 
getCompleteVoiceMailNumberForSubscriber(int subId)292     public String getCompleteVoiceMailNumberForSubscriber(int subId) {
293         Phone phone = getPhone(subId);
294         if (phone != null) {
295             mContext.enforceCallingOrSelfPermission(CALL_PRIVILEGED, "Requires CALL_PRIVILEGED");
296             String number = phone.getVoiceMailNumber();
297             if (VDBG) log("VM: getCompleteVoiceMailNUmber: " + number);
298             return number;
299         } else {
300             loge("getCompleteVoiceMailNumber phone is null for Subscription:" + subId);
301             return null;
302         }
303     }
304 
getVoiceMailAlphaTag(String callingPackage)305     public String getVoiceMailAlphaTag(String callingPackage) {
306         return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage);
307     }
308 
getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage)309     public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage) {
310         Phone phone = getPhone(subId);
311         if (phone != null) {
312             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
313                     mContext, subId, callingPackage, "getVoiceMailAlphaTag")) {
314                 return null;
315             }
316             return phone.getVoiceMailAlphaTag();
317         } else {
318             loge("getVoiceMailAlphaTag phone is null for Subscription:" + subId);
319             return null;
320         }
321     }
322 
323     /**
324      * get Phone object based on subId.
325      **/
getPhone(int subId)326     private Phone getPhone(int subId) {
327         int phoneId = SubscriptionManager.getPhoneId(subId);
328         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
329             phoneId = 0;
330         }
331         return mPhone[phoneId];
332     }
333 
334     /**
335      * Make sure caller has either read privileged phone permission or carrier privilege.
336      *
337      * @throws SecurityException if the caller does not have the required permission/privilege
338      */
enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message)339     private void enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message) {
340         int permissionResult = mContext.checkCallingOrSelfPermission(
341                 READ_PRIVILEGED_PHONE_STATE);
342         if (permissionResult == PackageManager.PERMISSION_GRANTED) {
343             return;
344         }
345         if (VDBG) log("No read privileged phone permission, check carrier privilege next.");
346         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, message);
347     }
348 
349     /**
350      * Make sure caller has modify phone state permission.
351      */
enforceModifyPermission()352     private void enforceModifyPermission() {
353         mContext.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE,
354                 "Requires MODIFY_PHONE_STATE");
355     }
356 
getDefaultSubscription()357     private int getDefaultSubscription() {
358         return  PhoneFactory.getDefaultSubscription();
359     }
360 
361 
362     /**
363     * get the Isim Impi based on subId
364     */
getIsimImpi(int subId)365     public String getIsimImpi(int subId) {
366         Phone phone = getPhone(subId);
367         if (phone != null) {
368             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
369                     "Requires READ_PRIVILEGED_PHONE_STATE");
370             IsimRecords isim = phone.getIsimRecords();
371             if (isim != null) {
372                 return isim.getIsimImpi();
373             } else {
374                 return null;
375             }
376         } else {
377             loge("getIsimImpi phone is null for Subscription:" + subId);
378             return null;
379         }
380     }
381 
382     /**
383     * get the Isim Domain based on subId
384     */
getIsimDomain(int subId)385     public String getIsimDomain(int subId) {
386         Phone phone = getPhone(subId);
387         if (phone != null) {
388             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
389                     "Requires READ_PRIVILEGED_PHONE_STATE");
390             IsimRecords isim = phone.getIsimRecords();
391             if (isim != null) {
392                 return isim.getIsimDomain();
393             } else {
394                 return null;
395             }
396         } else {
397             loge("getIsimDomain phone is null for Subscription:" + subId);
398             return null;
399         }
400     }
401 
402     /**
403     * get the Isim Impu based on subId
404     */
getIsimImpu(int subId)405     public String[] getIsimImpu(int subId) {
406         Phone phone = getPhone(subId);
407         if (phone != null) {
408             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
409                     "Requires READ_PRIVILEGED_PHONE_STATE");
410             IsimRecords isim = phone.getIsimRecords();
411             if (isim != null) {
412                 return isim.getIsimImpu();
413             } else {
414                 return null;
415             }
416         } else {
417             loge("getIsimImpu phone is null for Subscription:" + subId);
418             return null;
419         }
420     }
421 
422     /**
423     * get the Isim Ist based on subId
424     */
getIsimIst(int subId)425     public String getIsimIst(int subId) throws RemoteException {
426         Phone phone = getPhone(subId);
427         if (phone != null) {
428             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
429                     "Requires READ_PRIVILEGED_PHONE_STATE");
430             IsimRecords isim = phone.getIsimRecords();
431             if (isim != null) {
432                 return isim.getIsimIst();
433             } else {
434                 return null;
435             }
436         } else {
437             loge("getIsimIst phone is null for Subscription:" + subId);
438             return null;
439         }
440     }
441 
442     /**
443     * get the Isim Pcscf based on subId
444     */
getIsimPcscf(int subId)445     public String[] getIsimPcscf(int subId) throws RemoteException {
446         Phone phone = getPhone(subId);
447         if (phone != null) {
448             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
449                     "Requires READ_PRIVILEGED_PHONE_STATE");
450             IsimRecords isim = phone.getIsimRecords();
451             if (isim != null) {
452                 return isim.getIsimPcscf();
453             } else {
454                 return null;
455             }
456         } else {
457             loge("getIsimPcscf phone is null for Subscription:" + subId);
458             return null;
459         }
460     }
461 
getIccSimChallengeResponse(int subId, int appType, int authType, String data)462     public String getIccSimChallengeResponse(int subId, int appType, int authType, String data)
463             throws RemoteException {
464         // TODO(b/73660190): Migrate to
465         // TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivileges and delete
466         // this helper method.
467         enforcePrivilegedPermissionOrCarrierPrivilege(subId, "getIccSimChallengeResponse");
468         Phone phone = getPhone(subId);
469         UiccCard uiccCard = phone.getUiccCard();
470         if (uiccCard == null) {
471             loge("getIccSimChallengeResponse() UiccCard is null");
472             return null;
473         }
474 
475         UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
476         if (uiccApp == null) {
477             loge("getIccSimChallengeResponse() no app with specified type -- " +
478                     appType);
479             return null;
480         } else {
481             loge("getIccSimChallengeResponse() found app " + uiccApp.getAid()
482                     + " specified type -- " + appType);
483         }
484 
485         if(authType != UiccCardApplication.AUTH_CONTEXT_EAP_SIM &&
486                 authType != UiccCardApplication.AUTH_CONTEXT_EAP_AKA) {
487             loge("getIccSimChallengeResponse() unsupported authType: " + authType);
488             return null;
489         }
490 
491         return uiccApp.getIccRecords().getIccSimChallengeResponse(authType, data);
492     }
493 
getGroupIdLevel1ForSubscriber(int subId, String callingPackage)494     public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage) {
495         Phone phone = getPhone(subId);
496         if (phone != null) {
497             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
498                     mContext, subId, callingPackage, "getGroupIdLevel1")) {
499                 return null;
500             }
501             return phone.getGroupIdLevel1();
502         } else {
503             loge("getGroupIdLevel1 phone is null for Subscription:" + subId);
504             return null;
505         }
506     }
507 
log(String s)508     private void log(String s) {
509         Rlog.d(TAG, s);
510     }
511 
loge(String s)512     private void loge(String s) {
513         Rlog.e(TAG, s);
514     }
515 }
516