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.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.net.Uri; 24 import android.os.BadParcelableException; 25 import android.os.Bundle; 26 import android.telephony.AccessNetworkConstants; 27 import android.telephony.NetworkRegistrationInfo; 28 import android.telephony.ServiceState; 29 import android.telephony.TelephonyManager; 30 import android.telephony.ims.ImsCallProfile; 31 import android.telephony.ims.ImsConferenceState; 32 import android.telephony.ims.ImsExternalCallState; 33 import android.telephony.ims.ImsReasonInfo; 34 35 import com.android.ims.ImsCall; 36 import com.android.internal.telephony.gsm.SuppServiceNotification; 37 import com.android.internal.telephony.imsphone.ImsExternalCallTracker; 38 import com.android.internal.telephony.imsphone.ImsPhone; 39 import com.android.internal.telephony.imsphone.ImsPhoneCall; 40 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker; 41 import com.android.internal.telephony.test.TestConferenceEventPackageParser; 42 import com.android.internal.telephony.util.TelephonyUtils; 43 import com.android.telephony.Rlog; 44 45 import java.io.File; 46 import java.io.FileInputStream; 47 import java.io.FileNotFoundException; 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.List; 51 52 /** 53 * Telephony tester receives the following intents where {name} is the phone name 54 * 55 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_detached 56 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_attached 57 * adb shell am broadcast -a com.android.internal.telephony.TestConferenceEventPackage -e filename 58 * test_filename.xml 59 * adb shell am broadcast -a com.android.internal.telephony.TestServiceState --ei data_rat 10 --ei 60 * data_roaming_type 3 61 * adb shell am broadcast -a com.android.internal.telephony.TestServiceState --es action reset 62 * 63 */ 64 public class TelephonyTester { 65 private static final String LOG_TAG = "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_VOICE_RAT = "voice_rat"; 148 private static final String EXTRA_DATA_RAT = "data_rat"; 149 private static final String EXTRA_VOICE_REG_STATE = "voice_reg_state"; 150 private static final String EXTRA_DATA_REG_STATE = "data_reg_state"; 151 private static final String EXTRA_VOICE_ROAMING_TYPE = "voice_roaming_type"; 152 private static final String EXTRA_DATA_ROAMING_TYPE = "data_roaming_type"; 153 private static final String EXTRA_NR_FREQUENCY_RANGE = "nr_frequency_range"; 154 private static final String EXTRA_NR_STATE = "nr_state"; 155 private static final String EXTRA_OPERATOR = "operator"; 156 private static final String EXTRA_OPERATOR_RAW = "operator_raw"; 157 158 private static final String ACTION_RESET = "reset"; 159 160 private static List<ImsExternalCallState> mImsExternalCallStates = null; 161 162 private Intent mServiceStateTestIntent; 163 164 private Phone mPhone; 165 166 // The static intent receiver one for all instances and we assume this 167 // is running on the same thread as Dcc. 168 protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 169 @Override 170 public void onReceive(Context context, Intent intent) { 171 String action = intent.getAction(); 172 try { 173 if (DBG) log("sIntentReceiver.onReceive: action=" + action); 174 if (action.equals(mPhone.getActionDetached())) { 175 log("simulate detaching"); 176 mPhone.getServiceStateTracker().mDetachedRegistrants.get( 177 AccessNetworkConstants.TRANSPORT_TYPE_WWAN).notifyRegistrants(); 178 } else if (action.equals(mPhone.getActionAttached())) { 179 log("simulate attaching"); 180 mPhone.getServiceStateTracker().mAttachedRegistrants.get( 181 AccessNetworkConstants.TRANSPORT_TYPE_WWAN).notifyRegistrants(); 182 } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) { 183 log("inject simulated conference event package"); 184 handleTestConferenceEventPackage(context, 185 intent.getStringExtra(EXTRA_FILENAME), 186 intent.getBooleanExtra(EXTRA_BYPASS_IMSCALL, false)); 187 } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) { 188 log("handle test dialog event package intent"); 189 handleTestDialogEventPackageIntent(intent); 190 } else if (action.equals(ACTION_TEST_SUPP_SRVC_FAIL)) { 191 log("handle test supp svc failed intent"); 192 handleSuppServiceFailedIntent(intent); 193 } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) { 194 log("handle handover fail test intent"); 195 handleHandoverFailedIntent(); 196 } else if (action.equals(ACTION_TEST_SUPP_SRVC_NOTIFICATION)) { 197 log("handle supp service notification test intent"); 198 sendTestSuppServiceNotification(intent); 199 } else if (action.equals(ACTION_TEST_SERVICE_STATE)) { 200 log("handle test service state changed intent"); 201 // Trigger the service state update. The replacement will be done in 202 // overrideServiceState(). 203 mServiceStateTestIntent = intent; 204 mPhone.getServiceStateTracker().sendEmptyMessage( 205 ServiceStateTracker.EVENT_NETWORK_STATE_CHANGED); 206 } else if (action.equals(ACTION_TEST_IMS_E_CALL)) { 207 log("handle test IMS ecall intent"); 208 testImsECall(); 209 } else if (action.equals(ACTION_TEST_RECEIVE_DTMF)) { 210 log("handle test DTMF intent"); 211 testImsReceiveDtmf(intent); 212 } else if (action.equals(ACTION_TEST_CHANGE_NUMBER)) { 213 log("handle test change number intent"); 214 testChangeNumber(intent); 215 } else { 216 if (DBG) log("onReceive: unknown action=" + action); 217 } 218 } catch (BadParcelableException e) { 219 Rlog.w(LOG_TAG, e); 220 } 221 } 222 }; 223 TelephonyTester(Phone phone)224 TelephonyTester(Phone phone) { 225 mPhone = phone; 226 227 if (TelephonyUtils.IS_DEBUGGABLE) { 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 static void log(String s) { 265 Rlog.d(LOG_TAG, 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 overrideServiceState(ServiceState ss)388 void overrideServiceState(ServiceState ss) { 389 if (mServiceStateTestIntent == null || ss == null) return; 390 if (mServiceStateTestIntent.hasExtra(EXTRA_ACTION) 391 && ACTION_RESET.equals(mServiceStateTestIntent.getStringExtra(EXTRA_ACTION))) { 392 log("Service state override reset"); 393 return; 394 } 395 396 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_REG_STATE)) { 397 ss.setVoiceRegState(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_REG_STATE, 398 ServiceState.STATE_OUT_OF_SERVICE)); 399 log("Override voice service state with " + ss.getState()); 400 } 401 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_REG_STATE)) { 402 ss.setDataRegState(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_REG_STATE, 403 ServiceState.STATE_OUT_OF_SERVICE)); 404 log("Override data service state with " + ss.getDataRegistrationState()); 405 } 406 if (mServiceStateTestIntent.hasExtra(EXTRA_OPERATOR)) { 407 String[] data = mServiceStateTestIntent.getStringExtra(EXTRA_OPERATOR).split(","); 408 String operatorAlphaLong = data.length > 0 ? data[0] : ""; 409 String operatorAlphaShort = data.length > 1 ? data[1] : operatorAlphaLong; 410 String operatorNumeric = data.length > 2 ? data[2] : ""; 411 ss.setOperatorName(operatorAlphaLong, operatorAlphaShort, operatorNumeric); 412 log("Override operator with " + Arrays.toString(data)); 413 } 414 if (mServiceStateTestIntent.hasExtra(EXTRA_OPERATOR_RAW)) { 415 String operator_raw = mServiceStateTestIntent.getStringExtra(EXTRA_OPERATOR_RAW); 416 ss.setOperatorAlphaLongRaw(operator_raw); 417 ss.setOperatorAlphaShortRaw(operator_raw); 418 log("Override operator_raw with " + operator_raw); 419 } 420 if (mServiceStateTestIntent.hasExtra(EXTRA_NR_FREQUENCY_RANGE)) { 421 ss.setNrFrequencyRange(mServiceStateTestIntent.getIntExtra(EXTRA_NR_FREQUENCY_RANGE, 422 ServiceState.FREQUENCY_RANGE_UNKNOWN)); 423 log("Override NR frequency range with " + ss.getNrFrequencyRange()); 424 } 425 if (mServiceStateTestIntent.hasExtra(EXTRA_NR_STATE)) { 426 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 427 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 428 if (nri == null) { 429 nri = new NetworkRegistrationInfo.Builder() 430 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 431 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 432 .build(); 433 } 434 nri.setNrState(mServiceStateTestIntent.getIntExtra(EXTRA_NR_STATE, 435 NetworkRegistrationInfo.NR_STATE_NONE)); 436 ss.addNetworkRegistrationInfo(nri); 437 log("Override NR state with " + ss.getNrState()); 438 } 439 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_RAT)) { 440 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 441 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 442 if (nri == null) { 443 nri = new NetworkRegistrationInfo.Builder() 444 .setDomain(NetworkRegistrationInfo.DOMAIN_CS) 445 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 446 .build(); 447 } 448 nri.setAccessNetworkTechnology(ServiceState.rilRadioTechnologyToNetworkType( 449 mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_RAT, 450 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))); 451 ss.addNetworkRegistrationInfo(nri); 452 log("Override voice rat with " + ss.getRilVoiceRadioTechnology()); 453 } 454 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_RAT)) { 455 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 456 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 457 if (nri == null) { 458 nri = new NetworkRegistrationInfo.Builder() 459 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 460 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 461 .build(); 462 } 463 nri.setAccessNetworkTechnology(ServiceState.rilRadioTechnologyToNetworkType( 464 mServiceStateTestIntent.getIntExtra(EXTRA_DATA_RAT, 465 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))); 466 ss.addNetworkRegistrationInfo(nri); 467 log("Override data rat with " + ss.getRilDataRadioTechnology()); 468 } 469 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_ROAMING_TYPE)) { 470 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 471 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 472 if (nri == null) { 473 nri = new NetworkRegistrationInfo.Builder() 474 .setDomain(NetworkRegistrationInfo.DOMAIN_CS) 475 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 476 .build(); 477 } 478 nri.setRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_ROAMING_TYPE, 479 ServiceState.ROAMING_TYPE_UNKNOWN)); 480 ss.addNetworkRegistrationInfo(nri); 481 log("Override voice roaming type with " + ss.getVoiceRoamingType()); 482 } 483 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_ROAMING_TYPE)) { 484 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 485 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 486 if (nri == null) { 487 nri = new NetworkRegistrationInfo.Builder() 488 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 489 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 490 .build(); 491 } 492 nri.setRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_ROAMING_TYPE, 493 ServiceState.ROAMING_TYPE_UNKNOWN)); 494 ss.addNetworkRegistrationInfo(nri); 495 log("Override data roaming type with " + ss.getDataRoamingType()); 496 } 497 } 498 testImsECall()499 void testImsECall() { 500 // Attempt to get the active IMS call before parsing the test XML file. 501 ImsCall imsCall = getImsCall(); 502 if (imsCall == null) return; 503 504 ImsCallProfile callProfile = imsCall.getCallProfile(); 505 Bundle extras = callProfile.getCallExtras(); 506 if (extras == null) { 507 extras = new Bundle(); 508 } 509 extras.putBoolean(ImsCallProfile.EXTRA_EMERGENCY_CALL, true); 510 callProfile.mCallExtras = extras; 511 imsCall.getImsCallSessionListenerProxy().callSessionUpdated(imsCall.getSession(), 512 callProfile); 513 } 514 getImsCall()515 private ImsCall getImsCall() { 516 ImsPhone imsPhone = (ImsPhone) mPhone; 517 if (imsPhone == null) { 518 return null; 519 } 520 521 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 522 if (imsPhoneCall == null) { 523 return null; 524 } 525 526 ImsCall imsCall = imsPhoneCall.getImsCall(); 527 if (imsCall == null) { 528 return null; 529 } 530 return imsCall; 531 } 532 testImsReceiveDtmf(Intent intent)533 void testImsReceiveDtmf(Intent intent) { 534 if (!intent.hasExtra(EXTRA_DIGIT)) { 535 return; 536 } 537 char digit = intent.getStringExtra(EXTRA_DIGIT).charAt(0); 538 539 ImsCall imsCall = getImsCall(); 540 if (imsCall == null) { 541 return; 542 } 543 544 imsCall.getImsCallSessionListenerProxy().callSessionDtmfReceived(digit); 545 } 546 testChangeNumber(Intent intent)547 void testChangeNumber(Intent intent) { 548 if (!intent.hasExtra(EXTRA_NUMBER)) { 549 return; 550 } 551 552 String newNumber = intent.getStringExtra(EXTRA_NUMBER); 553 554 // Update all the calls. 555 mPhone.getForegroundCall().getConnections() 556 .stream() 557 .forEach(c -> { 558 c.setAddress(newNumber, PhoneConstants.PRESENTATION_ALLOWED); 559 c.setDialString(newNumber); 560 }); 561 562 // <sigh> 563 if (mPhone instanceof GsmCdmaPhone) { 564 ((GsmCdmaPhone) mPhone).notifyPhoneStateChanged(); 565 ((GsmCdmaPhone) mPhone).notifyPreciseCallStateChanged(); 566 } else if (mPhone instanceof ImsPhone) { 567 ((ImsPhone) mPhone).notifyPhoneStateChanged(); 568 ((ImsPhone) mPhone).notifyPreciseCallStateChanged(); 569 } 570 } 571 } 572