• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 android.telephony.ims.cts;
18 
19 import android.app.Instrumentation;
20 import android.app.role.RoleManager;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.ServiceConnection;
25 import android.os.IBinder;
26 import android.telephony.cts.TelephonyUtils;
27 import android.telephony.cts.externalimsservice.ITestExternalImsService;
28 import android.telephony.cts.externalimsservice.TestExternalImsService;
29 import android.telephony.ims.feature.ImsFeature;
30 import android.telephony.ims.stub.ImsFeatureConfiguration;
31 import android.text.TextUtils;
32 import android.util.Log;
33 import android.util.SparseArray;
34 
35 import androidx.test.platform.app.InstrumentationRegistry;
36 
37 import com.android.compatibility.common.util.ShellIdentityUtils;
38 
39 import java.util.List;
40 import java.util.concurrent.CountDownLatch;
41 import java.util.concurrent.LinkedBlockingQueue;
42 import java.util.concurrent.TimeUnit;
43 
44 /**
45  * Connects The CTS test ImsService to the Telephony Framework.
46  */
47 class ImsServiceConnector {
48 
49     private static final String TAG = "CtsImsServiceConnector";
50 
51     private static final String PACKAGE_NAME =
52             InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName();
53     private static final String EXTERNAL_PACKAGE_NAME =
54             TestExternalImsService.class.getPackage().getName();
55 
56     private static final String COMMAND_BASE = "cmd phone ";
57     private static final String COMMAND_SET_IMS_SERVICE = "ims set-ims-service ";
58     private static final String COMMAND_GET_IMS_SERVICE = "ims get-ims-service ";
59     private static final String COMMAND_CLEAR_SERVICE_OVERRIDE = "ims clear-ims-service-override";
60     private static final String COMMAND_CARRIER_SERVICE_IDENTIFIER = "-c ";
61     private static final String COMMAND_DEVICE_SERVICE_IDENTIFIER = "-d ";
62     private static final String COMMAND_SLOT_IDENTIFIER = "-s ";
63     private static final String COMMAND_FEATURE_IDENTIFIER = "-f ";
64     private static final String COMMAND_ENABLE_IMS = "ims enable ";
65     private static final String COMMAND_DISABLE_IMS = "ims disable ";
66     private static final String COMMAND_SET_DEVICE_SINGLE_REGISTRATION_ENABLED =
67             "src set-device-enabled ";
68     private static final String COMMAND_GET_DEVICE_SINGLE_REGISTRATION_ENABLED =
69             "src get-device-enabled";
70     private static final String COMMAND_SET_CARRIER_SINGLE_REGISTRATION_ENABLED =
71             "src set-carrier-enabled ";
72     private static final String COMMAND_GET_CARRIER_SINGLE_REGISTRATION_ENABLED =
73             "src get-carrier-enabled";
74     private static final String COMMAND_REMOVE_EAB_CONTACT = "uce remove-eab-contact ";
75     private static final String COMMAND_GET_UCE_ENABLED = "uce get-device-enabled";
76     private static final String COMMAND_SET_UCE_ENABLED = "uce set-device-enabled ";
77     private static final String COMMAND_REMOVE_UCE_REQUEST_DISALLOWED_STATUS =
78             "uce remove-request-disallowed-status ";
79     private static final String COMMAND_SET_CAPABILITY_REQUEST_TIMEOUT =
80             "uce set-capabilities-request-timeout ";
81     private static final String COMMAND_SET_TEST_MODE_ENABLED = "src set-test-enabled ";
82     private static final String COMMAND_SET_D2D_ENABLED = "d2d set-device-support ";
83 
84     private boolean mIsTestTypeExecutor = false;
85 
setExecutorTestType(boolean type)86     public void setExecutorTestType(boolean type) {
87         mIsTestTypeExecutor = type;
88     }
89 
90     private class TestCarrierServiceConnection implements ServiceConnection {
91 
92         private final CountDownLatch mLatch;
93 
TestCarrierServiceConnection(CountDownLatch latch)94         TestCarrierServiceConnection(CountDownLatch latch) {
95             mLatch = latch;
96         }
97 
98         @Override
onServiceConnected(ComponentName name, IBinder service)99         public void onServiceConnected(ComponentName name, IBinder service) {
100             mCarrierService = ((TestImsService.LocalBinder) service).getService();
101             mLatch.countDown();
102         }
103 
104         @Override
onServiceDisconnected(ComponentName name)105         public void onServiceDisconnected(ComponentName name) {
106             mCarrierService = null;
107         }
108     }
109 
110     private class TestDeviceServiceConnection implements ServiceConnection {
111 
112         private final CountDownLatch mLatch;
113 
TestDeviceServiceConnection(CountDownLatch latch)114         TestDeviceServiceConnection(CountDownLatch latch) {
115             mLatch = latch;
116         }
117 
118         @Override
onServiceConnected(ComponentName name, IBinder service)119         public void onServiceConnected(ComponentName name, IBinder service) {
120             mExternalService = ITestExternalImsService.Stub.asInterface(service);
121             mLatch.countDown();
122         }
123 
124         @Override
onServiceDisconnected(ComponentName name)125         public void onServiceDisconnected(ComponentName name) {
126             mExternalService = null;
127         }
128     }
129 
130     public class Connection {
131 
132         private static final int CONNECTION_TYPE_IMS_SERVICE_DEVICE = 1;
133         private static final int CONNECTION_TYPE_IMS_SERVICE_CARRIER = 2;
134         private static final int CONNECTION_TYPE_DEFAULT_SMS_APP = 3;
135 
136         private boolean mIsServiceOverridden = false;
137         private String mOrigMmTelServicePackage;
138         private String mOrigRcsServicePackage;
139         private String mOrigSmsPackage;
140         private int mConnectionType;
141         private int mSlotId;
142         private SparseArray<String> mFeatureTypeToPackageOverrideMap = new SparseArray<>(2);
Connection(int connectionType, int slotId)143         Connection(int connectionType, int slotId) {
144             mConnectionType = connectionType;
145             mSlotId = slotId;
146         }
147 
clearPackage()148         void clearPackage() throws Exception {
149             mIsServiceOverridden = true;
150             switch (mConnectionType) {
151                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
152                     boolean unbindSent = setCarrierImsService("none");
153                     if (unbindSent) waitForCarrierPackageUnbind();
154                     break;
155                 }
156                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
157                     boolean unbindSent = setDeviceImsService("");
158                     if (unbindSent) waitForDevicePackageUnbind();
159                     break;
160                 }
161                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
162                     // We don't need to clear anything for default SMS app.
163                     break;
164                 }
165             }
166         }
167 
waitForCarrierPackageUnbind()168         void waitForCarrierPackageUnbind() {
169             TestImsService carrierService = getCarrierService();
170             if (carrierService == null) return;
171             // First unbind the local services
172             removeLocalCarrierServiceConnection();
173             // Then wait for AOSP to unbind if there is still an active binding.
174             boolean isBound = carrierService.isTelephonyBound();
175             if (ImsUtils.VDBG) Log.i(TAG, "waitForCarrierPackageUnbind: isBound=" + isBound);
176             if (isBound) {
177                 // Wait for telephony to unbind to local ImsService
178                 carrierService.waitForLatchCountdown(TestImsService.LATCH_ON_UNBIND);
179             }
180         }
181 
waitForDevicePackageUnbind()182         void waitForDevicePackageUnbind() throws Exception {
183             // Wait until the ImsService unbinds
184             ITestExternalImsService externalService = getExternalService();
185             if (externalService == null) return;
186             // First unbind the local services
187             removeLocalExternalServiceConnection();
188             // Then wait for AOSP to unbind if there is still an active binding.
189             boolean isBound = externalService.isTelephonyBound();
190             if (ImsUtils.VDBG) Log.i(TAG, "waitForDevicePackageUnbind: isBound=" + isBound);
191             if (isBound) {
192                 // Wait for telephony to unbind to external ImsService
193                 externalService.waitForLatchCountdown(TestImsService.LATCH_ON_UNBIND);
194             }
195         }
196 
overrideService(ImsFeatureConfiguration config)197         boolean overrideService(ImsFeatureConfiguration config) throws Exception {
198             mIsServiceOverridden = true;
199             switch (mConnectionType) {
200                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
201                     return bindCarrierImsService(config, PACKAGE_NAME);
202                 }
203                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
204                     return bindDeviceImsService(config, EXTERNAL_PACKAGE_NAME);
205                 }
206                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
207                     return setDefaultSmsApp(PACKAGE_NAME);
208                 }
209             }
210             return false;
211         }
212 
restoreOriginalPackage()213         void restoreOriginalPackage() throws Exception {
214             if (!mIsServiceOverridden) {
215                 return;
216             }
217             mIsServiceOverridden = false;
218 
219             if (mOrigRcsServicePackage == null) {
220                 mOrigRcsServicePackage = "";
221             }
222 
223             if (mOrigMmTelServicePackage == null) {
224                 mOrigMmTelServicePackage = "";
225             }
226 
227             switch (mConnectionType) {
228                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
229                     clearCarrierImsServiceOverride();
230                     break;
231                 }
232                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
233                     setDeviceImsService(mOrigMmTelServicePackage, ImsFeature.FEATURE_MMTEL);
234                     setDeviceImsService(mOrigRcsServicePackage, ImsFeature.FEATURE_RCS);
235                     break;
236                 }
237                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
238                     setDefaultSmsApp(mOrigSmsPackage);
239                     break;
240                 }
241             }
242         }
243 
244         /**
245          * @return true if the configuration set here still exists in telephony or false if it was
246          * changed (due to something like a Phone process crash).
247          */
checkConfigurationExists()248         boolean checkConfigurationExists() throws Exception {
249             boolean result = true;
250             String mmTelPackage = mFeatureTypeToPackageOverrideMap.get(ImsFeature.FEATURE_MMTEL);
251             String rcsPackage = mFeatureTypeToPackageOverrideMap.get(ImsFeature.FEATURE_RCS);
252             switch (mConnectionType) {
253                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
254                     result &= isPackageTheSame(mmTelPackage, getMmTelCarrierService());
255                     result &= isPackageTheSame(rcsPackage, getRcsCarrierService());
256                     break;
257                 }
258                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
259                     result &= isPackageTheSame(mmTelPackage, getMmTelDeviceService());
260                     result &= isPackageTheSame(rcsPackage, getRcsDeviceService());
261                     break;
262                 }
263                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
264                     break;
265                 }
266             }
267             return result;
268         }
269 
isPackageTheSame(String pkgA, String pkgB)270         private boolean isPackageTheSame(String pkgA, String pkgB) {
271             if (TextUtils.isEmpty(pkgA) && TextUtils.isEmpty(pkgB)) {
272                 return true;
273             }
274             return TextUtils.equals(pkgA, pkgB);
275         }
276 
storeOriginalPackage()277         private void storeOriginalPackage() throws Exception {
278             switch (mConnectionType) {
279                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
280                     mOrigMmTelServicePackage = getMmTelCarrierService();
281                     mOrigRcsServicePackage = getRcsCarrierService();
282                     break;
283                 }
284                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
285                     mOrigMmTelServicePackage = getMmTelDeviceService();
286                     mOrigRcsServicePackage = getRcsDeviceService();
287                     break;
288                 }
289                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
290                     mOrigSmsPackage = getDefaultSmsApp();
291                     break;
292                 }
293             }
294         }
295 
setDeviceImsService(String packageName)296         private boolean setDeviceImsService(String packageName) throws Exception {
297             mFeatureTypeToPackageOverrideMap.put(ImsFeature.FEATURE_MMTEL, packageName);
298             mFeatureTypeToPackageOverrideMap.put(ImsFeature.FEATURE_RCS, packageName);
299             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
300                     constructSetImsServiceOverrideCommand(false, packageName, new int[] {
301                             ImsFeature.FEATURE_MMTEL, ImsFeature.FEATURE_RCS}));
302             if (ImsUtils.VDBG) {
303                 Log.d(TAG, "setDeviceMmTelImsService result: " + result);
304             }
305             return "true".equals(result);
306         }
307 
setCarrierImsService(String packageName)308         private boolean setCarrierImsService(String packageName) throws Exception {
309             mFeatureTypeToPackageOverrideMap.put(ImsFeature.FEATURE_MMTEL, packageName);
310             mFeatureTypeToPackageOverrideMap.put(ImsFeature.FEATURE_RCS, packageName);
311             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
312                     constructSetImsServiceOverrideCommand(true, packageName, new int[] {
313                             ImsFeature.FEATURE_EMERGENCY_MMTEL, ImsFeature.FEATURE_MMTEL,
314                             ImsFeature.FEATURE_RCS}));
315             if (ImsUtils.VDBG) {
316                 Log.d(TAG, "setCarrierMmTelImsService result: " + result);
317             }
318             return "true".equals(result);
319         }
320 
setDeviceImsService(String packageName, int featureType)321         private boolean setDeviceImsService(String packageName, int featureType) throws Exception {
322             mFeatureTypeToPackageOverrideMap.put(featureType, packageName);
323             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
324                     constructSetImsServiceOverrideCommand(false, packageName,
325                             new int[]{featureType}));
326             if (ImsUtils.VDBG) {
327                 Log.d(TAG, "setDeviceMmTelImsService result: " + result);
328             }
329             return "true".equals(result);
330         }
331 
setCarrierImsService(String packageName, int featureType)332         private boolean setCarrierImsService(String packageName, int featureType) throws Exception {
333             mFeatureTypeToPackageOverrideMap.put(featureType, packageName);
334             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
335                     constructSetImsServiceOverrideCommand(true, packageName,
336                             new int[]{featureType}));
337             if (ImsUtils.VDBG) {
338                 Log.d(TAG, "setCarrierMmTelImsService result: " + result);
339             }
340             return "true".equals(result);
341         }
342 
clearCarrierImsServiceOverride()343         private boolean clearCarrierImsServiceOverride() throws Exception {
344             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
345                     constructClearCarrierImsServiceOverrideCommand());
346             if (ImsUtils.VDBG) {
347                 Log.d(TAG, "clearCarrierImsServiceOverride result: " + result);
348             }
349             return "true".equals(result);
350         }
351 
setDefaultSmsApp(String packageName)352         private boolean setDefaultSmsApp(String packageName) throws Exception {
353             RoleManager roleManager = mInstrumentation.getContext()
354                     .getSystemService(RoleManager.class);
355             Boolean result;
356             LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1);
357             if (TextUtils.isEmpty(packageName)) {
358                 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(roleManager,
359                         (m) -> m.clearRoleHoldersAsUser(RoleManager.ROLE_SMS,
360                                 RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
361                                 android.os.Process.myUserHandle(),
362                                 // Run on calling binder thread.
363                                 Runnable::run, queue::offer));
364             } else {
365                 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(roleManager,
366                         (m) -> m.addRoleHolderAsUser(RoleManager.ROLE_SMS, packageName, 0,
367                                 android.os.Process.myUserHandle(),
368                                 // Run on calling binder thread.
369                                 Runnable::run, queue::offer));
370             }
371             result = queue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
372             if (ImsUtils.VDBG) {
373                 Log.d(TAG, "setDefaultSmsApp result: " + result);
374             }
375             return result;
376         }
377 
getDefaultSmsApp()378         private String getDefaultSmsApp() throws Exception {
379             RoleManager roleManager = mInstrumentation.getContext()
380                     .getSystemService(RoleManager.class);
381             List<String> result = ShellIdentityUtils.invokeMethodWithShellPermissions(roleManager,
382                     (m) -> m.getRoleHolders(RoleManager.ROLE_SMS));
383             if (ImsUtils.VDBG) {
384                 Log.d(TAG, "getDefaultSmsApp result: " + result);
385             }
386             if (result.isEmpty()) {
387                 // No default SMS app.
388                 return null;
389             }
390             // There should only be one default sms app
391             return result.get(0);
392         }
393 
bindCarrierImsService(ImsFeatureConfiguration config, String packageName)394         private boolean bindCarrierImsService(ImsFeatureConfiguration config, String packageName)
395                 throws Exception {
396             getCarrierService().setFeatureConfig(config);
397             return setCarrierImsService(packageName) && getCarrierService().waitForLatchCountdown(
398                             TestImsService.LATCH_FEATURES_READY);
399         }
400 
bindDeviceImsService(ImsFeatureConfiguration config, String packageName)401         private boolean bindDeviceImsService(ImsFeatureConfiguration config, String packageName)
402                 throws Exception {
403             getExternalService().setFeatureConfig(config);
404             return setDeviceImsService(packageName) && getExternalService().waitForLatchCountdown(
405                     TestImsService.LATCH_FEATURES_READY);
406         }
407 
getMmTelCarrierService()408         private String getMmTelCarrierService() throws Exception {
409             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
410                     constructGetImsServiceCommand(true, ImsFeature.FEATURE_MMTEL));
411             if (ImsUtils.VDBG) {
412                 Log.d(TAG, "getMmTelCarrierService result: " + result);
413             }
414             return result;
415         }
416 
getRcsCarrierService()417         private String getRcsCarrierService() throws Exception {
418             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
419                     constructGetImsServiceCommand(true, ImsFeature.FEATURE_RCS));
420             if (ImsUtils.VDBG) {
421                 Log.d(TAG, "getRcsCarrierService result: " + result);
422             }
423             return result;
424         }
425 
getMmTelDeviceService()426         private String getMmTelDeviceService() throws Exception {
427             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
428                     constructGetImsServiceCommand(false, ImsFeature.FEATURE_MMTEL));
429             if (ImsUtils.VDBG) {
430                 Log.d(TAG, "getMmTelDeviceService result: " + result);
431             }
432             return result;
433         }
434 
getRcsDeviceService()435         private String getRcsDeviceService() throws Exception {
436             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
437                     constructGetImsServiceCommand(false, ImsFeature.FEATURE_RCS));
438             if (ImsUtils.VDBG) {
439                 Log.d(TAG, "getRcsDeviceService result: " + result);
440             }
441             return result;
442         }
443 
constructSetImsServiceOverrideCommand(boolean isCarrierService, String packageName, int[] featureTypes)444         private String constructSetImsServiceOverrideCommand(boolean isCarrierService,
445                 String packageName, int[] featureTypes) {
446             return COMMAND_BASE + COMMAND_SET_IMS_SERVICE + COMMAND_SLOT_IDENTIFIER + mSlotId + " "
447                     + (isCarrierService
448                         ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER)
449                     + COMMAND_FEATURE_IDENTIFIER + getFeatureTypesString(featureTypes) + " "
450                     + packageName;
451         }
452 
constructGetImsServiceCommand(boolean isCarrierService, int featureType)453         private String constructGetImsServiceCommand(boolean isCarrierService, int featureType) {
454             return COMMAND_BASE + COMMAND_GET_IMS_SERVICE + COMMAND_SLOT_IDENTIFIER + mSlotId + " "
455                     + (isCarrierService
456                         ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER)
457                     + COMMAND_FEATURE_IDENTIFIER + featureType;
458         }
459 
constructClearCarrierImsServiceOverrideCommand()460         private String constructClearCarrierImsServiceOverrideCommand() {
461             return COMMAND_BASE + COMMAND_CLEAR_SERVICE_OVERRIDE + COMMAND_SLOT_IDENTIFIER
462                     + mSlotId;
463         }
464 
getFeatureTypesString(int[] featureTypes)465         private String getFeatureTypesString(int[] featureTypes) {
466             if (featureTypes.length == 0) return "";
467             StringBuilder builder = new StringBuilder();
468             builder.append(featureTypes[0]);
469             for (int i = 1; i < featureTypes.length; i++) {
470                 builder.append(",");
471                 builder.append(featureTypes[i]);
472             }
473             return builder.toString();
474         }
475     }
476 
477     private Instrumentation mInstrumentation;
478 
479     private TestImsService mCarrierService;
480     private TestCarrierServiceConnection mCarrierServiceConn;
481     private ITestExternalImsService mExternalService;
482     private TestDeviceServiceConnection mExternalServiceConn;
483 
484     private Connection mDeviceServiceConnection;
485     private Connection mCarrierServiceConnection;
486     private Connection mDefaultSmsAppConnection;
487 
ImsServiceConnector(Instrumentation instrumentation)488     ImsServiceConnector(Instrumentation instrumentation) {
489         mInstrumentation = instrumentation;
490     }
491 
clearAllActiveImsServices(int slotId)492     void clearAllActiveImsServices(int slotId) throws Exception {
493         mDeviceServiceConnection = new Connection(Connection.CONNECTION_TYPE_IMS_SERVICE_DEVICE,
494                 slotId);
495         mDeviceServiceConnection.storeOriginalPackage();
496         mDeviceServiceConnection.clearPackage();
497 
498         mCarrierServiceConnection = new Connection(Connection.CONNECTION_TYPE_IMS_SERVICE_CARRIER,
499                 slotId);
500         mCarrierServiceConnection.storeOriginalPackage();
501         mCarrierServiceConnection.clearPackage();
502 
503         mDefaultSmsAppConnection = new Connection(Connection.CONNECTION_TYPE_DEFAULT_SMS_APP,
504                 slotId);
505         mDefaultSmsAppConnection.storeOriginalPackage();
506         // No need to clear SMS App, only replace when necessary.
507     }
508 
509     /**
510      * Binds to the local implementation of ImsService but does not trigger ImsService bind from
511      * telephony to allow additional configuration steps.
512      * @return true if this request succeeded, false otherwise.
513      */
connectCarrierImsServiceLocally()514     boolean connectCarrierImsServiceLocally() {
515         if (!setupLocalCarrierImsService()) {
516             Log.w(TAG, "connectCarrierImsService: couldn't set up service.");
517             return false;
518         }
519         mCarrierService.resetState();
520         if (mIsTestTypeExecutor) {
521             mCarrierService.setExecutorTestType(mIsTestTypeExecutor);
522             // reset the mIsTestTypeExecutor value
523             mIsTestTypeExecutor = false;
524         }
525         return true;
526     }
527 
528     /**
529      * Trigger the telephony framework to bind to the local ImsService implementation.
530      * @return true if this request succeeded, false otherwise.
531      */
triggerFrameworkConnectionToCarrierImsService( ImsFeatureConfiguration config)532     boolean triggerFrameworkConnectionToCarrierImsService(
533             ImsFeatureConfiguration config) throws Exception {
534         return mCarrierServiceConnection.overrideService(config);
535     }
536 
connectCarrierImsService(ImsFeatureConfiguration config)537     boolean connectCarrierImsService(ImsFeatureConfiguration config) throws Exception {
538         if (!connectCarrierImsServiceLocally()) return false;
539         return triggerFrameworkConnectionToCarrierImsService(config);
540     }
541 
connectDeviceImsService(ImsFeatureConfiguration config)542     boolean connectDeviceImsService(ImsFeatureConfiguration config) throws Exception {
543         if (!setupExternalImsService()) {
544             Log.w(TAG, "connectDeviceImsService: couldn't set up service.");
545             return false;
546         }
547         mExternalService.resetState();
548         return mDeviceServiceConnection.overrideService(config);
549     }
550 
setDefaultSmsApp()551     boolean setDefaultSmsApp() throws Exception {
552         return mDefaultSmsAppConnection.overrideService(null);
553     }
554 
restoreDefaultSmsApp()555     void restoreDefaultSmsApp() throws Exception {
556         mDefaultSmsAppConnection.restoreOriginalPackage();
557     }
558 
disconnectCarrierImsService()559     void disconnectCarrierImsService() throws Exception {
560         mCarrierServiceConnection.clearPackage();
561     }
562 
disconnectDeviceImsService()563     void disconnectDeviceImsService() throws Exception {
564         mDeviceServiceConnection.clearPackage();
565     }
566 
isCarrierServiceStillConfigured()567     boolean isCarrierServiceStillConfigured() throws Exception {
568         return mCarrierServiceConnection.checkConfigurationExists();
569     }
570 
setupLocalCarrierImsService()571     private boolean setupLocalCarrierImsService() {
572         if (mCarrierService != null) {
573             return true;
574         }
575         CountDownLatch latch = new CountDownLatch(1);
576         mCarrierServiceConn = new TestCarrierServiceConnection(latch);
577         mInstrumentation.getContext().bindService(new Intent(mInstrumentation.getContext(),
578                         TestImsService.class), mCarrierServiceConn, Context.BIND_AUTO_CREATE);
579         try {
580             return latch.await(5000, TimeUnit.MILLISECONDS);
581         } catch (InterruptedException e) {
582             return false;
583         }
584     }
585 
setupExternalImsService()586     private boolean setupExternalImsService() {
587         if (mExternalService != null) {
588             return true;
589         }
590         CountDownLatch latch = new CountDownLatch(1);
591         mExternalServiceConn = new TestDeviceServiceConnection(latch);
592         Intent deviceIntent = new Intent();
593         deviceIntent.setComponent(new ComponentName(EXTERNAL_PACKAGE_NAME,
594                 TestExternalImsService.class.getName()));
595         mInstrumentation.getContext().bindService(deviceIntent, mExternalServiceConn,
596                 Context.BIND_AUTO_CREATE);
597         try {
598             return latch.await(5000, TimeUnit.MILLISECONDS);
599         } catch (InterruptedException e) {
600             return false;
601         }
602     }
603 
removeLocalCarrierServiceConnection()604     void removeLocalCarrierServiceConnection() {
605         if (mCarrierServiceConn != null) {
606             mInstrumentation.getContext().unbindService(mCarrierServiceConn);
607             mCarrierServiceConn = null;
608             mCarrierService = null;
609         }
610     }
611 
removeLocalExternalServiceConnection()612     void removeLocalExternalServiceConnection() {
613         if (mExternalServiceConn != null) {
614             mInstrumentation.getContext().unbindService(mExternalServiceConn);
615             mExternalServiceConn = null;
616             mExternalService = null;
617         }
618     }
619 
620     // Detect and disconnect all active services.
disconnectServices()621     void disconnectServices() throws Exception {
622         // Remove local connections
623         removeLocalCarrierServiceConnection();
624         removeLocalExternalServiceConnection();
625         mDeviceServiceConnection.restoreOriginalPackage();
626         mCarrierServiceConnection.restoreOriginalPackage();
627         mDefaultSmsAppConnection.restoreOriginalPackage();
628 
629         // Remove any overrides for single registration state
630         setDeviceSingleRegistrationEnabled(null);
631     }
632 
enableImsService(int slot)633     void enableImsService(int slot) throws Exception {
634         TelephonyUtils.executeShellCommand(mInstrumentation, COMMAND_BASE + COMMAND_ENABLE_IMS
635                 + COMMAND_SLOT_IDENTIFIER + slot);
636     }
637 
disableImsService(int slot)638     void disableImsService(int slot) throws Exception {
639         TelephonyUtils.executeShellCommand(mInstrumentation, COMMAND_BASE + COMMAND_DISABLE_IMS
640                 + COMMAND_SLOT_IDENTIFIER + slot);
641     }
642 
setDeviceSingleRegistrationEnabled(Boolean enabled)643     void setDeviceSingleRegistrationEnabled(Boolean enabled) throws Exception {
644         TelephonyUtils.executeShellCommand(mInstrumentation, COMMAND_BASE
645                 + COMMAND_SET_DEVICE_SINGLE_REGISTRATION_ENABLED
646                 // if "null" is sent, it will remove override
647                 + (enabled != null ? enabled : "null"));
648     }
649 
getDeviceSingleRegistrationEnabled()650     boolean getDeviceSingleRegistrationEnabled() throws Exception {
651         return Boolean.parseBoolean(TelephonyUtils.executeShellCommand(mInstrumentation,
652                 COMMAND_BASE + COMMAND_GET_DEVICE_SINGLE_REGISTRATION_ENABLED));
653     }
654 
getCarrierSingleRegistrationEnabled()655     boolean getCarrierSingleRegistrationEnabled() throws Exception {
656         return Boolean.parseBoolean(TelephonyUtils.executeShellCommand(mInstrumentation,
657                 COMMAND_BASE + COMMAND_GET_CARRIER_SINGLE_REGISTRATION_ENABLED));
658     }
659 
getDeviceUceEnabled()660     boolean getDeviceUceEnabled() throws Exception {
661         return Boolean.parseBoolean(TelephonyUtils.executeShellCommand(mInstrumentation,
662                 COMMAND_BASE + COMMAND_GET_UCE_ENABLED));
663     }
664 
setDeviceUceEnabled(boolean isEnabled)665     void setDeviceUceEnabled(boolean isEnabled) throws Exception {
666         TelephonyUtils.executeShellCommand(mInstrumentation,
667                 COMMAND_BASE + COMMAND_SET_UCE_ENABLED + isEnabled);
668     }
669 
removeEabContacts(int slotId, String phoneNum)670     void removeEabContacts(int slotId, String phoneNum) throws Exception {
671         StringBuilder cmdBuilder = new StringBuilder();
672         cmdBuilder.append(COMMAND_BASE).append(COMMAND_REMOVE_EAB_CONTACT)
673                 .append(COMMAND_SLOT_IDENTIFIER).append(slotId).append(" ").append(phoneNum);
674         TelephonyUtils.executeShellCommand(mInstrumentation, cmdBuilder.toString());
675     }
676 
getCarrierService()677     TestImsService getCarrierService() {
678         return mCarrierService;
679     }
680 
getExternalService()681     ITestExternalImsService getExternalService() {
682         return mExternalService;
683     }
684 
setSingleRegistrationTestModeEnabled(boolean enabled)685     void setSingleRegistrationTestModeEnabled(boolean enabled) throws Exception {
686         TelephonyUtils.executeShellCommand(mInstrumentation, COMMAND_BASE
687                 + COMMAND_SET_TEST_MODE_ENABLED  + (enabled ? "true" : "false"));
688     }
689 
removeUceRequestDisallowedStatus(int slotId)690     void removeUceRequestDisallowedStatus(int slotId) throws Exception {
691         StringBuilder cmdBuilder = new StringBuilder();
692         cmdBuilder.append(COMMAND_BASE).append(COMMAND_REMOVE_UCE_REQUEST_DISALLOWED_STATUS)
693                 .append(COMMAND_SLOT_IDENTIFIER).append(slotId);
694         TelephonyUtils.executeShellCommand(mInstrumentation, cmdBuilder.toString());
695     }
696 
setCapabilitiesRequestTimeout(int slotId, long timeoutAfterMs)697     void setCapabilitiesRequestTimeout(int slotId, long timeoutAfterMs) throws Exception {
698         StringBuilder cmdBuilder = new StringBuilder();
699         cmdBuilder.append(COMMAND_BASE).append(COMMAND_SET_CAPABILITY_REQUEST_TIMEOUT)
700                 .append(COMMAND_SLOT_IDENTIFIER).append(slotId).append(" ").append(timeoutAfterMs);
701         TelephonyUtils.executeShellCommand(mInstrumentation, cmdBuilder.toString());
702     }
703 
setDeviceToDeviceCommunicationEnabled(boolean enabled)704     void setDeviceToDeviceCommunicationEnabled(boolean enabled) throws Exception {
705         TelephonyUtils.executeShellCommand(mInstrumentation, COMMAND_BASE
706                 + COMMAND_SET_D2D_ENABLED  + (enabled ? "true" : "default"));
707     }
708 }
709