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