• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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