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