1 /* 2 * Copyright (C) 2013 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; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.net.Uri; 26 import android.os.AsyncResult; 27 import android.os.BadParcelableException; 28 import android.os.Bundle; 29 import android.os.PersistableBundle; 30 import android.telephony.AccessNetworkConstants; 31 import android.telephony.CellSignalStrengthLte; 32 import android.telephony.NetworkRegistrationInfo; 33 import android.telephony.ServiceState; 34 import android.telephony.SignalStrength; 35 import android.telephony.TelephonyManager; 36 import android.telephony.ims.ImsCallProfile; 37 import android.telephony.ims.ImsConferenceState; 38 import android.telephony.ims.ImsExternalCallState; 39 import android.telephony.ims.ImsReasonInfo; 40 41 import com.android.ims.ImsCall; 42 import com.android.internal.telephony.gsm.SuppServiceNotification; 43 import com.android.internal.telephony.imsphone.ImsExternalCallTracker; 44 import com.android.internal.telephony.imsphone.ImsPhone; 45 import com.android.internal.telephony.imsphone.ImsPhoneCall; 46 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker; 47 import com.android.internal.telephony.test.TestConferenceEventPackageParser; 48 import com.android.internal.telephony.util.TelephonyUtils; 49 import com.android.telephony.Rlog; 50 51 import java.io.File; 52 import java.io.FileInputStream; 53 import java.io.FileNotFoundException; 54 import java.lang.reflect.Field; 55 import java.util.ArrayList; 56 import java.util.Arrays; 57 import java.util.List; 58 59 /** 60 * Telephony tester receives the following intents where {name} is the phone name 61 * 62 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_detached 63 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_attached 64 * adb shell am broadcast -a com.android.internal.telephony.TestConferenceEventPackage -e filename 65 * test_filename.xml 66 * adb shell am broadcast -a com.android.internal.telephony.TestServiceState --ei data_rat 10 --ei 67 * data_roaming_type 3 68 * adb shell am broadcast -a com.android.internal.telephony.TestServiceState --es action reset 69 * 70 */ 71 public class TelephonyTester { 72 private static final boolean DBG = true; 73 74 /** 75 * Test-only intent used to send a test conference event package to the IMS framework. 76 */ 77 private static final String ACTION_TEST_CONFERENCE_EVENT_PACKAGE = 78 "com.android.internal.telephony.TestConferenceEventPackage"; 79 80 /** 81 * Test-only intent used to send a test dialog event package to the IMS framework. 82 */ 83 private static final String ACTION_TEST_DIALOG_EVENT_PACKAGE = 84 "com.android.internal.telephony.TestDialogEventPackage"; 85 86 private static final String EXTRA_FILENAME = "filename"; 87 /** 88 * Used to inject the conference event package by bypassing the ImsCall and doing the 89 * injection via ImsPhoneCallTracker. This is useful in scenarios where the 90 * adb shell cmd phone ims conference-event-package disable 91 * command is used to disable network CEP data and it is desired to still inject CEP data. 92 * Where the network CEP data is not explicitly disabled using the command above, it is not 93 * necessary to bypass the ImsCall. 94 */ 95 private static final String EXTRA_BYPASS_IMSCALL = "bypassImsCall"; 96 private static final String EXTRA_STARTPACKAGE = "startPackage"; 97 private static final String EXTRA_SENDPACKAGE = "sendPackage"; 98 private static final String EXTRA_DIALOGID = "dialogId"; 99 private static final String EXTRA_NUMBER = "number"; 100 private static final String EXTRA_STATE = "state"; 101 private static final String EXTRA_CANPULL = "canPull"; 102 103 /** 104 * Test-only intent used to trigger supp service notification failure. 105 */ 106 private static final String ACTION_TEST_SUPP_SRVC_FAIL = 107 "com.android.internal.telephony.TestSuppSrvcFail"; 108 private static final String EXTRA_FAILURE_CODE = "failureCode"; 109 110 /** 111 * Test-only intent used to trigger the signalling which occurs when a handover to WIFI fails. 112 */ 113 private static final String ACTION_TEST_HANDOVER_FAIL = 114 "com.android.internal.telephony.TestHandoverFail"; 115 116 /** 117 * Test-only intent used to trigger signalling of a 118 * {@link com.android.internal.telephony.gsm.SuppServiceNotification} to the {@link ImsPhone}. 119 * Use {@link #EXTRA_CODE} to specify the 120 * {@link com.android.internal.telephony.gsm.SuppServiceNotification#code}. 121 */ 122 private static final String ACTION_TEST_SUPP_SRVC_NOTIFICATION = 123 "com.android.internal.telephony.TestSuppSrvcNotification"; 124 125 private static final String EXTRA_CODE = "code"; 126 private static final String EXTRA_TYPE = "type"; 127 128 /** 129 * Test-only intent used to trigger signalling that an IMS call is an emergency call. 130 */ 131 private static final String ACTION_TEST_IMS_E_CALL = 132 "com.android.internal.telephony.TestImsECall"; 133 134 /** 135 * Test-only intent used to trigger signalling that an IMS call received a DTMF tone. 136 */ 137 private static final String ACTION_TEST_RECEIVE_DTMF = 138 "com.android.internal.telephony.TestReceiveDtmf"; 139 140 private static final String EXTRA_DIGIT = "digit"; 141 142 /** 143 * Test-only intent used to trigger a change to the current call's phone number. 144 * Use the {@link #EXTRA_NUMBER} extra to specify the new phone number. 145 */ 146 private static final String ACTION_TEST_CHANGE_NUMBER = 147 "com.android.internal.telephony.TestChangeNumber"; 148 149 private static final String ACTION_TEST_SERVICE_STATE = 150 "com.android.internal.telephony.TestServiceState"; 151 152 private static final String EXTRA_ACTION = "action"; 153 private static final String EXTRA_PHONE_ID = "phone_id"; 154 private static final String EXTRA_VOICE_RAT = "voice_rat"; 155 private static final String EXTRA_DATA_RAT = "data_rat"; 156 private static final String EXTRA_VOICE_REG_STATE = "voice_reg_state"; 157 private static final String EXTRA_DATA_REG_STATE = "data_reg_state"; 158 private static final String EXTRA_VOICE_ROAMING_TYPE = "voice_roaming_type"; 159 private static final String EXTRA_DATA_ROAMING_TYPE = "data_roaming_type"; 160 private static final String EXTRA_NR_FREQUENCY_RANGE = "nr_frequency_range"; 161 private static final String EXTRA_NR_STATE = "nr_state"; 162 private static final String EXTRA_OPERATOR = "operator"; 163 private static final String EXTRA_OPERATOR_RAW = "operator_raw"; 164 165 private static final String ACTION_RESET = "reset"; 166 167 private String mLogTag; 168 169 private static List<ImsExternalCallState> mImsExternalCallStates = null; 170 171 private Intent mServiceStateTestIntent; 172 private SignalStrengthTestable mSignalStrengthTest; 173 174 private Phone mPhone; 175 176 // The static intent receiver one for all instances and we assume this 177 // is running on the same thread as Dcc. 178 protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 179 @Override 180 public void onReceive(Context context, Intent intent) { 181 String action = intent.getAction(); 182 try { 183 if (DBG) log("sIntentReceiver.onReceive: action=" + action); 184 if (action.equals(mPhone.getActionDetached())) { 185 log("simulate detaching"); 186 mPhone.getServiceStateTracker().mDetachedRegistrants.get( 187 AccessNetworkConstants.TRANSPORT_TYPE_WWAN).notifyRegistrants(); 188 } else if (action.equals(mPhone.getActionAttached())) { 189 log("simulate attaching"); 190 mPhone.getServiceStateTracker().mAttachedRegistrants.get( 191 AccessNetworkConstants.TRANSPORT_TYPE_WWAN).notifyRegistrants(); 192 } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) { 193 log("inject simulated conference event package"); 194 handleTestConferenceEventPackage(context, 195 intent.getStringExtra(EXTRA_FILENAME), 196 intent.getBooleanExtra(EXTRA_BYPASS_IMSCALL, false)); 197 } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) { 198 log("handle test dialog event package intent"); 199 handleTestDialogEventPackageIntent(intent); 200 } else if (action.equals(ACTION_TEST_SUPP_SRVC_FAIL)) { 201 log("handle test supp svc failed intent"); 202 handleSuppServiceFailedIntent(intent); 203 } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) { 204 log("handle handover fail test intent"); 205 handleHandoverFailedIntent(); 206 } else if (action.equals(ACTION_TEST_SUPP_SRVC_NOTIFICATION)) { 207 log("handle supp service notification test intent"); 208 sendTestSuppServiceNotification(intent); 209 } else if (action.equals(ACTION_TEST_SERVICE_STATE)) { 210 log("handle test service state changed intent"); 211 setServiceStateTestIntent(intent); 212 } else if (action.equals(ACTION_TEST_IMS_E_CALL)) { 213 log("handle test IMS ecall intent"); 214 testImsECall(); 215 } else if (action.equals(ACTION_TEST_RECEIVE_DTMF)) { 216 log("handle test DTMF intent"); 217 testImsReceiveDtmf(intent); 218 } else if (action.equals(ACTION_TEST_CHANGE_NUMBER)) { 219 log("handle test change number intent"); 220 testChangeNumber(intent); 221 } else { 222 if (DBG) log("onReceive: unknown action=" + action); 223 } 224 } catch (BadParcelableException e) { 225 Rlog.w(mLogTag, e); 226 } 227 } 228 }; 229 TelephonyTester(Phone phone)230 TelephonyTester(Phone phone) { 231 mPhone = phone; 232 233 if (TelephonyUtils.IS_DEBUGGABLE) { 234 mLogTag = "TelephonyTester-" + mPhone.getPhoneId(); 235 IntentFilter filter = new IntentFilter(); 236 237 filter.addAction(mPhone.getActionDetached()); 238 log("register for intent action=" + mPhone.getActionDetached()); 239 240 filter.addAction(mPhone.getActionAttached()); 241 log("register for intent action=" + mPhone.getActionAttached()); 242 243 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 244 log("register for intent action=" + ACTION_TEST_CONFERENCE_EVENT_PACKAGE); 245 filter.addAction(ACTION_TEST_CONFERENCE_EVENT_PACKAGE); 246 filter.addAction(ACTION_TEST_DIALOG_EVENT_PACKAGE); 247 filter.addAction(ACTION_TEST_SUPP_SRVC_FAIL); 248 filter.addAction(ACTION_TEST_HANDOVER_FAIL); 249 filter.addAction(ACTION_TEST_SUPP_SRVC_NOTIFICATION); 250 filter.addAction(ACTION_TEST_IMS_E_CALL); 251 filter.addAction(ACTION_TEST_RECEIVE_DTMF); 252 mImsExternalCallStates = new ArrayList<ImsExternalCallState>(); 253 } 254 255 filter.addAction(ACTION_TEST_SERVICE_STATE); 256 log("register for intent action=" + ACTION_TEST_SERVICE_STATE); 257 258 filter.addAction(ACTION_TEST_CHANGE_NUMBER); 259 log("register for intent action=" + ACTION_TEST_CHANGE_NUMBER); 260 phone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone.getHandler(), 261 Context.RECEIVER_EXPORTED); 262 } 263 } 264 dispose()265 void dispose() { 266 if (TelephonyUtils.IS_DEBUGGABLE) { 267 mPhone.getContext().unregisterReceiver(mIntentReceiver); 268 } 269 } 270 log(String s)271 private void log(String s) { 272 Rlog.d(mLogTag, s); 273 } 274 handleSuppServiceFailedIntent(Intent intent)275 private void handleSuppServiceFailedIntent(Intent intent) { 276 ImsPhone imsPhone = (ImsPhone) mPhone; 277 if (imsPhone == null) { 278 return; 279 } 280 int code = intent.getIntExtra(EXTRA_FAILURE_CODE, 0); 281 imsPhone.notifySuppServiceFailed(PhoneInternalInterface.SuppService.values()[code]); 282 } 283 handleHandoverFailedIntent()284 private void handleHandoverFailedIntent() { 285 // Attempt to get the active IMS call 286 ImsCall imsCall = getImsCall(); 287 if (imsCall == null) { 288 return; 289 } 290 291 imsCall.getImsCallSessionListenerProxy().callSessionHandoverFailed(imsCall.getCallSession(), 292 TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_IWLAN, 293 new ImsReasonInfo()); 294 } 295 296 /** 297 * Handles request to send a test conference event package to the active Ims call. 298 * 299 * @see com.android.internal.telephony.test.TestConferenceEventPackageParser 300 * @param context The context. 301 * @param fileName The name of the test conference event package file to read. 302 */ handleTestConferenceEventPackage(Context context, String fileName, boolean isBypassingImsCall)303 private void handleTestConferenceEventPackage(Context context, String fileName, 304 boolean isBypassingImsCall) { 305 // Attempt to get the active IMS call before parsing the test XML file. 306 ImsPhone imsPhone = (ImsPhone) mPhone; 307 if (imsPhone == null) { 308 return; 309 } 310 311 ImsPhoneCallTracker tracker = (ImsPhoneCallTracker) imsPhone.getCallTracker(); 312 313 File packageFile = new File(context.getFilesDir(), fileName); 314 final FileInputStream is; 315 try { 316 is = new FileInputStream(packageFile); 317 } catch (FileNotFoundException ex) { 318 log("Test conference event package file not found: " + packageFile.getAbsolutePath()); 319 return; 320 } 321 322 TestConferenceEventPackageParser parser = new TestConferenceEventPackageParser(is); 323 ImsConferenceState imsConferenceState = parser.parse(); 324 if (imsConferenceState == null) { 325 return; 326 } 327 328 if (isBypassingImsCall) { 329 tracker.injectTestConferenceState(imsConferenceState); 330 } else { 331 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 332 if (imsPhoneCall == null) { 333 return; 334 } 335 336 ImsCall imsCall = imsPhoneCall.getImsCall(); 337 if (imsCall == null) { 338 return; 339 } 340 341 imsCall.conferenceStateUpdated(imsConferenceState); 342 } 343 } 344 345 /** 346 * Handles intents containing test dialog event package data. 347 * 348 * @param intent 349 */ handleTestDialogEventPackageIntent(Intent intent)350 private void handleTestDialogEventPackageIntent(Intent intent) { 351 ImsPhone imsPhone = (ImsPhone) mPhone; 352 if (imsPhone == null) { 353 return; 354 } 355 ImsExternalCallTracker externalCallTracker = imsPhone.getExternalCallTracker(); 356 if (externalCallTracker == null) { 357 return; 358 } 359 360 if (intent.hasExtra(EXTRA_STARTPACKAGE)) { 361 mImsExternalCallStates.clear(); 362 } else if (intent.hasExtra(EXTRA_SENDPACKAGE)) { 363 externalCallTracker.refreshExternalCallState(mImsExternalCallStates); 364 mImsExternalCallStates.clear(); 365 } else if (intent.hasExtra(EXTRA_DIALOGID)) { 366 ImsExternalCallState state = new ImsExternalCallState( 367 intent.getIntExtra(EXTRA_DIALOGID, 0), 368 Uri.parse(intent.getStringExtra(EXTRA_NUMBER)), 369 intent.getBooleanExtra(EXTRA_CANPULL, true), 370 intent.getIntExtra(EXTRA_STATE, 371 ImsExternalCallState.CALL_STATE_CONFIRMED), 372 ImsCallProfile.CALL_TYPE_VOICE, 373 false /* isHeld */ 374 ); 375 mImsExternalCallStates.add(state); 376 } 377 } 378 sendTestSuppServiceNotification(Intent intent)379 private void sendTestSuppServiceNotification(Intent intent) { 380 if (intent.hasExtra(EXTRA_CODE) && intent.hasExtra(EXTRA_TYPE)) { 381 int code = intent.getIntExtra(EXTRA_CODE, -1); 382 int type = intent.getIntExtra(EXTRA_TYPE, -1); 383 ImsPhone imsPhone = (ImsPhone) mPhone; 384 if (imsPhone == null) { 385 return; 386 } 387 log("Test supp service notification:" + code); 388 SuppServiceNotification suppServiceNotification = new SuppServiceNotification(); 389 suppServiceNotification.code = code; 390 suppServiceNotification.notificationType = type; 391 imsPhone.notifySuppSvcNotification(suppServiceNotification); 392 } 393 } 394 395 /** 396 * Testable signal strength that mocks its fields. 397 */ 398 private class SignalStrengthTestable extends SignalStrength { SignalStrengthTestable()399 private SignalStrengthTestable() { 400 super(); 401 } 402 mockLevel(int level)403 public void mockLevel(int level) { 404 try { 405 Field lteField = SignalStrength.class.getDeclaredField("mLte"); 406 lteField.setAccessible(true); 407 CellSignalStrengthLte lte = (CellSignalStrengthLte) lteField.get(this); 408 409 Field lvlField = CellSignalStrengthLte.class.getDeclaredField("mLevel"); 410 lvlField.setAccessible(true); 411 lvlField.set(lte, level); 412 } catch (Exception e) { 413 log("SignalStrengthTestable: mockLevel " + e); 414 } 415 } 416 417 @Override updateLevel(PersistableBundle cc, ServiceState ss)418 public void updateLevel(PersistableBundle cc, ServiceState ss) { 419 log("SignalStrengthTestable: updateLevel: do nothing "); 420 } 421 422 @Override toString()423 public String toString() { 424 return "SignalStrengthTestable-" + getLevel(); 425 } 426 } 427 428 /** {@link android.telephony.SignalStrength} */ setSignalStrength(int level)429 public void setSignalStrength(int level) { 430 if (level > -1) { 431 log("setSignalStrength: level " + level); 432 mSignalStrengthTest = new SignalStrengthTestable(); 433 mSignalStrengthTest.mockLevel(level); 434 AsyncResult ar = new AsyncResult(null, mSignalStrengthTest, null); 435 mPhone.getSignalStrengthController().sendMessage(mPhone.getSignalStrengthController() 436 .obtainMessage(SignalStrengthController.EVENT_POLL_SIGNAL_STRENGTH_DONE, ar)); 437 } else { 438 log("setSignalStrength: clear mock"); 439 mSignalStrengthTest = null; 440 mPhone.getSignalStrengthController().getSignalStrengthFromCi(); 441 } 442 } 443 444 /** {@link android.telephony.SignalStrength} */ 445 @Nullable getOverriddenSignalStrength()446 public SignalStrength getOverriddenSignalStrength() { 447 return mSignalStrengthTest; 448 } 449 450 /** 451 * Set the service state test intent. 452 * 453 * @param intent The service state test intent. 454 */ setServiceStateTestIntent(@onNull Intent intent)455 public void setServiceStateTestIntent(@NonNull Intent intent) { 456 // Don't process if the intent is not prepared for this phone slot. 457 if (mPhone.getPhoneId() != intent.getIntExtra(EXTRA_PHONE_ID, mPhone.getPhoneId())) return; 458 mServiceStateTestIntent = intent; 459 // Trigger the service state update. The replacement will be done in 460 // overrideServiceState(). 461 mPhone.getServiceStateTracker().sendEmptyMessage( 462 ServiceStateTracker.EVENT_NETWORK_STATE_CHANGED); 463 } 464 overrideServiceState(ServiceState ss)465 void overrideServiceState(ServiceState ss) { 466 if (mServiceStateTestIntent == null || ss == null) return; 467 if (mServiceStateTestIntent.hasExtra(EXTRA_ACTION) 468 && ACTION_RESET.equals(mServiceStateTestIntent.getStringExtra(EXTRA_ACTION))) { 469 log("Service state override reset"); 470 return; 471 } 472 473 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_REG_STATE)) { 474 int state = mServiceStateTestIntent.getIntExtra(EXTRA_DATA_REG_STATE, 475 ServiceState.STATE_OUT_OF_SERVICE); 476 ss.setVoiceRegState(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_REG_STATE, 477 ServiceState.STATE_OUT_OF_SERVICE)); 478 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 479 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 480 NetworkRegistrationInfo.Builder builder = new NetworkRegistrationInfo.Builder(nri); 481 if (state == ServiceState.STATE_IN_SERVICE) { 482 builder.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME); 483 } else { 484 builder.setRegistrationState( 485 NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING); 486 } 487 ss.addNetworkRegistrationInfo(builder.build()); 488 log("Override voice service state with " + ss.getState()); 489 } 490 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_REG_STATE)) { 491 int state = mServiceStateTestIntent.getIntExtra(EXTRA_DATA_REG_STATE, 492 ServiceState.STATE_OUT_OF_SERVICE); 493 ss.setDataRegState(state); 494 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 495 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 496 NetworkRegistrationInfo.Builder builder = new NetworkRegistrationInfo.Builder(nri); 497 if (state == ServiceState.STATE_IN_SERVICE) { 498 builder.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME); 499 } else { 500 builder.setRegistrationState( 501 NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING); 502 } 503 ss.addNetworkRegistrationInfo(builder.build()); 504 log("Override data service state with " + ss.getDataRegistrationState()); 505 } 506 if (mServiceStateTestIntent.hasExtra(EXTRA_OPERATOR)) { 507 String[] data = mServiceStateTestIntent.getStringExtra(EXTRA_OPERATOR).split(","); 508 String operatorAlphaLong = data.length > 0 ? data[0] : ""; 509 String operatorAlphaShort = data.length > 1 ? data[1] : operatorAlphaLong; 510 String operatorNumeric = data.length > 2 ? data[2] : ""; 511 ss.setOperatorName(operatorAlphaLong, operatorAlphaShort, operatorNumeric); 512 log("Override operator with " + Arrays.toString(data)); 513 } 514 if (mServiceStateTestIntent.hasExtra(EXTRA_OPERATOR_RAW)) { 515 String operator_raw = mServiceStateTestIntent.getStringExtra(EXTRA_OPERATOR_RAW); 516 ss.setOperatorAlphaLongRaw(operator_raw); 517 ss.setOperatorAlphaShortRaw(operator_raw); 518 log("Override operator_raw with " + operator_raw); 519 } 520 if (mServiceStateTestIntent.hasExtra(EXTRA_NR_FREQUENCY_RANGE)) { 521 ss.setNrFrequencyRange(mServiceStateTestIntent.getIntExtra(EXTRA_NR_FREQUENCY_RANGE, 522 ServiceState.FREQUENCY_RANGE_UNKNOWN)); 523 log("Override NR frequency range with " + ss.getNrFrequencyRange()); 524 } 525 if (mServiceStateTestIntent.hasExtra(EXTRA_NR_STATE)) { 526 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 527 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 528 if (nri == null) { 529 nri = new NetworkRegistrationInfo.Builder() 530 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 531 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 532 .build(); 533 } 534 nri.setNrState(mServiceStateTestIntent.getIntExtra(EXTRA_NR_STATE, 535 NetworkRegistrationInfo.NR_STATE_NONE)); 536 ss.addNetworkRegistrationInfo(nri); 537 log("Override NR state with " + ss.getNrState()); 538 } 539 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_RAT)) { 540 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 541 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 542 if (nri == null) { 543 nri = new NetworkRegistrationInfo.Builder() 544 .setDomain(NetworkRegistrationInfo.DOMAIN_CS) 545 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 546 .build(); 547 } 548 nri.setAccessNetworkTechnology(ServiceState.rilRadioTechnologyToNetworkType( 549 mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_RAT, 550 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))); 551 ss.addNetworkRegistrationInfo(nri); 552 log("Override voice rat with " + ss.getRilVoiceRadioTechnology()); 553 } 554 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_RAT)) { 555 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 556 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 557 if (nri == null) { 558 nri = new NetworkRegistrationInfo.Builder() 559 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 560 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 561 .build(); 562 } 563 nri.setAccessNetworkTechnology(ServiceState.rilRadioTechnologyToNetworkType( 564 mServiceStateTestIntent.getIntExtra(EXTRA_DATA_RAT, 565 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))); 566 ss.addNetworkRegistrationInfo(nri); 567 log("Override data rat with " + ss.getRilDataRadioTechnology()); 568 } 569 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_ROAMING_TYPE)) { 570 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 571 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 572 if (nri == null) { 573 nri = new NetworkRegistrationInfo.Builder() 574 .setDomain(NetworkRegistrationInfo.DOMAIN_CS) 575 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 576 .build(); 577 } 578 nri.setRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_ROAMING_TYPE, 579 ServiceState.ROAMING_TYPE_UNKNOWN)); 580 ss.addNetworkRegistrationInfo(nri); 581 log("Override voice roaming type with " + ss.getVoiceRoamingType()); 582 } 583 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_ROAMING_TYPE)) { 584 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 585 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 586 if (nri == null) { 587 nri = new NetworkRegistrationInfo.Builder() 588 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 589 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 590 .build(); 591 } 592 nri.setRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_ROAMING_TYPE, 593 ServiceState.ROAMING_TYPE_UNKNOWN)); 594 ss.addNetworkRegistrationInfo(nri); 595 log("Override data roaming type with " + ss.getDataRoamingType()); 596 } 597 } 598 testImsECall()599 void testImsECall() { 600 // Attempt to get the active IMS call before parsing the test XML file. 601 ImsCall imsCall = getImsCall(); 602 if (imsCall == null) return; 603 604 ImsCallProfile callProfile = imsCall.getCallProfile(); 605 Bundle extras = callProfile.getCallExtras(); 606 if (extras == null) { 607 extras = new Bundle(); 608 } 609 extras.putBoolean(ImsCallProfile.EXTRA_EMERGENCY_CALL, true); 610 callProfile.mCallExtras = extras; 611 imsCall.getImsCallSessionListenerProxy().callSessionUpdated(imsCall.getSession(), 612 callProfile); 613 } 614 getImsCall()615 private ImsCall getImsCall() { 616 ImsPhone imsPhone = (ImsPhone) mPhone; 617 if (imsPhone == null) { 618 return null; 619 } 620 621 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 622 if (imsPhoneCall == null) { 623 return null; 624 } 625 626 ImsCall imsCall = imsPhoneCall.getImsCall(); 627 if (imsCall == null) { 628 return null; 629 } 630 return imsCall; 631 } 632 testImsReceiveDtmf(Intent intent)633 void testImsReceiveDtmf(Intent intent) { 634 if (!intent.hasExtra(EXTRA_DIGIT)) { 635 return; 636 } 637 char digit = intent.getStringExtra(EXTRA_DIGIT).charAt(0); 638 639 ImsCall imsCall = getImsCall(); 640 if (imsCall == null) { 641 return; 642 } 643 644 imsCall.getImsCallSessionListenerProxy().callSessionDtmfReceived(digit); 645 } 646 testChangeNumber(Intent intent)647 void testChangeNumber(Intent intent) { 648 if (!intent.hasExtra(EXTRA_NUMBER)) { 649 return; 650 } 651 652 String newNumber = intent.getStringExtra(EXTRA_NUMBER); 653 654 // Update all the calls. 655 mPhone.getForegroundCall().getConnections() 656 .stream() 657 .forEach(c -> { 658 c.setAddress(newNumber, PhoneConstants.PRESENTATION_ALLOWED); 659 c.setDialString(newNumber); 660 }); 661 662 // <sigh> 663 if (mPhone instanceof GsmCdmaPhone) { 664 ((GsmCdmaPhone) mPhone).notifyPhoneStateChanged(); 665 ((GsmCdmaPhone) mPhone).notifyPreciseCallStateChanged(); 666 } else if (mPhone instanceof ImsPhone) { 667 ((ImsPhone) mPhone).notifyPhoneStateChanged(); 668 ((ImsPhone) mPhone).notifyPreciseCallStateChanged(); 669 } 670 } 671 } 672