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