CDMALTEPhone.java revision b93bb3538c55f173f94a4ee7510d9d1521d8f731
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.IsimRecords; 55import com.android.internal.telephony.uicc.IsimUiccRecords; 56import com.android.internal.telephony.uicc.SIMRecords; 57import com.android.internal.telephony.uicc.UiccCardApplication; 58import com.android.internal.telephony.uicc.UiccController; 59import com.android.internal.telephony.ServiceStateTracker; 60import com.android.internal.telephony.TelephonyIntents; 61import com.android.internal.telephony.TelephonyProperties; 62 63import java.io.FileDescriptor; 64import java.io.PrintWriter; 65 66import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; 67import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; 68import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; 69 70import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_ACTIVATED; 71import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_DEACTIVATED; 72 73public class CDMALTEPhone extends CDMAPhone { 74 static final String LOG_LTE_TAG = "CDMALTEPhone"; 75 private static final boolean DBG = true; 76 77 /** CdmaLtePhone in addition to RuimRecords available from 78 * PhoneBase needs access to SIMRecords and IsimUiccRecords 79 */ 80 private SIMRecords mSimRecords; 81 private IsimUiccRecords mIsimUiccRecords; 82 83 // Constructors 84 public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 85 int phoneId) { 86 this(context, ci, notifier, false, phoneId); 87 } 88 89 public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 90 boolean unitTestMode, int phoneId) { 91 super(context, ci, notifier, phoneId); 92 93 Rlog.d(LOG_TAG, "CDMALTEPhone: constructor: sub = " + mPhoneId); 94 95 mDcTracker = new DcTracker(this); 96 97 } 98 99 // Constructors 100 public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) { 101 super(context, ci, notifier, false); 102 } 103 104 @Override 105 public void handleMessage (Message msg) { 106 switch (msg.what) { 107 case EVENT_SUBSCRIPTION_ACTIVATED: 108 log("EVENT_SUBSCRIPTION_ACTIVATED"); 109 onSubscriptionActivated(); 110 break; 111 112 case EVENT_SUBSCRIPTION_DEACTIVATED: 113 log("EVENT_SUBSCRIPTION_DEACTIVATED"); 114 onSubscriptionDeactivated(); 115 break; 116 117 default: 118 super.handleMessage(msg); 119 } 120 } 121 122 @Override 123 protected void initSstIcc() { 124 mSST = new CdmaLteServiceStateTracker(this); 125 } 126 127 @Override 128 public void dispose() { 129 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 130 super.dispose(); 131 } 132 } 133 134 @Override 135 public void removeReferences() { 136 super.removeReferences(); 137 } 138 139 @Override 140 public PhoneConstants.DataState getDataConnectionState(String apnType) { 141 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 142 143 if (mSST == null) { 144 // Radio Technology Change is ongoing, dispose() and 145 // removeReferences() have already been called 146 147 ret = PhoneConstants.DataState.DISCONNECTED; 148 } else if (mDcTracker.isApnTypeEnabled(apnType) == false) { 149 ret = PhoneConstants.DataState.DISCONNECTED; 150 } else { 151 switch (mDcTracker.getState(apnType)) { 152 case RETRYING: 153 case FAILED: 154 case IDLE: 155 ret = PhoneConstants.DataState.DISCONNECTED; 156 break; 157 158 case CONNECTED: 159 case DISCONNECTING: 160 if (mCT.mState != PhoneConstants.State.IDLE && 161 !mSST.isConcurrentVoiceAndDataAllowed()) { 162 ret = PhoneConstants.DataState.SUSPENDED; 163 } else { 164 ret = PhoneConstants.DataState.CONNECTED; 165 } 166 break; 167 168 case CONNECTING: 169 case SCANNING: 170 ret = PhoneConstants.DataState.CONNECTING; 171 break; 172 } 173 } 174 175 log("getDataConnectionState apnType=" + apnType + " ret=" + ret); 176 return ret; 177 } 178 179 /** 180 * Sets the "current" field in the telephony provider according to the 181 * build-time operator numeric property 182 * 183 * @return true for success; false otherwise. 184 */ 185 @Override 186 boolean updateCurrentCarrierInProvider(String operatorNumeric) { 187 boolean retVal; 188 if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) == null) { 189 if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null"); 190 retVal = super.updateCurrentCarrierInProvider(operatorNumeric); 191 } else { 192 if (DBG) log("updateCurrentCarrierInProvider not updated"); 193 retVal = true; 194 } 195 if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal); 196 return retVal; 197 } 198 199 @Override 200 public boolean updateCurrentCarrierInProvider() { 201 long currentDds = SubscriptionManager.getDefaultDataSubId(); 202 String operatorNumeric = getOperatorNumeric(); 203 204 Rlog.d(LOG_TAG, "updateCurrentCarrierInProvider: mSubscription = " + getSubId() 205 + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric); 206 207 if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) { 208 try { 209 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 210 ContentValues map = new ContentValues(); 211 map.put(Telephony.Carriers.NUMERIC, operatorNumeric); 212 mContext.getContentResolver().insert(uri, map); 213 return true; 214 } catch (SQLException e) { 215 Rlog.e(LOG_TAG, "Can't store current operator", e); 216 } 217 } 218 return false; 219 } 220 221 // return IMSI from USIM as subscriber ID. 222 @Override 223 public String getSubscriberId() { 224 return (mSimRecords != null) ? mSimRecords.getIMSI() : ""; 225 } 226 227 // return GID1 from USIM 228 @Override 229 public String getGroupIdLevel1() { 230 return (mSimRecords != null) ? mSimRecords.getGid1() : ""; 231 } 232 233 @Override 234 public String getImei() { 235 return mImei; 236 } 237 238 @Override 239 public String getDeviceSvn() { 240 return mImeiSv; 241 } 242 243 @Override 244 public IsimRecords getIsimRecords() { 245 return mIsimUiccRecords; 246 } 247 248 @Override 249 public String getMsisdn() { 250 return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null; 251 } 252 253 @Override 254 public void getAvailableNetworks(Message response) { 255 mCi.getAvailableNetworks(response); 256 } 257 258 @Override 259 protected void onUpdateIccAvailability() { 260 if (mUiccController == null ) { 261 return; 262 } 263 264 UiccCardApplication newUiccApplication = getUiccCardApplication(); 265 266 UiccCardApplication app = mUiccApplication.get(); 267 if (app != newUiccApplication) { 268 if (app != null) { 269 log("Removing stale icc objects."); 270 if (mIccRecords.get() != null) { 271 unregisterForRuimRecordEvents(); 272 } 273 mIccRecords.set(null); 274 mUiccApplication.set(null); 275 } 276 if (newUiccApplication != null) { 277 log("New Uicc application found"); 278 mUiccApplication.set(newUiccApplication); 279 mIccRecords.set(newUiccApplication.getIccRecords()); 280 registerForRuimRecordEvents(); 281 } 282 } 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 protected UiccCardApplication getUiccCardApplication() { 378 return mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2); 379 } 380 381 @Override 382 public void setSystemProperty(String property, String value) { 383 if(getUnitTestMode()) { 384 return; 385 } 386 TelephonyManager.setTelephonyProperty(property, getSubId(), value); 387 } 388 389 public String getSystemProperty(String property, String defValue) { 390 if(getUnitTestMode()) { 391 return null; 392 } 393 return TelephonyManager.getTelephonyProperty(property, getSubId(), defValue); 394 } 395 396 public void updateDataConnectionTracker() { 397 ((DcTracker)mDcTracker).update(); 398 } 399 400 public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) { 401 ((DcTracker)mDcTracker) 402 .setInternalDataEnabled(enable, onCompleteMsg); 403 } 404 405 public boolean setInternalDataEnabledFlag(boolean enable) { 406 return ((DcTracker)mDcTracker) 407 .setInternalDataEnabledFlag(enable); 408 } 409 410 /** 411 * @return operator numeric. 412 */ 413 public String getOperatorNumeric() { 414 String operatorNumeric = null; 415 416 if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) { 417 operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric"); 418 } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM 419 && mIccRecords != null && mIccRecords.get() != null) { 420 operatorNumeric = mIccRecords.get().getOperatorNumeric(); 421 } else { 422 Rlog.e(LOG_TAG, "getOperatorNumeric: Cannot retrieve operatorNumeric:" 423 + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + " mIccRecords = " 424 + ((mIccRecords != null) && (mIccRecords.get() != null) 425 ? mIccRecords.get().getRecordsLoaded() 426 : null)); 427 } 428 429 Rlog.d(LOG_TAG, "getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource 430 + " operatorNumeric = " + operatorNumeric); 431 432 return operatorNumeric; 433 } 434 public void registerForAllDataDisconnected(Handler h, int what, Object obj) { 435 ((DcTracker)mDcTracker) 436 .registerForAllDataDisconnected(h, what, obj); 437 } 438 439 public void unregisterForAllDataDisconnected(Handler h) { 440 ((DcTracker)mDcTracker) 441 .unregisterForAllDataDisconnected(h); 442 } 443 444 @Override 445 protected void log(String s) { 446 Rlog.d(LOG_LTE_TAG, s); 447 } 448 449 protected void loge(String s) { 450 Rlog.e(LOG_LTE_TAG, s); 451 } 452 453 protected void loge(String s, Throwable e) { 454 Rlog.e(LOG_LTE_TAG, s, e); 455 } 456 457 @Override 458 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 459 pw.println("CDMALTEPhone extends:"); 460 super.dump(fd, pw, args); 461 } 462} 463