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