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