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.content.ContentValues;
     20 import android.content.Context;
     21 import android.content.SharedPreferences;
     22 import android.database.SQLException;
     23 import android.net.Uri;
     24 import android.os.AsyncResult;
     25 import android.os.Message;
     26 import android.preference.PreferenceManager;
     27 import android.provider.Telephony;
     28 import android.telephony.Rlog;
     29 
     30 import com.android.internal.telephony.CommandsInterface;
     31 
     32 import com.android.internal.telephony.OperatorInfo;
     33 import com.android.internal.telephony.PhoneConstants;
     34 import com.android.internal.telephony.PhoneNotifier;
     35 import com.android.internal.telephony.PhoneProxy;
     36 import com.android.internal.telephony.SMSDispatcher;
     37 import com.android.internal.telephony.SmsBroadcastUndelivered;
     38 import com.android.internal.telephony.gsm.GsmSMSDispatcher;
     39 import com.android.internal.telephony.gsm.SmsMessage;
     40 import com.android.internal.telephony.uicc.IsimRecords;
     41 import com.android.internal.telephony.uicc.IsimUiccRecords;
     42 import com.android.internal.telephony.uicc.SIMRecords;
     43 import com.android.internal.telephony.uicc.UiccCardApplication;
     44 import com.android.internal.telephony.uicc.UiccController;
     45 
     46 import java.io.FileDescriptor;
     47 import java.io.PrintWriter;
     48 
     49 public class CDMALTEPhone extends CDMAPhone {
     50     static final String LOG_LTE_TAG = "CDMALTEPhone";
     51     private static final boolean DBG = true;
     52 
     53     /** CdmaLtePhone in addition to RuimRecords available from
     54      * PhoneBase needs access to SIMRecords and IsimUiccRecords
     55      */
     56     private SIMRecords mSimRecords;
     57     private IsimUiccRecords mIsimUiccRecords;
     58 
     59     /**
     60      * Small container class used to hold information relevant to
     61      * the carrier selection process. operatorNumeric can be ""
     62      * if we are looking for automatic selection. operatorAlphaLong is the
     63      * corresponding operator name.
     64      */
     65     private static class NetworkSelectMessage {
     66         public Message message;
     67         public String operatorNumeric;
     68         public String operatorAlphaLong;
     69     }
     70 
     71     // Constructors
     72     public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
     73         super(context, ci, notifier, false);
     74     }
     75 
     76     @Override
     77     public void handleMessage (Message msg) {
     78         switch (msg.what) {
     79             // handle the select network completion callbacks.
     80             case EVENT_SET_NETWORK_MANUAL_COMPLETE:
     81                 handleSetSelectNetwork((AsyncResult) msg.obj);
     82                 break;
     83 
     84             default:
     85                 super.handleMessage(msg);
     86         }
     87     }
     88 
     89     @Override
     90     protected void initSstIcc() {
     91         mSST = new CdmaLteServiceStateTracker(this);
     92     }
     93 
     94     @Override
     95     public void dispose() {
     96         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
     97             super.dispose();
     98         }
     99     }
    100 
    101     @Override
    102     public void removeReferences() {
    103         super.removeReferences();
    104     }
    105 
    106     @Override
    107     public PhoneConstants.DataState getDataConnectionState(String apnType) {
    108         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
    109 
    110         if (mSST == null) {
    111             // Radio Technology Change is ongoing, dispose() and
    112             // removeReferences() have already been called
    113 
    114             ret = PhoneConstants.DataState.DISCONNECTED;
    115         } else if (mDcTracker.isApnTypeEnabled(apnType) == false) {
    116             ret = PhoneConstants.DataState.DISCONNECTED;
    117         } else {
    118             switch (mDcTracker.getState(apnType)) {
    119                 case RETRYING:
    120                 case FAILED:
    121                 case IDLE:
    122                     ret = PhoneConstants.DataState.DISCONNECTED;
    123                     break;
    124 
    125                 case CONNECTED:
    126                 case DISCONNECTING:
    127                     if (mCT.mState != PhoneConstants.State.IDLE &&
    128                             !mSST.isConcurrentVoiceAndDataAllowed()) {
    129                         ret = PhoneConstants.DataState.SUSPENDED;
    130                     } else {
    131                         ret = PhoneConstants.DataState.CONNECTED;
    132                     }
    133                     break;
    134 
    135                 case CONNECTING:
    136                 case SCANNING:
    137                     ret = PhoneConstants.DataState.CONNECTING;
    138                     break;
    139             }
    140         }
    141 
    142         log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
    143         return ret;
    144     }
    145 
    146     @Override
    147     public void
    148     selectNetworkManually(OperatorInfo network,
    149             Message response) {
    150         // wrap the response message in our own message along with
    151         // the operator's id.
    152         NetworkSelectMessage nsm = new NetworkSelectMessage();
    153         nsm.message = response;
    154         nsm.operatorNumeric = network.getOperatorNumeric();
    155         nsm.operatorAlphaLong = network.getOperatorAlphaLong();
    156 
    157         // get the message
    158         Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
    159 
    160         mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
    161     }
    162 
    163     /**
    164      * Used to track the settings upon completion of the network change.
    165      */
    166     private void handleSetSelectNetwork(AsyncResult ar) {
    167         // look for our wrapper within the asyncresult, skip the rest if it
    168         // is null.
    169         if (!(ar.userObj instanceof NetworkSelectMessage)) {
    170             loge("unexpected result from user object.");
    171             return;
    172         }
    173 
    174         NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
    175 
    176         // found the object, now we send off the message we had originally
    177         // attached to the request.
    178         if (nsm.message != null) {
    179             if (DBG) log("sending original message to recipient");
    180             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
    181             nsm.message.sendToTarget();
    182         }
    183 
    184         // open the shared preferences editor, and write the value.
    185         // nsm.operatorNumeric is "" if we're in automatic.selection.
    186         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    187         SharedPreferences.Editor editor = sp.edit();
    188         editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric);
    189         editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong);
    190 
    191         // commit and log the result.
    192         if (! editor.commit()) {
    193             loge("failed to commit network selection preference");
    194         }
    195 
    196     }
    197 
    198 
    199     /**
    200      * Sets the "current" field in the telephony provider according to the
    201      * build-time operator numeric property
    202      *
    203      * @return true for success; false otherwise.
    204      */
    205     @Override
    206     boolean updateCurrentCarrierInProvider(String operatorNumeric) {
    207         boolean retVal;
    208         if (mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP) == null) {
    209             if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null");
    210             retVal = super.updateCurrentCarrierInProvider(operatorNumeric);
    211         } else {
    212             if (DBG) log("updateCurrentCarrierInProvider not updated");
    213             retVal = true;
    214         }
    215         if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal);
    216         return retVal;
    217     }
    218 
    219     @Override
    220     public boolean updateCurrentCarrierInProvider() {
    221         if (mSimRecords != null) {
    222             try {
    223                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
    224                 ContentValues map = new ContentValues();
    225                 String operatorNumeric = mSimRecords.getOperatorNumeric();
    226                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
    227                 if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" +
    228                         operatorNumeric);
    229                 mContext.getContentResolver().insert(uri, map);
    230                 return true;
    231             } catch (SQLException e) {
    232                 loge("Can't store current operator ret false", e);
    233             }
    234         } else {
    235             if (DBG) log("updateCurrentCarrierInProvider mIccRecords == null ret false");
    236         }
    237         return false;
    238     }
    239 
    240     // return IMSI from USIM as subscriber ID.
    241     @Override
    242     public String getSubscriberId() {
    243         return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
    244     }
    245 
    246     // return GID1 from USIM
    247     @Override
    248     public String getGroupIdLevel1() {
    249         return (mSimRecords != null) ? mSimRecords.getGid1() : "";
    250     }
    251 
    252     @Override
    253     public String getImei() {
    254         return mImei;
    255     }
    256 
    257     @Override
    258     public String getDeviceSvn() {
    259         return mImeiSv;
    260     }
    261 
    262     @Override
    263     public IsimRecords getIsimRecords() {
    264         return mIsimUiccRecords;
    265     }
    266 
    267     @Override
    268     public String getMsisdn() {
    269         return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
    270     }
    271 
    272     @Override
    273     public void getAvailableNetworks(Message response) {
    274         mCi.getAvailableNetworks(response);
    275     }
    276 
    277     @Override
    278     public void requestIsimAuthentication(String nonce, Message result) {
    279         mCi.requestIsimAuthentication(nonce, result);
    280     }
    281 
    282     @Override
    283     protected void onUpdateIccAvailability() {
    284         if (mUiccController == null ) {
    285             return;
    286         }
    287 
    288         // Update IsimRecords
    289         UiccCardApplication newUiccApplication =
    290                 mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS);
    291         IsimUiccRecords newIsimUiccRecords = null;
    292 
    293         if (newUiccApplication != null) {
    294             newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords();
    295         }
    296         mIsimUiccRecords = newIsimUiccRecords;
    297 
    298         // Update UsimRecords
    299         newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
    300         SIMRecords newSimRecords = null;
    301         if (newUiccApplication != null) {
    302             newSimRecords = (SIMRecords)newUiccApplication.getIccRecords();
    303         }
    304         if (mSimRecords != newSimRecords) {
    305             if (mSimRecords != null) {
    306                 log("Removing stale SIMRecords object.");
    307                 mSimRecords = null;
    308             }
    309             if (newSimRecords != null) {
    310                 log("New SIMRecords found");
    311                 mSimRecords = newSimRecords;
    312             }
    313         }
    314 
    315         super.onUpdateIccAvailability();
    316     }
    317 
    318     @Override
    319     protected void log(String s) {
    320             Rlog.d(LOG_LTE_TAG, s);
    321     }
    322 
    323     protected void loge(String s) {
    324             Rlog.e(LOG_LTE_TAG, s);
    325     }
    326 
    327     protected void loge(String s, Throwable e) {
    328         Rlog.e(LOG_LTE_TAG, s, e);
    329 }
    330 
    331     @Override
    332     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    333         pw.println("CDMALTEPhone extends:");
    334         super.dump(fd, pw, args);
    335     }
    336 }
    337