Home | History | Annotate | Download | only in cdma
      1 /*
      2  * Copyright (C) 2011 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 
     17 package com.android.internal.telephony.cdma;
     18 
     19 import android.app.ActivityManagerNative;
     20 import android.content.ContentValues;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.SharedPreferences;
     24 import android.database.SQLException;
     25 import android.net.Uri;
     26 import android.os.AsyncResult;
     27 import android.os.Handler;
     28 import android.os.Message;
     29 import android.os.UserHandle;
     30 import android.preference.PreferenceManager;
     31 import android.os.PowerManager;
     32 import android.os.SystemProperties;
     33 import android.provider.Telephony;
     34 import android.text.TextUtils;
     35 import android.telephony.SubscriptionManager;
     36 import android.telephony.Rlog;
     37 
     38 import com.android.internal.telephony.CommandsInterface;
     39 
     40 import android.telephony.TelephonyManager;
     41 
     42 import com.android.internal.telephony.dataconnection.DcTracker;
     43 import com.android.internal.telephony.MccTable;
     44 import com.android.internal.telephony.OperatorInfo;
     45 import com.android.internal.telephony.PhoneConstants;
     46 import com.android.internal.telephony.PhoneNotifier;
     47 import com.android.internal.telephony.PhoneProxy;
     48 import com.android.internal.telephony.PhoneFactory;
     49 import com.android.internal.telephony.PhoneSubInfo;
     50 import com.android.internal.telephony.SMSDispatcher;
     51 import com.android.internal.telephony.SmsBroadcastUndelivered;
     52 import com.android.internal.telephony.Subscription;
     53 import com.android.internal.telephony.SubscriptionController;
     54 import com.android.internal.telephony.gsm.GsmSMSDispatcher;
     55 import com.android.internal.telephony.gsm.SmsMessage;
     56 import com.android.internal.telephony.uicc.IccRecords;
     57 import com.android.internal.telephony.uicc.IsimRecords;
     58 import com.android.internal.telephony.uicc.IsimUiccRecords;
     59 import com.android.internal.telephony.uicc.RuimRecords;
     60 import com.android.internal.telephony.uicc.SIMRecords;
     61 import com.android.internal.telephony.uicc.UiccCardApplication;
     62 import com.android.internal.telephony.uicc.UiccController;
     63 import com.android.internal.telephony.ServiceStateTracker;
     64 import com.android.internal.telephony.TelephonyIntents;
     65 import com.android.internal.telephony.TelephonyProperties;
     66 
     67 import java.io.FileDescriptor;
     68 import java.io.PrintWriter;
     69 
     70 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
     71 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
     72 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
     73 import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_ACTIVATED;
     74 import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_DEACTIVATED;
     75 
     76 public class CDMALTEPhone extends CDMAPhone {
     77     static final String LOG_LTE_TAG = "CDMALTEPhone";
     78     private static final boolean DBG = true;
     79 
     80     /** CdmaLtePhone in addition to RuimRecords available from
     81      * PhoneBase needs access to SIMRecords and IsimUiccRecords
     82      */
     83     private SIMRecords mSimRecords;
     84     private IsimUiccRecords mIsimUiccRecords;
     85 
     86     // Constructors
     87     public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
     88             int phoneId) {
     89         this(context, ci, notifier, false, phoneId);
     90     }
     91 
     92     public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
     93             boolean unitTestMode, int phoneId) {
     94         super(context, ci, notifier, phoneId);
     95 
     96         Rlog.d(LOG_TAG, "CDMALTEPhone: constructor: sub = " + mPhoneId);
     97 
     98         mDcTracker = new DcTracker(this);
     99 
    100     }
    101 
    102     // Constructors
    103     public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
    104         super(context, ci, notifier, false);
    105     }
    106 
    107     @Override
    108     public void handleMessage (Message msg) {
    109         switch (msg.what) {
    110             case EVENT_SUBSCRIPTION_ACTIVATED:
    111                 log("EVENT_SUBSCRIPTION_ACTIVATED");
    112                 onSubscriptionActivated();
    113                 break;
    114 
    115             case EVENT_SUBSCRIPTION_DEACTIVATED:
    116                 log("EVENT_SUBSCRIPTION_DEACTIVATED");
    117                 onSubscriptionDeactivated();
    118                 break;
    119 
    120             default:
    121                 super.handleMessage(msg);
    122         }
    123     }
    124 
    125     @Override
    126     protected void initSstIcc() {
    127         mSST = new CdmaLteServiceStateTracker(this);
    128     }
    129 
    130     @Override
    131     public void dispose() {
    132         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
    133             super.dispose();
    134         }
    135     }
    136 
    137     @Override
    138     public void removeReferences() {
    139         super.removeReferences();
    140     }
    141 
    142     @Override
    143     public PhoneConstants.DataState getDataConnectionState(String apnType) {
    144         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
    145 
    146         if (mSST == null) {
    147             // Radio Technology Change is ongoing, dispose() and
    148             // removeReferences() have already been called
    149 
    150             ret = PhoneConstants.DataState.DISCONNECTED;
    151         } else if (mDcTracker.isApnTypeEnabled(apnType) == false) {
    152             ret = PhoneConstants.DataState.DISCONNECTED;
    153         } else {
    154             switch (mDcTracker.getState(apnType)) {
    155                 case RETRYING:
    156                 case FAILED:
    157                 case IDLE:
    158                     ret = PhoneConstants.DataState.DISCONNECTED;
    159                     break;
    160 
    161                 case CONNECTED:
    162                 case DISCONNECTING:
    163                     if (mCT.mState != PhoneConstants.State.IDLE &&
    164                             !mSST.isConcurrentVoiceAndDataAllowed()) {
    165                         ret = PhoneConstants.DataState.SUSPENDED;
    166                     } else {
    167                         ret = PhoneConstants.DataState.CONNECTED;
    168                     }
    169                     break;
    170 
    171                 case CONNECTING:
    172                 case SCANNING:
    173                     ret = PhoneConstants.DataState.CONNECTING;
    174                     break;
    175             }
    176         }
    177 
    178         log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
    179         return ret;
    180     }
    181 
    182     /**
    183      * Sets the "current" field in the telephony provider according to the
    184      * build-time operator numeric property
    185      *
    186      * @return true for success; false otherwise.
    187      */
    188     @Override
    189     boolean updateCurrentCarrierInProvider(String operatorNumeric) {
    190         boolean retVal;
    191         if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) == null) {
    192             if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null");
    193             retVal = super.updateCurrentCarrierInProvider(operatorNumeric);
    194         } else {
    195             if (DBG) log("updateCurrentCarrierInProvider not updated");
    196             retVal = true;
    197         }
    198         if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal);
    199         return retVal;
    200     }
    201 
    202     @Override
    203     public boolean updateCurrentCarrierInProvider() {
    204         long currentDds = SubscriptionManager.getDefaultDataSubId();
    205         String operatorNumeric = getOperatorNumeric();
    206 
    207         Rlog.d(LOG_TAG, "updateCurrentCarrierInProvider: mSubscription = " + getSubId()
    208                 + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric);
    209 
    210         if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) {
    211             try {
    212                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
    213                 ContentValues map = new ContentValues();
    214                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
    215                 mContext.getContentResolver().insert(uri, map);
    216                 return true;
    217             } catch (SQLException e) {
    218                 Rlog.e(LOG_TAG, "Can't store current operator", e);
    219             }
    220         }
    221         return false;
    222     }
    223 
    224     // return IMSI from USIM as subscriber ID.
    225     @Override
    226     public String getSubscriberId() {
    227         return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
    228     }
    229 
    230     // return GID1 from USIM
    231     @Override
    232     public String getGroupIdLevel1() {
    233         return (mSimRecords != null) ? mSimRecords.getGid1() : "";
    234     }
    235 
    236     @Override
    237     public String getImei() {
    238         return mImei;
    239     }
    240 
    241     @Override
    242     public String getDeviceSvn() {
    243         return mImeiSv;
    244     }
    245 
    246     @Override
    247     public IsimRecords getIsimRecords() {
    248         return mIsimUiccRecords;
    249     }
    250 
    251     @Override
    252     public String getMsisdn() {
    253         return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
    254     }
    255 
    256     @Override
    257     public void getAvailableNetworks(Message response) {
    258         mCi.getAvailableNetworks(response);
    259     }
    260 
    261     @Override
    262     protected void onUpdateIccAvailability() {
    263         if (mUiccController == null ) {
    264             return;
    265         }
    266 
    267         // Update IsimRecords
    268         UiccCardApplication newUiccApplication =
    269                 mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_IMS);
    270         IsimUiccRecords newIsimUiccRecords = null;
    271 
    272         if (newUiccApplication != null) {
    273             newIsimUiccRecords = (IsimUiccRecords) newUiccApplication.getIccRecords();
    274         }
    275         mIsimUiccRecords = newIsimUiccRecords;
    276 
    277         // Update UsimRecords
    278         newUiccApplication = mUiccController.getUiccCardApplication(mPhoneId,
    279                 UiccController.APP_FAM_3GPP);
    280         SIMRecords newSimRecords = null;
    281         if (newUiccApplication != null) {
    282             newSimRecords = (SIMRecords) newUiccApplication.getIccRecords();
    283         }
    284         mSimRecords = newSimRecords;
    285 
    286         super.onUpdateIccAvailability();
    287     }
    288 
    289     @Override
    290     protected void init(Context context, PhoneNotifier notifier) {
    291         mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
    292         mCT = new CdmaCallTracker(this);
    293         mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCi, this,
    294                 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
    295         mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
    296         mSubInfo = new PhoneSubInfo(this);
    297         mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
    298 
    299         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
    300         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
    301         mCi.registerForOn(this, EVENT_RADIO_ON, null);
    302         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
    303         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
    304         mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
    305         mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE,
    306                 null);
    307 
    308         PowerManager pm
    309             = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    310         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG);
    311 
    312         // This is needed to handle phone process crashes
    313         String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
    314         mIsPhoneInEcmState = inEcm.equals("true");
    315         if (mIsPhoneInEcmState) {
    316             // Send a message which will invoke handleExitEmergencyCallbackMode
    317             mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
    318         }
    319 
    320         // get the string that specifies the carrier OTA Sp number
    321         mCarrierOtaSpNumSchema = SystemProperties.get(
    322                 TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,"");
    323 
    324         setProperties();
    325     }
    326 
    327     private void onSubscriptionActivated() {
    328 //        mSubscriptionData = SubscriptionManager.getCurrentSubscription(mSubscription);
    329 
    330         log("SUBSCRIPTION ACTIVATED : slotId : " + mSubscriptionData.slotId
    331                 + " appid : " + mSubscriptionData.m3gpp2Index
    332                 + " subId : " + mSubscriptionData.subId
    333                 + " subStatus : " + mSubscriptionData.subStatus);
    334 
    335         // Make sure properties are set for proper subscription.
    336         setProperties();
    337 
    338         onUpdateIccAvailability();
    339         mSST.sendMessage(mSST.obtainMessage(ServiceStateTracker.EVENT_ICC_CHANGED));
    340         ((CdmaLteServiceStateTracker)mSST).updateCdmaSubscription();
    341         ((DcTracker)mDcTracker).updateRecords();
    342     }
    343 
    344     private void onSubscriptionDeactivated() {
    345         log("SUBSCRIPTION DEACTIVATED");
    346         // resetSubSpecifics
    347         mSubscriptionData = null;
    348     }
    349 
    350     // Set the properties per subscription
    351     private void setProperties() {
    352         //Change the system property
    353         setSystemProperty(TelephonyProperties.CURRENT_ACTIVE_PHONE,
    354                 new Integer(PhoneConstants.PHONE_TYPE_CDMA).toString());
    355         // Sets operator alpha property by retrieving from build-time system property
    356         String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
    357         if (!TextUtils.isEmpty(operatorAlpha)) {
    358             setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
    359         }
    360 
    361         // Sets operator numeric property by retrieving from build-time system property
    362         String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
    363         log("update icc_operator_numeric=" + operatorNumeric);
    364         if (!TextUtils.isEmpty(operatorNumeric)) {
    365             setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
    366 
    367             SubscriptionController.getInstance().setMccMnc(operatorNumeric, getSubId());
    368             // Sets iso country property by retrieving from build-time system property
    369             setIsoCountryProperty(operatorNumeric);
    370             // Updates MCC MNC device configuration information
    371             log("update mccmnc=" + operatorNumeric);
    372             MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
    373         }
    374         // Sets current entry in the telephony carrier table
    375         updateCurrentCarrierInProvider();
    376     }
    377 
    378     @Override
    379     public void setSystemProperty(String property, String value) {
    380         if(getUnitTestMode()) {
    381             return;
    382         }
    383         TelephonyManager.setTelephonyProperty(property, getSubId(), value);
    384     }
    385 
    386     public String getSystemProperty(String property, String defValue) {
    387         if(getUnitTestMode()) {
    388             return null;
    389         }
    390         return TelephonyManager.getTelephonyProperty(property, getSubId(), defValue);
    391     }
    392 
    393     public void updateDataConnectionTracker() {
    394         ((DcTracker)mDcTracker).update();
    395     }
    396 
    397     public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
    398         ((DcTracker)mDcTracker)
    399                 .setInternalDataEnabled(enable, onCompleteMsg);
    400     }
    401 
    402     public boolean setInternalDataEnabledFlag(boolean enable) {
    403        return ((DcTracker)mDcTracker)
    404                 .setInternalDataEnabledFlag(enable);
    405     }
    406 
    407     /**
    408      * @return operator numeric.
    409      */
    410     public String getOperatorNumeric() {
    411         String operatorNumeric = null;
    412         IccRecords curIccRecords = null;
    413         if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
    414             operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
    415         } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM) {
    416             curIccRecords = mSimRecords;
    417             if (curIccRecords != null) {
    418                 operatorNumeric = curIccRecords.getOperatorNumeric();
    419             } else {
    420                 curIccRecords = mIccRecords.get();
    421                 if (curIccRecords != null && (curIccRecords instanceof RuimRecords)) {
    422                     RuimRecords csim = (RuimRecords) curIccRecords;
    423                     operatorNumeric = csim.getRUIMOperatorNumeric();
    424                 }
    425             }
    426         }
    427         if (operatorNumeric == null) {
    428             Rlog.e(LOG_TAG, "getOperatorNumeric: Cannot retrieve operatorNumeric:"
    429                     + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + " mIccRecords = "
    430                     + ((curIccRecords != null) ? curIccRecords.getRecordsLoaded() : null));
    431         }
    432 
    433         Rlog.d(LOG_TAG, "getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource
    434                 + " operatorNumeric = " + operatorNumeric);
    435 
    436         return operatorNumeric;
    437     }
    438     public void registerForAllDataDisconnected(Handler h, int what, Object obj) {
    439         ((DcTracker)mDcTracker)
    440                .registerForAllDataDisconnected(h, what, obj);
    441     }
    442 
    443     public void unregisterForAllDataDisconnected(Handler h) {
    444         ((DcTracker)mDcTracker)
    445                 .unregisterForAllDataDisconnected(h);
    446     }
    447 
    448     @Override
    449     protected void log(String s) {
    450             Rlog.d(LOG_LTE_TAG, s);
    451     }
    452 
    453     protected void loge(String s) {
    454             Rlog.e(LOG_LTE_TAG, s);
    455     }
    456 
    457     protected void loge(String s, Throwable e) {
    458         Rlog.e(LOG_LTE_TAG, s, e);
    459     }
    460 
    461     @Override
    462     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    463         pw.println("CDMALTEPhone extends:");
    464         super.dump(fd, pw, args);
    465     }
    466 }
    467