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