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