1/* 2 * Copyrigh (C) 2011 The Android Open Source Project 3 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.internal.telephony.cdma; 19 20import android.content.ContentValues; 21import android.content.Context; 22import android.content.SharedPreferences; 23import android.database.SQLException; 24import android.net.Uri; 25import android.os.AsyncResult; 26import android.os.Message; 27import android.preference.PreferenceManager; 28import android.provider.Telephony; 29import android.telephony.Rlog; 30 31import com.android.internal.telephony.CommandsInterface; 32 33import com.android.internal.telephony.OperatorInfo; 34import com.android.internal.telephony.PhoneConstants; 35import com.android.internal.telephony.PhoneNotifier; 36import com.android.internal.telephony.PhoneProxy; 37import com.android.internal.telephony.SMSDispatcher; 38import com.android.internal.telephony.SmsBroadcastUndelivered; 39import com.android.internal.telephony.gsm.GsmSMSDispatcher; 40import com.android.internal.telephony.gsm.SmsMessage; 41import com.android.internal.telephony.uicc.IsimRecords; 42import com.android.internal.telephony.uicc.IsimUiccRecords; 43import com.android.internal.telephony.uicc.SIMRecords; 44import com.android.internal.telephony.uicc.UiccCardApplication; 45import com.android.internal.telephony.uicc.UiccController; 46 47import java.io.FileDescriptor; 48import java.io.PrintWriter; 49 50public class CDMALTEPhone extends CDMAPhone { 51 static final String LOG_LTE_TAG = "CDMALTEPhone"; 52 private static final boolean DBG = true; 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 } 76 77 @Override 78 public void handleMessage (Message msg) { 79 switch (msg.what) { 80 // handle the select network completion callbacks. 81 case EVENT_SET_NETWORK_MANUAL_COMPLETE: 82 handleSetSelectNetwork((AsyncResult) msg.obj); 83 break; 84 85 default: 86 super.handleMessage(msg); 87 } 88 } 89 90 @Override 91 protected void initSstIcc() { 92 mSST = new CdmaLteServiceStateTracker(this); 93 } 94 95 @Override 96 public void dispose() { 97 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 98 super.dispose(); 99 } 100 } 101 102 @Override 103 public void removeReferences() { 104 super.removeReferences(); 105 } 106 107 @Override 108 public PhoneConstants.DataState getDataConnectionState(String apnType) { 109 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 110 111 if (mSST == null) { 112 // Radio Technology Change is ongoing, dispose() and 113 // removeReferences() have already been called 114 115 ret = PhoneConstants.DataState.DISCONNECTED; 116 } else if (mDcTracker.isApnTypeEnabled(apnType) == false) { 117 ret = PhoneConstants.DataState.DISCONNECTED; 118 } else { 119 switch (mDcTracker.getState(apnType)) { 120 case RETRYING: 121 case FAILED: 122 case IDLE: 123 ret = PhoneConstants.DataState.DISCONNECTED; 124 break; 125 126 case CONNECTED: 127 case DISCONNECTING: 128 if (mCT.mState != PhoneConstants.State.IDLE && 129 !mSST.isConcurrentVoiceAndDataAllowed()) { 130 ret = PhoneConstants.DataState.SUSPENDED; 131 } else { 132 ret = PhoneConstants.DataState.CONNECTED; 133 } 134 break; 135 136 case CONNECTING: 137 case SCANNING: 138 ret = PhoneConstants.DataState.CONNECTING; 139 break; 140 } 141 } 142 143 log("getDataConnectionState apnType=" + apnType + " ret=" + ret); 144 return ret; 145 } 146 147 @Override 148 public void 149 selectNetworkManually(OperatorInfo network, 150 Message response) { 151 // wrap the response message in our own message along with 152 // the operator's id. 153 NetworkSelectMessage nsm = new NetworkSelectMessage(); 154 nsm.message = response; 155 nsm.operatorNumeric = network.getOperatorNumeric(); 156 nsm.operatorAlphaLong = network.getOperatorAlphaLong(); 157 158 // get the message 159 Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm); 160 161 mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg); 162 } 163 164 /** 165 * Used to track the settings upon completion of the network change. 166 */ 167 private void handleSetSelectNetwork(AsyncResult ar) { 168 // look for our wrapper within the asyncresult, skip the rest if it 169 // is null. 170 if (!(ar.userObj instanceof NetworkSelectMessage)) { 171 loge("unexpected result from user object."); 172 return; 173 } 174 175 NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj; 176 177 // found the object, now we send off the message we had originally 178 // attached to the request. 179 if (nsm.message != null) { 180 if (DBG) log("sending original message to recipient"); 181 AsyncResult.forMessage(nsm.message, ar.result, ar.exception); 182 nsm.message.sendToTarget(); 183 } 184 185 // open the shared preferences editor, and write the value. 186 // nsm.operatorNumeric is "" if we're in automatic.selection. 187 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 188 SharedPreferences.Editor editor = sp.edit(); 189 editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric); 190 editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong); 191 192 // commit and log the result. 193 if (! editor.commit()) { 194 loge("failed to commit network selection preference"); 195 } 196 197 } 198 199 @Override 200 public boolean updateCurrentCarrierInProvider() { 201 if (mSimRecords != null) { 202 try { 203 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 204 ContentValues map = new ContentValues(); 205 String operatorNumeric = mSimRecords.getOperatorNumeric(); 206 map.put(Telephony.Carriers.NUMERIC, operatorNumeric); 207 if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" + 208 operatorNumeric); 209 mContext.getContentResolver().insert(uri, map); 210 return true; 211 } catch (SQLException e) { 212 loge("Can't store current operator ret false", e); 213 } 214 } else { 215 if (DBG) log("updateCurrentCarrierInProvider mIccRecords == null ret false"); 216 } 217 return false; 218 } 219 220 // return IMSI from USIM as subscriber ID. 221 @Override 222 public String getSubscriberId() { 223 return (mSimRecords != null) ? mSimRecords.getIMSI() : ""; 224 } 225 226 // return GID1 from USIM 227 @Override 228 public String getGroupIdLevel1() { 229 return (mSimRecords != null) ? mSimRecords.getGid1() : ""; 230 } 231 232 @Override 233 public String getImei() { 234 return mImei; 235 } 236 237 @Override 238 public String getDeviceSvn() { 239 return mImeiSv; 240 } 241 242 @Override 243 public IsimRecords getIsimRecords() { 244 return mIsimUiccRecords; 245 } 246 247 @Override 248 public String getMsisdn() { 249 return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null; 250 } 251 252 @Override 253 public void getAvailableNetworks(Message response) { 254 mCi.getAvailableNetworks(response); 255 } 256 257 @Override 258 public void requestIsimAuthentication(String nonce, Message result) { 259 mCi.requestIsimAuthentication(nonce, result); 260 } 261 262 @Override 263 protected void onUpdateIccAvailability() { 264 if (mUiccController == null ) { 265 return; 266 } 267 268 // Update IsimRecords 269 UiccCardApplication newUiccApplication = 270 mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS); 271 IsimUiccRecords newIsimUiccRecords = null; 272 273 if (newUiccApplication != null) { 274 newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords(); 275 } 276 mIsimUiccRecords = newIsimUiccRecords; 277 278 // Update UsimRecords 279 newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP); 280 SIMRecords newSimRecords = null; 281 if (newUiccApplication != null) { 282 newSimRecords = (SIMRecords)newUiccApplication.getIccRecords(); 283 } 284 if (mSimRecords != newSimRecords) { 285 if (mSimRecords != null) { 286 log("Removing stale SIMRecords object."); 287 mSimRecords = null; 288 } 289 if (newSimRecords != null) { 290 log("New SIMRecords found"); 291 mSimRecords = newSimRecords; 292 } 293 } 294 295 super.onUpdateIccAvailability(); 296 } 297 298 @Override 299 protected void log(String s) { 300 Rlog.d(LOG_LTE_TAG, s); 301 } 302 303 protected void loge(String s) { 304 Rlog.e(LOG_LTE_TAG, s); 305 } 306 307 protected void loge(String s, Throwable e) { 308 Rlog.e(LOG_LTE_TAG, s, e); 309} 310 311 @Override 312 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 313 pw.println("CDMALTEPhone extends:"); 314 super.dump(fd, pw, args); 315 } 316} 317