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 a change to the current call's phone number. 129 * Use the {@link #EXTRA_NUMBER} extra to specify the new phone number. 130 */ 131 private static final String ACTION_TEST_CHANGE_NUMBER = 132 "com.android.internal.telephony.TestChangeNumber"; 133 134 private static final String ACTION_TEST_SERVICE_STATE = 135 "com.android.internal.telephony.TestServiceState"; 136 137 private static final String EXTRA_ACTION = "action"; 138 private static final String EXTRA_VOICE_RAT = "voice_rat"; 139 private static final String EXTRA_DATA_RAT = "data_rat"; 140 private static final String EXTRA_VOICE_REG_STATE = "voice_reg_state"; 141 private static final String EXTRA_DATA_REG_STATE = "data_reg_state"; 142 private static final String EXTRA_VOICE_ROAMING_TYPE = "voice_roaming_type"; 143 private static final String EXTRA_DATA_ROAMING_TYPE = "data_roaming_type"; 144 private static final String EXTRA_NR_FREQUENCY_RANGE = "nr_frequency_range"; 145 private static final String EXTRA_NR_STATE = "nr_state"; 146 private static final String EXTRA_OPERATOR = "operator"; 147 private static final String EXTRA_OPERATOR_RAW = "operator_raw"; 148 149 private static final String ACTION_RESET = "reset"; 150 151 private static List<ImsExternalCallState> mImsExternalCallStates = null; 152 153 private Intent mServiceStateTestIntent; 154 155 private Phone mPhone; 156 157 // The static intent receiver one for all instances and we assume this 158 // is running on the same thread as Dcc. 159 protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 160 @Override 161 public void onReceive(Context context, Intent intent) { 162 String action = intent.getAction(); 163 try { 164 if (DBG) log("sIntentReceiver.onReceive: action=" + action); 165 if (action.equals(mPhone.getActionDetached())) { 166 log("simulate detaching"); 167 mPhone.getServiceStateTracker().mDetachedRegistrants.get( 168 AccessNetworkConstants.TRANSPORT_TYPE_WWAN).notifyRegistrants(); 169 } else if (action.equals(mPhone.getActionAttached())) { 170 log("simulate attaching"); 171 mPhone.getServiceStateTracker().mAttachedRegistrants.get( 172 AccessNetworkConstants.TRANSPORT_TYPE_WWAN).notifyRegistrants(); 173 } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) { 174 log("inject simulated conference event package"); 175 handleTestConferenceEventPackage(context, 176 intent.getStringExtra(EXTRA_FILENAME), 177 intent.getBooleanExtra(EXTRA_BYPASS_IMSCALL, false)); 178 } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) { 179 log("handle test dialog event package intent"); 180 handleTestDialogEventPackageIntent(intent); 181 } else if (action.equals(ACTION_TEST_SUPP_SRVC_FAIL)) { 182 log("handle test supp svc failed intent"); 183 handleSuppServiceFailedIntent(intent); 184 } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) { 185 log("handle handover fail test intent"); 186 handleHandoverFailedIntent(); 187 } else if (action.equals(ACTION_TEST_SUPP_SRVC_NOTIFICATION)) { 188 log("handle supp service notification test intent"); 189 sendTestSuppServiceNotification(intent); 190 } else if (action.equals(ACTION_TEST_SERVICE_STATE)) { 191 log("handle test service state changed intent"); 192 // Trigger the service state update. The replacement will be done in 193 // overrideServiceState(). 194 mServiceStateTestIntent = intent; 195 mPhone.getServiceStateTracker().sendEmptyMessage( 196 ServiceStateTracker.EVENT_NETWORK_STATE_CHANGED); 197 } else if (action.equals(ACTION_TEST_IMS_E_CALL)) { 198 log("handle test IMS ecall intent"); 199 testImsECall(); 200 } else if (action.equals(ACTION_TEST_CHANGE_NUMBER)) { 201 log("handle test change number intent"); 202 testChangeNumber(intent); 203 } else { 204 if (DBG) log("onReceive: unknown action=" + action); 205 } 206 } catch (BadParcelableException e) { 207 Rlog.w(LOG_TAG, e); 208 } 209 } 210 }; 211 TelephonyTester(Phone phone)212 TelephonyTester(Phone phone) { 213 mPhone = phone; 214 215 if (TelephonyUtils.IS_DEBUGGABLE) { 216 IntentFilter filter = new IntentFilter(); 217 218 filter.addAction(mPhone.getActionDetached()); 219 log("register for intent action=" + mPhone.getActionDetached()); 220 221 filter.addAction(mPhone.getActionAttached()); 222 log("register for intent action=" + mPhone.getActionAttached()); 223 224 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 225 log("register for intent action=" + ACTION_TEST_CONFERENCE_EVENT_PACKAGE); 226 filter.addAction(ACTION_TEST_CONFERENCE_EVENT_PACKAGE); 227 filter.addAction(ACTION_TEST_DIALOG_EVENT_PACKAGE); 228 filter.addAction(ACTION_TEST_SUPP_SRVC_FAIL); 229 filter.addAction(ACTION_TEST_HANDOVER_FAIL); 230 filter.addAction(ACTION_TEST_SUPP_SRVC_NOTIFICATION); 231 filter.addAction(ACTION_TEST_IMS_E_CALL); 232 mImsExternalCallStates = new ArrayList<ImsExternalCallState>(); 233 } 234 235 filter.addAction(ACTION_TEST_SERVICE_STATE); 236 log("register for intent action=" + ACTION_TEST_SERVICE_STATE); 237 238 filter.addAction(ACTION_TEST_CHANGE_NUMBER); 239 log("register for intent action=" + ACTION_TEST_CHANGE_NUMBER); 240 phone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone.getHandler()); 241 } 242 } 243 dispose()244 void dispose() { 245 if (TelephonyUtils.IS_DEBUGGABLE) { 246 mPhone.getContext().unregisterReceiver(mIntentReceiver); 247 } 248 } 249 log(String s)250 private static void log(String s) { 251 Rlog.d(LOG_TAG, s); 252 } 253 handleSuppServiceFailedIntent(Intent intent)254 private void handleSuppServiceFailedIntent(Intent intent) { 255 ImsPhone imsPhone = (ImsPhone) mPhone; 256 if (imsPhone == null) { 257 return; 258 } 259 int code = intent.getIntExtra(EXTRA_FAILURE_CODE, 0); 260 imsPhone.notifySuppServiceFailed(PhoneInternalInterface.SuppService.values()[code]); 261 } 262 handleHandoverFailedIntent()263 private void handleHandoverFailedIntent() { 264 // Attempt to get the active IMS call 265 ImsPhone imsPhone = (ImsPhone) mPhone; 266 if (imsPhone == null) { 267 return; 268 } 269 270 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 271 if (imsPhoneCall == null) { 272 return; 273 } 274 275 ImsCall imsCall = imsPhoneCall.getImsCall(); 276 if (imsCall == null) { 277 return; 278 } 279 280 imsCall.getImsCallSessionListenerProxy().callSessionHandoverFailed(imsCall.getCallSession(), 281 TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_IWLAN, 282 new ImsReasonInfo()); 283 } 284 285 /** 286 * Handles request to send a test conference event package to the active Ims call. 287 * 288 * @see com.android.internal.telephony.test.TestConferenceEventPackageParser 289 * @param context The context. 290 * @param fileName The name of the test conference event package file to read. 291 */ handleTestConferenceEventPackage(Context context, String fileName, boolean isBypassingImsCall)292 private void handleTestConferenceEventPackage(Context context, String fileName, 293 boolean isBypassingImsCall) { 294 // Attempt to get the active IMS call before parsing the test XML file. 295 ImsPhone imsPhone = (ImsPhone) mPhone; 296 if (imsPhone == null) { 297 return; 298 } 299 300 ImsPhoneCallTracker tracker = (ImsPhoneCallTracker) imsPhone.getCallTracker(); 301 302 File packageFile = new File(context.getFilesDir(), fileName); 303 final FileInputStream is; 304 try { 305 is = new FileInputStream(packageFile); 306 } catch (FileNotFoundException ex) { 307 log("Test conference event package file not found: " + packageFile.getAbsolutePath()); 308 return; 309 } 310 311 TestConferenceEventPackageParser parser = new TestConferenceEventPackageParser(is); 312 ImsConferenceState imsConferenceState = parser.parse(); 313 if (imsConferenceState == null) { 314 return; 315 } 316 317 if (isBypassingImsCall) { 318 tracker.injectTestConferenceState(imsConferenceState); 319 } else { 320 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 321 if (imsPhoneCall == null) { 322 return; 323 } 324 325 ImsCall imsCall = imsPhoneCall.getImsCall(); 326 if (imsCall == null) { 327 return; 328 } 329 330 imsCall.conferenceStateUpdated(imsConferenceState); 331 } 332 } 333 334 /** 335 * Handles intents containing test dialog event package data. 336 * 337 * @param intent 338 */ handleTestDialogEventPackageIntent(Intent intent)339 private void handleTestDialogEventPackageIntent(Intent intent) { 340 ImsPhone imsPhone = (ImsPhone) mPhone; 341 if (imsPhone == null) { 342 return; 343 } 344 ImsExternalCallTracker externalCallTracker = imsPhone.getExternalCallTracker(); 345 if (externalCallTracker == null) { 346 return; 347 } 348 349 if (intent.hasExtra(EXTRA_STARTPACKAGE)) { 350 mImsExternalCallStates.clear(); 351 } else if (intent.hasExtra(EXTRA_SENDPACKAGE)) { 352 externalCallTracker.refreshExternalCallState(mImsExternalCallStates); 353 mImsExternalCallStates.clear(); 354 } else if (intent.hasExtra(EXTRA_DIALOGID)) { 355 ImsExternalCallState state = new ImsExternalCallState( 356 intent.getIntExtra(EXTRA_DIALOGID, 0), 357 Uri.parse(intent.getStringExtra(EXTRA_NUMBER)), 358 intent.getBooleanExtra(EXTRA_CANPULL, true), 359 intent.getIntExtra(EXTRA_STATE, 360 ImsExternalCallState.CALL_STATE_CONFIRMED), 361 ImsCallProfile.CALL_TYPE_VOICE, 362 false /* isHeld */ 363 ); 364 mImsExternalCallStates.add(state); 365 } 366 } 367 sendTestSuppServiceNotification(Intent intent)368 private void sendTestSuppServiceNotification(Intent intent) { 369 if (intent.hasExtra(EXTRA_CODE) && intent.hasExtra(EXTRA_TYPE)) { 370 int code = intent.getIntExtra(EXTRA_CODE, -1); 371 int type = intent.getIntExtra(EXTRA_TYPE, -1); 372 ImsPhone imsPhone = (ImsPhone) mPhone; 373 if (imsPhone == null) { 374 return; 375 } 376 log("Test supp service notification:" + code); 377 SuppServiceNotification suppServiceNotification = new SuppServiceNotification(); 378 suppServiceNotification.code = code; 379 suppServiceNotification.notificationType = type; 380 imsPhone.notifySuppSvcNotification(suppServiceNotification); 381 } 382 } 383 overrideServiceState(ServiceState ss)384 void overrideServiceState(ServiceState ss) { 385 if (mServiceStateTestIntent == null || ss == null) return; 386 if (mServiceStateTestIntent.hasExtra(EXTRA_ACTION) 387 && ACTION_RESET.equals(mServiceStateTestIntent.getStringExtra(EXTRA_ACTION))) { 388 log("Service state override reset"); 389 return; 390 } 391 392 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_REG_STATE)) { 393 ss.setVoiceRegState(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_REG_STATE, 394 ServiceState.STATE_OUT_OF_SERVICE)); 395 log("Override voice service state with " + ss.getState()); 396 } 397 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_REG_STATE)) { 398 ss.setDataRegState(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_REG_STATE, 399 ServiceState.STATE_OUT_OF_SERVICE)); 400 log("Override data service state with " + ss.getDataRegistrationState()); 401 } 402 if (mServiceStateTestIntent.hasExtra(EXTRA_OPERATOR)) { 403 String operator = mServiceStateTestIntent.getStringExtra(EXTRA_OPERATOR); 404 ss.setOperatorName(operator, operator, ""); 405 log("Override operator with " + operator); 406 } 407 if (mServiceStateTestIntent.hasExtra(EXTRA_OPERATOR_RAW)) { 408 String operator_raw = mServiceStateTestIntent.getStringExtra(EXTRA_OPERATOR_RAW); 409 ss.setOperatorAlphaLongRaw(operator_raw); 410 ss.setOperatorAlphaShortRaw(operator_raw); 411 log("Override operator_raw with " + operator_raw); 412 } 413 if (mServiceStateTestIntent.hasExtra(EXTRA_NR_FREQUENCY_RANGE)) { 414 ss.setNrFrequencyRange(mServiceStateTestIntent.getIntExtra(EXTRA_NR_FREQUENCY_RANGE, 415 ServiceState.FREQUENCY_RANGE_UNKNOWN)); 416 log("Override NR frequency range with " + ss.getNrFrequencyRange()); 417 } 418 if (mServiceStateTestIntent.hasExtra(EXTRA_NR_STATE)) { 419 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 420 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 421 if (nri == null) { 422 nri = new NetworkRegistrationInfo.Builder() 423 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 424 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 425 .build(); 426 } 427 nri.setNrState(mServiceStateTestIntent.getIntExtra(EXTRA_NR_STATE, 428 NetworkRegistrationInfo.NR_STATE_NONE)); 429 ss.addNetworkRegistrationInfo(nri); 430 log("Override NR state with " + ss.getNrState()); 431 } 432 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_RAT)) { 433 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 434 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 435 if (nri == null) { 436 nri = new NetworkRegistrationInfo.Builder() 437 .setDomain(NetworkRegistrationInfo.DOMAIN_CS) 438 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 439 .build(); 440 } 441 nri.setAccessNetworkTechnology(ServiceState.rilRadioTechnologyToNetworkType( 442 mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_RAT, 443 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))); 444 ss.addNetworkRegistrationInfo(nri); 445 log("Override voice rat with " + ss.getRilVoiceRadioTechnology()); 446 } 447 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_RAT)) { 448 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 449 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 450 if (nri == null) { 451 nri = new NetworkRegistrationInfo.Builder() 452 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 453 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 454 .build(); 455 } 456 nri.setAccessNetworkTechnology(ServiceState.rilRadioTechnologyToNetworkType( 457 mServiceStateTestIntent.getIntExtra(EXTRA_DATA_RAT, 458 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))); 459 ss.addNetworkRegistrationInfo(nri); 460 log("Override data rat with " + ss.getRilDataRadioTechnology()); 461 } 462 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_ROAMING_TYPE)) { 463 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 464 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 465 if (nri == null) { 466 nri = new NetworkRegistrationInfo.Builder() 467 .setDomain(NetworkRegistrationInfo.DOMAIN_CS) 468 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 469 .build(); 470 } 471 nri.setRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_ROAMING_TYPE, 472 ServiceState.ROAMING_TYPE_UNKNOWN)); 473 ss.addNetworkRegistrationInfo(nri); 474 log("Override voice roaming type with " + ss.getVoiceRoamingType()); 475 } 476 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_ROAMING_TYPE)) { 477 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 478 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 479 if (nri == null) { 480 nri = new NetworkRegistrationInfo.Builder() 481 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 482 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 483 .build(); 484 } 485 nri.setRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_ROAMING_TYPE, 486 ServiceState.ROAMING_TYPE_UNKNOWN)); 487 ss.addNetworkRegistrationInfo(nri); 488 log("Override data roaming type with " + ss.getDataRoamingType()); 489 } 490 } 491 testImsECall()492 void testImsECall() { 493 // Attempt to get the active IMS call before parsing the test XML file. 494 ImsPhone imsPhone = (ImsPhone) mPhone; 495 if (imsPhone == null) { 496 return; 497 } 498 499 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 500 if (imsPhoneCall == null) { 501 return; 502 } 503 504 ImsCall imsCall = imsPhoneCall.getImsCall(); 505 if (imsCall == null) { 506 return; 507 } 508 509 ImsCallProfile callProfile = imsCall.getCallProfile(); 510 Bundle extras = callProfile.getCallExtras(); 511 if (extras == null) { 512 extras = new Bundle(); 513 } 514 extras.putBoolean(ImsCallProfile.EXTRA_EMERGENCY_CALL, true); 515 callProfile.mCallExtras = extras; 516 imsCall.getImsCallSessionListenerProxy().callSessionUpdated(imsCall.getSession(), 517 callProfile); 518 } 519 testChangeNumber(Intent intent)520 void testChangeNumber(Intent intent) { 521 if (!intent.hasExtra(EXTRA_NUMBER)) { 522 return; 523 } 524 525 String newNumber = intent.getStringExtra(EXTRA_NUMBER); 526 527 // Update all the calls. 528 mPhone.getForegroundCall().getConnections() 529 .stream() 530 .forEach(c -> { 531 c.setAddress(newNumber, PhoneConstants.PRESENTATION_ALLOWED); 532 c.setDialString(newNumber); 533 }); 534 535 // <sigh> 536 if (mPhone instanceof GsmCdmaPhone) { 537 ((GsmCdmaPhone) mPhone).notifyPhoneStateChanged(); 538 ((GsmCdmaPhone) mPhone).notifyPreciseCallStateChanged(); 539 } else if (mPhone instanceof ImsPhone) { 540 ((ImsPhone) mPhone).notifyPhoneStateChanged(); 541 ((ImsPhone) mPhone).notifyPreciseCallStateChanged(); 542 } 543 } 544 } 545