CDMALTEPhone.java revision 80bc1e5a6f0bd91b886351997b797e01732c1c67
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.app.ActivityManagerNative; 20import android.content.ContentValues; 21import android.content.Context; 22import android.content.Intent; 23import android.content.SharedPreferences; 24import android.database.SQLException; 25import android.net.Uri; 26import android.os.AsyncResult; 27import android.os.Handler; 28import android.os.Message; 29import android.os.UserHandle; 30import android.preference.PreferenceManager; 31import android.os.PowerManager; 32import android.os.SystemProperties; 33import android.provider.Telephony; 34import android.text.TextUtils; 35import android.telephony.SubscriptionManager; 36import android.telephony.Rlog; 37 38import com.android.internal.telephony.CommandsInterface; 39import android.telephony.TelephonyManager; 40 41import com.android.internal.telephony.dataconnection.DcTracker; 42import com.android.internal.telephony.MccTable; 43import com.android.internal.telephony.OperatorInfo; 44import com.android.internal.telephony.PhoneConstants; 45import com.android.internal.telephony.PhoneNotifier; 46import com.android.internal.telephony.PhoneProxy; 47import com.android.internal.telephony.PhoneFactory; 48import com.android.internal.telephony.PhoneSubInfo; 49import com.android.internal.telephony.SMSDispatcher; 50import com.android.internal.telephony.SmsBroadcastUndelivered; 51import com.android.internal.telephony.Subscription; 52import com.android.internal.telephony.gsm.GsmSMSDispatcher; 53import com.android.internal.telephony.gsm.SmsMessage; 54import com.android.internal.telephony.uicc.IccRecords; 55import com.android.internal.telephony.uicc.IsimRecords; 56import com.android.internal.telephony.uicc.IsimUiccRecords; 57import com.android.internal.telephony.uicc.RuimRecords; 58import com.android.internal.telephony.uicc.SIMRecords; 59import com.android.internal.telephony.uicc.UiccCardApplication; 60import com.android.internal.telephony.uicc.UiccController; 61import com.android.internal.telephony.ServiceStateTracker; 62import com.android.internal.telephony.TelephonyIntents; 63import com.android.internal.telephony.TelephonyProperties; 64 65import java.io.FileDescriptor; 66import java.io.PrintWriter; 67 68import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; 69import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; 70import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; 71 72import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_ACTIVATED; 73import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_DEACTIVATED; 74 75public class CDMALTEPhone extends CDMAPhone { 76 static final String LOG_LTE_TAG = "CDMALTEPhone"; 77 private static final boolean DBG = true; 78 79 /** CdmaLtePhone in addition to RuimRecords available from 80 * PhoneBase needs access to SIMRecords and IsimUiccRecords 81 */ 82 private SIMRecords mSimRecords; 83 private IsimUiccRecords mIsimUiccRecords; 84 85 // Constructors 86 public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 87 int phoneId) { 88 this(context, ci, notifier, false, phoneId); 89 } 90 91 public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 92 boolean unitTestMode, int phoneId) { 93 super(context, ci, notifier, phoneId); 94 95 Rlog.d(LOG_TAG, "CDMALTEPhone: constructor: sub = " + mPhoneId); 96 97 mDcTracker = new DcTracker(this); 98 99 } 100 101 // Constructors 102 public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) { 103 super(context, ci, notifier, false); 104 } 105 106 @Override 107 public void handleMessage (Message msg) { 108 switch (msg.what) { 109 case EVENT_SUBSCRIPTION_ACTIVATED: 110 log("EVENT_SUBSCRIPTION_ACTIVATED"); 111 onSubscriptionActivated(); 112 break; 113 114 case EVENT_SUBSCRIPTION_DEACTIVATED: 115 log("EVENT_SUBSCRIPTION_DEACTIVATED"); 116 onSubscriptionDeactivated(); 117 break; 118 119 default: 120 super.handleMessage(msg); 121 } 122 } 123 124 @Override 125 protected void initSstIcc() { 126 mSST = new CdmaLteServiceStateTracker(this); 127 } 128 129 @Override 130 public void dispose() { 131 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 132 super.dispose(); 133 } 134 } 135 136 @Override 137 public void removeReferences() { 138 super.removeReferences(); 139 } 140 141 @Override 142 public PhoneConstants.DataState getDataConnectionState(String apnType) { 143 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 144 145 if (mSST == null) { 146 // Radio Technology Change is ongoing, dispose() and 147 // removeReferences() have already been called 148 149 ret = PhoneConstants.DataState.DISCONNECTED; 150 } else if (mDcTracker.isApnTypeEnabled(apnType) == false) { 151 ret = PhoneConstants.DataState.DISCONNECTED; 152 } else { 153 switch (mDcTracker.getState(apnType)) { 154 case RETRYING: 155 case FAILED: 156 case IDLE: 157 ret = PhoneConstants.DataState.DISCONNECTED; 158 break; 159 160 case CONNECTED: 161 case DISCONNECTING: 162 if (mCT.mState != PhoneConstants.State.IDLE && 163 !mSST.isConcurrentVoiceAndDataAllowed()) { 164 ret = PhoneConstants.DataState.SUSPENDED; 165 } else { 166 ret = PhoneConstants.DataState.CONNECTED; 167 } 168 break; 169 170 case CONNECTING: 171 case SCANNING: 172 ret = PhoneConstants.DataState.CONNECTING; 173 break; 174 } 175 } 176 177 log("getDataConnectionState apnType=" + apnType + " ret=" + ret); 178 return ret; 179 } 180 181 /** 182 * Sets the "current" field in the telephony provider according to the 183 * build-time operator numeric property 184 * 185 * @return true for success; false otherwise. 186 */ 187 @Override 188 boolean updateCurrentCarrierInProvider(String operatorNumeric) { 189 boolean retVal; 190 if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) == null) { 191 if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null"); 192 retVal = super.updateCurrentCarrierInProvider(operatorNumeric); 193 } else { 194 if (DBG) log("updateCurrentCarrierInProvider not updated"); 195 retVal = true; 196 } 197 if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal); 198 return retVal; 199 } 200 201 @Override 202 public boolean updateCurrentCarrierInProvider() { 203 long currentDds = SubscriptionManager.getDefaultDataSubId(); 204 String operatorNumeric = getOperatorNumeric(); 205 206 Rlog.d(LOG_TAG, "updateCurrentCarrierInProvider: mSubscription = " + getSubId() 207 + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric); 208 209 if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) { 210 try { 211 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 212 ContentValues map = new ContentValues(); 213 map.put(Telephony.Carriers.NUMERIC, operatorNumeric); 214 mContext.getContentResolver().insert(uri, map); 215 return true; 216 } catch (SQLException e) { 217 Rlog.e(LOG_TAG, "Can't store current operator", e); 218 } 219 } 220 return false; 221 } 222 223 // return IMSI from USIM as subscriber ID. 224 @Override 225 public String getSubscriberId() { 226 return (mSimRecords != null) ? mSimRecords.getIMSI() : ""; 227 } 228 229 // return GID1 from USIM 230 @Override 231 public String getGroupIdLevel1() { 232 return (mSimRecords != null) ? mSimRecords.getGid1() : ""; 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 mCi.getAvailableNetworks(response); 258 } 259 260 @Override 261 protected void onUpdateIccAvailability() { 262 if (mUiccController == null ) { 263 return; 264 } 265 266 // Update IsimRecords 267 UiccCardApplication newUiccApplication = 268 mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS); 269 IsimUiccRecords newIsimUiccRecords = null; 270 271 if (newUiccApplication != null) { 272 newIsimUiccRecords = (IsimUiccRecords) newUiccApplication.getIccRecords(); 273 } 274 mIsimUiccRecords = newIsimUiccRecords; 275 276 // Update UsimRecords 277 newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP); 278 SIMRecords newSimRecords = null; 279 if (newUiccApplication != null) { 280 newSimRecords = (SIMRecords) newUiccApplication.getIccRecords(); 281 } 282 mSimRecords = newSimRecords; 283 284 super.onUpdateIccAvailability(); 285 } 286 287 @Override 288 protected void init(Context context, PhoneNotifier notifier) { 289 mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA); 290 mCT = new CdmaCallTracker(this); 291 mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCi, this, 292 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 293 mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this); 294 mSubInfo = new PhoneSubInfo(this); 295 mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML); 296 297 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 298 mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 299 mCi.registerForOn(this, EVENT_RADIO_ON, null); 300 mCi.setOnSuppServiceNotification(this, EVENT_SSN, null); 301 mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); 302 mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null); 303 mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE, 304 null); 305 306 PowerManager pm 307 = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 308 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG); 309 310 // This is needed to handle phone process crashes 311 String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 312 mIsPhoneInEcmState = inEcm.equals("true"); 313 if (mIsPhoneInEcmState) { 314 // Send a message which will invoke handleExitEmergencyCallbackMode 315 mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); 316 } 317 318 // get the string that specifies the carrier OTA Sp number 319 mCarrierOtaSpNumSchema = SystemProperties.get( 320 TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,""); 321 322 // Notify voicemails. 323 notifier.notifyMessageWaitingChanged(this); 324 setProperties(); 325 } 326 327 private void onSubscriptionActivated() { 328// mSubscriptionData = SubscriptionManager.getCurrentSubscription(mSubscription); 329 330 log("SUBSCRIPTION ACTIVATED : slotId : " + mSubscriptionData.slotId 331 + " appid : " + mSubscriptionData.m3gpp2Index 332 + " subId : " + mSubscriptionData.subId 333 + " subStatus : " + mSubscriptionData.subStatus); 334 335 // Make sure properties are set for proper subscription. 336 setProperties(); 337 338 onUpdateIccAvailability(); 339 mSST.sendMessage(mSST.obtainMessage(ServiceStateTracker.EVENT_ICC_CHANGED)); 340 ((CdmaLteServiceStateTracker)mSST).updateCdmaSubscription(); 341 ((DcTracker)mDcTracker).updateRecords(); 342 } 343 344 private void onSubscriptionDeactivated() { 345 log("SUBSCRIPTION DEACTIVATED"); 346 // resetSubSpecifics 347 mSubscriptionData = null; 348 } 349 350 // Set the properties per subscription 351 private void setProperties() { 352 //Change the system property 353 setSystemProperty(TelephonyProperties.CURRENT_ACTIVE_PHONE, 354 new Integer(PhoneConstants.PHONE_TYPE_CDMA).toString()); 355 // Sets operator alpha property by retrieving from build-time system property 356 String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha"); 357 if (!TextUtils.isEmpty(operatorAlpha)) { 358 setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha); 359 } 360 361 // Sets operator numeric property by retrieving from build-time system property 362 String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC); 363 log("update icc_operator_numeric=" + operatorNumeric); 364 if (!TextUtils.isEmpty(operatorNumeric)) { 365 setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric); 366 // Sets iso country property by retrieving from build-time system property 367 setIsoCountryProperty(operatorNumeric); 368 // Updates MCC MNC device configuration information 369 log("update mccmnc=" + operatorNumeric); 370 MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false); 371 } 372 // Sets current entry in the telephony carrier table 373 updateCurrentCarrierInProvider(); 374 } 375 376 @Override 377 public void setSystemProperty(String property, String value) { 378 if(getUnitTestMode()) { 379 return; 380 } 381 TelephonyManager.setTelephonyProperty(property, getSubId(), value); 382 } 383 384 public String getSystemProperty(String property, String defValue) { 385 if(getUnitTestMode()) { 386 return null; 387 } 388 return TelephonyManager.getTelephonyProperty(property, getSubId(), defValue); 389 } 390 391 public void updateDataConnectionTracker() { 392 ((DcTracker)mDcTracker).update(); 393 } 394 395 public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) { 396 ((DcTracker)mDcTracker) 397 .setInternalDataEnabled(enable, onCompleteMsg); 398 } 399 400 public boolean setInternalDataEnabledFlag(boolean enable) { 401 return ((DcTracker)mDcTracker) 402 .setInternalDataEnabledFlag(enable); 403 } 404 405 /** 406 * @return operator numeric. 407 */ 408 public String getOperatorNumeric() { 409 String operatorNumeric = null; 410 IccRecords curIccRecords = null; 411 if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) { 412 operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric"); 413 } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM) { 414 curIccRecords = mSimRecords; 415 if (curIccRecords != null) { 416 operatorNumeric = curIccRecords.getOperatorNumeric(); 417 } else { 418 curIccRecords = mIccRecords.get(); 419 if (curIccRecords != null && (curIccRecords instanceof RuimRecords)) { 420 RuimRecords csim = (RuimRecords) curIccRecords; 421 operatorNumeric = csim.getRUIMOperatorNumeric(); 422 } 423 } 424 } 425 if (operatorNumeric == null) { 426 Rlog.e(LOG_TAG, "getOperatorNumeric: Cannot retrieve operatorNumeric:" 427 + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + " mIccRecords = " 428 + ((curIccRecords != null) ? curIccRecords.getRecordsLoaded() : null)); 429 } 430 431 Rlog.d(LOG_TAG, "getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource 432 + " operatorNumeric = " + operatorNumeric); 433 434 return operatorNumeric; 435 } 436 public void registerForAllDataDisconnected(Handler h, int what, Object obj) { 437 ((DcTracker)mDcTracker) 438 .registerForAllDataDisconnected(h, what, obj); 439 } 440 441 public void unregisterForAllDataDisconnected(Handler h) { 442 ((DcTracker)mDcTracker) 443 .unregisterForAllDataDisconnected(h); 444 } 445 446 @Override 447 protected void log(String s) { 448 Rlog.d(LOG_LTE_TAG, s); 449 } 450 451 protected void loge(String s) { 452 Rlog.e(LOG_LTE_TAG, s); 453 } 454 455 protected void loge(String s, Throwable e) { 456 Rlog.e(LOG_LTE_TAG, s, e); 457 } 458 459 @Override 460 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 461 pw.println("CDMALTEPhone extends:"); 462 super.dump(fd, pw, args); 463 } 464} 465