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