Home | History | Annotate | Download | only in telephony
      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 
     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 
     57     public String getDeviceId(String callingPackage) {
     58         return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()),
     59                 callingPackage);
     60     }
     61 
     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 
     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 
     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 
    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 
    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      */
    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 
    155     public String getDeviceSvn(String callingPackage) {
    156         return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage);
    157     }
    158 
    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 
    173     public String getSubscriberId(String callingPackage) {
    174         return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage);
    175     }
    176 
    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      */
    194     public String getIccSerialNumber(String callingPackage) {
    195         return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage);
    196     }
    197 
    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 
    212     public String getLine1Number(String callingPackage) {
    213         return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage);
    214     }
    215 
    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 
    231     public String getLine1AlphaTag(String callingPackage) {
    232         return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage);
    233     }
    234 
    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 
    249     public String getMsisdn(String callingPackage) {
    250         return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage);
    251     }
    252 
    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 
    267     public String getVoiceMailNumber(String callingPackage) {
    268         return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage);
    269     }
    270 
    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
    288     public String getCompleteVoiceMailNumber() {
    289         return getCompleteVoiceMailNumberForSubscriber(getDefaultSubscription());
    290     }
    291 
    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 
    305     public String getVoiceMailAlphaTag(String callingPackage) {
    306         return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage);
    307     }
    308 
    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      **/
    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      */
    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      */
    352     private void enforceModifyPermission() {
    353         mContext.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE,
    354                 "Requires MODIFY_PHONE_STATE");
    355     }
    356 
    357     private int getDefaultSubscription() {
    358         return  PhoneFactory.getDefaultSubscription();
    359     }
    360 
    361 
    362     /**
    363     * get the Isim Impi based on subId
    364     */
    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     */
    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     */
    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     */
    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     */
    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 
    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 
    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 
    508     private void log(String s) {
    509         Rlog.d(TAG, s);
    510     }
    511 
    512     private void loge(String s) {
    513         Rlog.e(TAG, s);
    514     }
    515 }
    516