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