1 /* 2 * Copyright (C) 2021 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 static android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities.DUPLEX_MODE_RECEIVE_ONLY; 20 import static android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities.DUPLEX_MODE_SEND_ONLY; 21 import static android.telephony.ims.RcsContactPresenceTuple.TUPLE_BASIC_STATUS_OPEN; 22 import static android.telephony.ims.RcsContactUceCapability.REQUEST_RESULT_FOUND; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertTrue; 27 import static org.junit.Assert.fail; 28 29 import android.app.UiAutomation; 30 import android.content.BroadcastReceiver; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.net.Uri; 35 import android.os.PersistableBundle; 36 import android.telecom.PhoneAccount; 37 import android.telephony.CarrierConfigManager; 38 import android.telephony.SubscriptionManager; 39 import android.telephony.TelephonyManager; 40 import android.telephony.cts.util.TelephonyUtils; 41 import android.telephony.ims.ImsException; 42 import android.telephony.ims.ImsManager; 43 import android.telephony.ims.ProvisioningManager; 44 import android.telephony.ims.RcsContactPresenceTuple; 45 import android.telephony.ims.RcsContactUceCapability; 46 import android.telephony.ims.RcsUceAdapter; 47 import android.telephony.ims.feature.ImsFeature; 48 import android.telephony.ims.stub.ImsFeatureConfiguration; 49 import android.util.Log; 50 51 import androidx.test.platform.app.InstrumentationRegistry; 52 53 import com.android.compatibility.common.util.ShellIdentityUtils; 54 import com.android.i18n.phonenumbers.NumberParseException; 55 import com.android.i18n.phonenumbers.PhoneNumberUtil; 56 import com.android.i18n.phonenumbers.Phonenumber; 57 58 import org.junit.After; 59 import org.junit.AfterClass; 60 import org.junit.Before; 61 import org.junit.BeforeClass; 62 import org.junit.Test; 63 64 import java.text.SimpleDateFormat; 65 import java.time.Instant; 66 import java.util.ArrayList; 67 import java.util.GregorianCalendar; 68 import java.util.List; 69 import java.util.Random; 70 import java.util.concurrent.BlockingQueue; 71 import java.util.concurrent.CountDownLatch; 72 import java.util.concurrent.LinkedBlockingQueue; 73 import java.util.concurrent.TimeUnit; 74 75 public class EabControllerTest { 76 77 private static final String TAG = "EabControllerTest"; 78 private static final String COMMAND_BASE = "cmd phone "; 79 private static final String COMMAND_GET_EAB_CONTACT = "uce get-eab-capability "; 80 81 private static int sTestSlot = SubscriptionManager.INVALID_SIM_SLOT_INDEX; 82 private static int sTestSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 83 private static ImsServiceConnector sServiceConnector; 84 private static CarrierConfigReceiver sReceiver; 85 private static String sTestPhoneNumber; 86 private static Uri sTestNumberUri; 87 private static boolean sDeviceUceEnabled; 88 89 private static final String TEST_SERVICE_DESCRIPTION = "description_test1"; 90 private static final int EXPIRATION_TIME_IN_SEC = 1; 91 private static final int WAITING_IN_MILLI_SEC = 1000; 92 private static final int POLLING_RETRY_TIMES = 3; 93 94 BlockingQueue<Long> mErrorQueue = new LinkedBlockingQueue<>(); 95 BlockingQueue<Boolean> mCompleteQueue = new LinkedBlockingQueue<>(); 96 BlockingQueue<RcsContactUceCapability> mCapabilityQueue = new LinkedBlockingQueue<>(); 97 RcsUceAdapter.CapabilitiesCallback mCallback = new RcsUceAdapter.CapabilitiesCallback() { 98 @Override 99 public void onCapabilitiesReceived(List<RcsContactUceCapability> capabilities) { 100 capabilities.forEach(c -> mCapabilityQueue.offer(c)); 101 } 102 103 @Override 104 public void onComplete() { 105 mCompleteQueue.offer(true); 106 } 107 108 @Override 109 public void onError(int errorCode, long retryAfterMilliseconds) { 110 mErrorQueue.offer(new Long(errorCode)); 111 mErrorQueue.offer(retryAfterMilliseconds); 112 } 113 }; 114 115 private static class CarrierConfigReceiver extends BroadcastReceiver { 116 private CountDownLatch mLatch = new CountDownLatch(1); 117 private final int mSubId; 118 CarrierConfigReceiver(int subId)119 CarrierConfigReceiver(int subId) { 120 mSubId = subId; 121 } 122 123 @Override onReceive(Context context, Intent intent)124 public void onReceive(Context context, Intent intent) { 125 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) { 126 int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1); 127 if (mSubId == subId) { 128 mLatch.countDown(); 129 } 130 } 131 } 132 clearQueue()133 void clearQueue() { 134 mLatch = new CountDownLatch(1); 135 } 136 waitForCarrierConfigChanged()137 void waitForCarrierConfigChanged() throws Exception { 138 mLatch.await(5000, TimeUnit.MILLISECONDS); 139 } 140 } 141 142 @BeforeClass beforeAllTests()143 public static void beforeAllTests() throws Exception { 144 if (!ImsUtils.shouldTestImsService()) { 145 return; 146 } 147 148 sTestPhoneNumber = generateRandomPhoneNumber(); 149 sTestNumberUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, sTestPhoneNumber, null); 150 151 sTestSub = ImsUtils.getPreferredActiveSubId(); 152 sTestSlot = SubscriptionManager.getSlotIndex(sTestSub); 153 154 sServiceConnector = new ImsServiceConnector(InstrumentationRegistry.getInstrumentation()); 155 sServiceConnector.clearAllActiveImsServices(sTestSlot); 156 sDeviceUceEnabled = sServiceConnector.getDeviceUceEnabled(); 157 sServiceConnector.setDeviceUceEnabled(true); 158 159 sReceiver = new CarrierConfigReceiver(sTestSub); 160 IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 161 // ACTION_CARRIER_CONFIG_CHANGED is sticky, so we will get a callback right away. 162 InstrumentationRegistry.getInstrumentation().getContext() 163 .registerReceiver(sReceiver, filter); 164 165 overrideCarrierConfig(); 166 167 connectTestImsService(); 168 } 169 generateRandomPhoneNumber()170 private static String generateRandomPhoneNumber() { 171 Random random = new Random(); 172 StringBuilder builder = new StringBuilder(); 173 for (int i = 0; i < 10; i++) { 174 builder.append(random.nextInt(10)); 175 } 176 return builder.toString(); 177 } 178 179 @AfterClass afterAllTests()180 public static void afterAllTests() throws Exception { 181 if (!ImsUtils.shouldTestImsService()) { 182 return; 183 } 184 // Restore all ImsService configurations that existed before the test. 185 if (sServiceConnector != null) { 186 sServiceConnector.disconnectCarrierImsService(); 187 sServiceConnector.disconnectDeviceImsService(); 188 sServiceConnector.disconnectServices(); 189 sServiceConnector.setDeviceUceEnabled(sDeviceUceEnabled); 190 } 191 sServiceConnector = null; 192 193 overrideCarrierConfig(null); 194 195 if (sReceiver != null) { 196 InstrumentationRegistry.getInstrumentation().getContext().unregisterReceiver(sReceiver); 197 sReceiver = null; 198 } 199 } 200 201 @Before beforeTest()202 public void beforeTest() { 203 if (!ImsUtils.shouldTestImsService()) { 204 return; 205 } 206 if (!SubscriptionManager.isValidSubscriptionId(sTestSub)) { 207 fail("This test requires that there is a SIM in the device!"); 208 } 209 } 210 211 @After afterTest()212 public void afterTest() { 213 if (!ImsUtils.shouldTestImsService()) { 214 return; 215 } 216 // Remove all the test contacts from EAB database 217 removeTestContactFromEab(); 218 219 mErrorQueue.clear(); 220 mCompleteQueue.clear(); 221 mCapabilityQueue.clear(); 222 } 223 224 @Test testRequestCapabilities()225 public void testRequestCapabilities() throws Exception { 226 if (!ImsUtils.shouldTestImsService()) { 227 return; 228 } 229 ArrayList<Uri> contacts = new ArrayList<>(1); 230 contacts.add(sTestNumberUri); 231 fakeNetworkResult(getPidfXmlData( 232 sTestNumberUri, 233 TEST_SERVICE_DESCRIPTION, 234 TUPLE_BASIC_STATUS_OPEN, 235 false, 236 true, 237 DUPLEX_MODE_RECEIVE_ONLY, 238 DUPLEX_MODE_SEND_ONLY)); 239 // Request capabilities for saving capability to EAB provider 240 requestCapabilities(contacts); 241 mErrorQueue.clear(); 242 mCompleteQueue.clear(); 243 mCapabilityQueue.clear(); 244 245 // Request capabilities again to get the capabilities in EAB provider 246 RcsContactUceCapability capability = requestCapabilities(contacts); 247 248 // Verify that the capability in EAB is the same as expected 249 verifyCapabilityResult(capability, 250 sTestNumberUri, 251 TEST_SERVICE_DESCRIPTION, 252 TUPLE_BASIC_STATUS_OPEN, 253 REQUEST_RESULT_FOUND, 254 RcsContactUceCapability.SOURCE_TYPE_CACHED, 255 false, 256 true, 257 DUPLEX_MODE_RECEIVE_ONLY, 258 DUPLEX_MODE_SEND_ONLY); 259 260 // Verify the onCompleted is called 261 waitForResult(mCompleteQueue); 262 } 263 264 @Test testRequestAvailabilities()265 public void testRequestAvailabilities() throws Exception { 266 if (!ImsUtils.shouldTestImsService()) { 267 return; 268 } 269 fakeNetworkResult(getPidfXmlData( 270 sTestNumberUri, 271 TEST_SERVICE_DESCRIPTION, 272 TUPLE_BASIC_STATUS_OPEN, 273 false, 274 true, 275 DUPLEX_MODE_RECEIVE_ONLY, 276 DUPLEX_MODE_SEND_ONLY)); 277 // Request capabilities for saving capability to EAB provider 278 requestAvailability(sTestNumberUri); 279 mErrorQueue.clear(); 280 mCompleteQueue.clear(); 281 mCapabilityQueue.clear(); 282 283 // Request capabilities again to get the capabilities in EAB provider 284 RcsContactUceCapability capability = requestAvailability(sTestNumberUri); 285 286 // Verify that the capability in EAB is the same as expected 287 verifyCapabilityResult(capability, 288 sTestNumberUri, 289 TEST_SERVICE_DESCRIPTION, 290 TUPLE_BASIC_STATUS_OPEN, 291 REQUEST_RESULT_FOUND, 292 RcsContactUceCapability.SOURCE_TYPE_CACHED, 293 false, 294 true, 295 DUPLEX_MODE_RECEIVE_ONLY, 296 DUPLEX_MODE_SEND_ONLY); 297 298 // Verify the onCompleted is called 299 waitForResult(mCompleteQueue); 300 } 301 302 @Test testRequestExpiredCapabilities()303 public void testRequestExpiredCapabilities() throws Exception { 304 if (!ImsUtils.shouldTestImsService()) { 305 return; 306 } 307 308 // Set capabilities expiration time 309 setProvisioningIntValue(ProvisioningManager.KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC, 310 EXPIRATION_TIME_IN_SEC); 311 312 ArrayList<Uri> contacts = new ArrayList<>(1); 313 contacts.add(sTestNumberUri); 314 fakeNetworkResult(getPidfXmlData( 315 sTestNumberUri, 316 TEST_SERVICE_DESCRIPTION, 317 TUPLE_BASIC_STATUS_OPEN, 318 false, 319 true, 320 DUPLEX_MODE_RECEIVE_ONLY, 321 DUPLEX_MODE_SEND_ONLY)); 322 // Request capabilities for saving expired capability to EAB provider 323 requestCapabilities(contacts); 324 mErrorQueue.clear(); 325 mCompleteQueue.clear(); 326 mCapabilityQueue.clear(); 327 328 waitingEabCapabilityExpire(); 329 330 // Request capabilities again 331 RcsContactUceCapability capability = requestCapabilities(contacts); 332 333 // Verify that return the availabilities from network instead of the EAB provider 334 verifyCapabilityResult(capability, 335 sTestNumberUri, 336 TEST_SERVICE_DESCRIPTION, 337 TUPLE_BASIC_STATUS_OPEN, 338 REQUEST_RESULT_FOUND, 339 RcsContactUceCapability.SOURCE_TYPE_NETWORK, 340 false, 341 true, 342 DUPLEX_MODE_RECEIVE_ONLY, 343 DUPLEX_MODE_SEND_ONLY); 344 345 // Verify the onCompleted is called 346 waitForResult(mCompleteQueue); 347 } 348 349 @Test testRequestExpiredAvailabilities()350 public void testRequestExpiredAvailabilities() throws Exception { 351 if (!ImsUtils.shouldTestImsService()) { 352 return; 353 } 354 355 // Set availability expiration time 356 setProvisioningIntValue(ProvisioningManager.KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC, 357 EXPIRATION_TIME_IN_SEC); 358 359 fakeNetworkResult(getPidfXmlData( 360 sTestNumberUri, 361 TEST_SERVICE_DESCRIPTION, 362 TUPLE_BASIC_STATUS_OPEN, 363 true, 364 false, 365 DUPLEX_MODE_RECEIVE_ONLY, 366 DUPLEX_MODE_SEND_ONLY)); 367 // Request availabilities for saving availabilities to EAB provider 368 requestAvailability(sTestNumberUri); 369 mErrorQueue.clear(); 370 mCompleteQueue.clear(); 371 mCapabilityQueue.clear(); 372 373 // Waiting availabilities expire 374 waitingEabCapabilityExpire(); 375 376 // Request availabilities again 377 RcsContactUceCapability capability = requestAvailability(sTestNumberUri); 378 379 // Verify that return the availabilities from network instead of the EAB provider 380 verifyCapabilityResult(capability, 381 sTestNumberUri, 382 TEST_SERVICE_DESCRIPTION, 383 TUPLE_BASIC_STATUS_OPEN, 384 REQUEST_RESULT_FOUND, 385 RcsContactUceCapability.SOURCE_TYPE_NETWORK, 386 true, 387 false, 388 DUPLEX_MODE_RECEIVE_ONLY, 389 DUPLEX_MODE_SEND_ONLY); 390 391 // Verify the onCompleted is called 392 waitForResult(mCompleteQueue); 393 } 394 requestAvailability(Uri contact)395 private RcsContactUceCapability requestAvailability(Uri contact) throws Exception { 396 // Request capabilities by calling the API requestCapabilities. 397 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 398 RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(sTestSub).getUceAdapter(); 399 400 try { 401 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn( 402 uceAdapter, 403 adapter -> adapter.requestAvailability(contact, Runnable::run, 404 mCallback), 405 ImsException.class, 406 "android.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE"); 407 } catch (SecurityException e) { 408 fail("requestCapabilities should succeed with ACCESS_RCS_USER_CAPABILITY_EXCHANGE." 409 + e); 410 } catch (ImsException e) { 411 fail("requestCapabilities failed " + e); 412 } 413 414 // Verify that all the contact's capabilities are received 415 return waitForResult(mCapabilityQueue); 416 } 417 requestCapabilities(List<Uri> contact)418 private RcsContactUceCapability requestCapabilities(List<Uri> contact) throws Exception { 419 // Request capabilities by calling the API requestCapabilities. 420 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 421 RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(sTestSub).getUceAdapter(); 422 423 try { 424 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn( 425 uceAdapter, 426 adapter -> adapter.requestCapabilities(contact, Runnable::run, mCallback), 427 ImsException.class, 428 "android.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE"); 429 } catch (SecurityException e) { 430 fail("requestCapabilities should succeed with ACCESS_RCS_USER_CAPABILITY_EXCHANGE." 431 + e); 432 } catch (ImsException e) { 433 fail("requestCapabilities failed " + e); 434 } 435 436 // Verify that all the contact's capabilities are received 437 return waitForResult(mCapabilityQueue); 438 } 439 overrideCarrierConfig()440 private static void overrideCarrierConfig() throws Exception { 441 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 442 RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(sTestSub).getUceAdapter(); 443 assertNotNull("UCE adapter should not be null!", uceAdapter); 444 445 446 // Trigger carrier config changed 447 PersistableBundle bundle = new PersistableBundle(); 448 bundle.putBoolean(CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, true); 449 bundle.putBoolean(CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, 450 true); 451 overrideCarrierConfig(bundle); 452 } 453 fakeNetworkResult(String pidfXml)454 private void fakeNetworkResult(String pidfXml) { 455 TestRcsCapabilityExchangeImpl capabilityExchangeImpl = sServiceConnector 456 .getCarrierService().getRcsFeature().getRcsCapabilityExchangeImpl(); 457 458 ArrayList<String> pidfXmlList = new ArrayList<>(1); 459 pidfXmlList.add(pidfXml); 460 461 // Setup the network response is 200 OK and notify capabilities update 462 int networkRespCode = 200; 463 String networkRespReason = "OK"; 464 capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> { 465 cb.onNetworkResponse(networkRespCode, networkRespReason); 466 cb.onNotifyCapabilitiesUpdate(pidfXmlList); 467 cb.onTerminated("", 0L); 468 }); 469 } 470 getPidfXmlData(Uri contact, String serviceDescription, String serviceStatus, boolean audioSupported, boolean videoSupported, String supportedDuplexMode, String unSupportedDuplexMode)471 private String getPidfXmlData(Uri contact, 472 String serviceDescription, 473 String serviceStatus, 474 boolean audioSupported, 475 boolean videoSupported, 476 String supportedDuplexMode, 477 String unSupportedDuplexMode) { 478 GregorianCalendar date = new GregorianCalendar(); 479 String timeStamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX") 480 .format(date.getTime()); 481 482 String pidfBuilder = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>" 483 + "<presence entity=\"" + contact + "\"" 484 + " xmlns=\"urn:ietf:params:xml:ns:pidf\"" 485 + " xmlns:op=\"urn:oma:xml:prs:pidf:oma-pres\"" 486 + " xmlns:caps=\"urn:ietf:params:xml:ns:pidf:caps\">" 487 + "<tuple id=\"tid0\">" 488 // status 489 + "<status><basic>" + serviceStatus + "</basic></status>" 490 // timestamp 491 + "<timestamp>" + timeStamp + "</timestamp>" 492 493 // service description 494 + "<op:service-description>" 495 + "<op:service-id>service_id_01</op:service-id>" 496 + "<op:version>1.0</op:version>" 497 + "<op:description>" + serviceDescription + "</op:description>" 498 + "</op:service-description>" 499 500 // service capabilities 501 + "<caps:servcaps>" 502 // audio capabilities 503 + "<caps:audio>" + audioSupported + "</caps:audio>" 504 // video capabilities 505 + "<caps:video>" + videoSupported + "</caps:video>" 506 507 // duplex mode 508 + "<caps:duplex>" 509 // support duplex mode 510 + "<caps:supported>" 511 + "<caps:" + supportedDuplexMode + "/>" 512 + "</caps:supported>" 513 514 // unsupported duplex mode 515 + "<caps:notsupported>" 516 + "<caps:" + unSupportedDuplexMode + "/>" 517 + "</caps:notsupported>" 518 + "</caps:duplex>" 519 + "</caps:servcaps>" 520 + "<contact>" + contact + "</contact>" 521 + "</tuple>" 522 + "</presence>"; 523 return pidfBuilder; 524 } 525 verifyCapabilityResult(RcsContactUceCapability resultCapability, Uri expectedUri, String serviceDescription, String serviceStatus, int expectedResult, int expectedSourceType, boolean expectedAudioSupported, boolean expectedVideoSupported, String expectedSupportedDuplexMode, String expectedUnSupportedDuplexMode)526 private void verifyCapabilityResult(RcsContactUceCapability resultCapability, 527 Uri expectedUri, 528 String serviceDescription, 529 String serviceStatus, 530 int expectedResult, 531 int expectedSourceType, 532 boolean expectedAudioSupported, 533 boolean expectedVideoSupported, 534 String expectedSupportedDuplexMode, 535 String expectedUnSupportedDuplexMode) { 536 // Verify the contact URI 537 assertEquals(expectedUri, resultCapability.getContactUri()); 538 539 // Verify the source type is the network type. 540 assertEquals(expectedSourceType, resultCapability.getSourceType()); 541 542 // Verify the request result is expected. 543 final int requestResult = resultCapability.getRequestResult(); 544 assertEquals(requestResult, expectedResult); 545 546 // Verify the mechanism is presence 547 assertEquals(RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE, 548 resultCapability.getCapabilityMechanism()); 549 550 RcsContactPresenceTuple presenceTuple = 551 resultCapability.getCapabilityTuple("service_id_01"); 552 assertNotNull("Contact Presence tuple should not be null!", presenceTuple); 553 554 RcsContactPresenceTuple.ServiceCapabilities capabilities = 555 presenceTuple.getServiceCapabilities(); 556 assertNotNull("Service capabilities should not be null!", capabilities); 557 558 // Verify timestamp 559 assertNotNull("Timestamp should not be null!", presenceTuple.getTime()); 560 561 // Verify service id 562 assertEquals("service_id_01", presenceTuple.getServiceId()); 563 564 // Verify service status 565 assertEquals(serviceStatus, presenceTuple.getStatus()); 566 567 // Verify service description 568 assertEquals(serviceDescription, presenceTuple.getServiceDescription()); 569 570 // Verify audio 571 assertEquals(expectedAudioSupported, capabilities.isAudioCapable()); 572 573 // Verify video 574 assertEquals(expectedVideoSupported, capabilities.isVideoCapable()); 575 576 // Verify Supported Duplex Mode 577 assertEquals(expectedSupportedDuplexMode, capabilities.getSupportedDuplexModes().get(0)); 578 579 // Verify UnSupported Duplex Mode 580 assertEquals(expectedUnSupportedDuplexMode, 581 capabilities.getUnsupportedDuplexModes().get(0)); 582 } 583 waitForResult(BlockingQueue<T> queue)584 private <T> T waitForResult(BlockingQueue<T> queue) throws Exception { 585 return queue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS); 586 } 587 getContext()588 private static Context getContext() { 589 return InstrumentationRegistry.getInstrumentation().getContext(); 590 } 591 connectTestImsService()592 private static void connectTestImsService() throws Exception { 593 assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder() 594 .addFeature(sTestSlot, ImsFeature.FEATURE_RCS) 595 .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL) 596 .build())); 597 598 // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the 599 // Framework did not call it. 600 assertTrue("Did not receive createRcsFeature", sServiceConnector.getCarrierService() 601 .waitForLatchCountdown(TestImsService.LATCH_CREATE_RCS)); 602 assertTrue("Did not receive RcsFeature#onReady", sServiceConnector.getCarrierService() 603 .waitForLatchCountdown(TestImsService.LATCH_RCS_READY)); 604 // Make sure the RcsFeature was created in the test service. 605 assertNotNull("Device ImsService created, but TestDeviceImsService#createRcsFeature was not" 606 + "called!", sServiceConnector.getCarrierService().getRcsFeature()); 607 assertTrue("Did not receive RcsFeature#setCapabilityExchangeEventListener", 608 sServiceConnector.getCarrierService().waitForLatchCountdown( 609 TestImsService.LATCH_UCE_LISTENER_SET)); 610 int serviceSlot = sServiceConnector.getCarrierService().getRcsFeature().getSlotIndex(); 611 assertEquals("The slot specified for the test (" + sTestSlot + ") does not match the " 612 + "assigned slot (" + serviceSlot + "+ for the associated RcsFeature", 613 sTestSlot, serviceSlot); 614 } 615 overrideCarrierConfig(PersistableBundle bundle)616 private static void overrideCarrierConfig(PersistableBundle bundle) throws Exception { 617 CarrierConfigManager carrierConfigManager = InstrumentationRegistry.getInstrumentation() 618 .getContext().getSystemService(CarrierConfigManager.class); 619 sReceiver.clearQueue(); 620 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(carrierConfigManager, 621 (m) -> m.overrideConfig(sTestSub, bundle)); 622 sReceiver.waitForCarrierConfigChanged(); 623 } 624 removeTestContactFromEab()625 private static void removeTestContactFromEab() { 626 try { 627 sServiceConnector.removeEabContacts(sTestSlot, sTestPhoneNumber); 628 } catch (Exception e) { 629 Log.w("RcsUceAdapterTest", "Cannot remove test contacts from eab database: " + e); 630 } 631 } 632 formatNumber(Context context, String number)633 private static String formatNumber(Context context, String number) { 634 TelephonyManager manager = context.getSystemService(TelephonyManager.class); 635 String simCountryIso = manager.getSimCountryIso(); 636 if (simCountryIso != null) { 637 simCountryIso = simCountryIso.toUpperCase(); 638 PhoneNumberUtil util = PhoneNumberUtil.getInstance(); 639 try { 640 Phonenumber.PhoneNumber phoneNumber = util.parse(number, simCountryIso); 641 return util.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164); 642 } catch (NumberParseException e) { 643 Log.w(TAG, "formatNumber: could not format " + number + ", error: " + e); 644 } 645 } 646 return number; 647 } 648 getEabCapabilities(String phoneNum)649 private String getEabCapabilities(String phoneNum) throws Exception { 650 StringBuilder cmdBuilder = new StringBuilder(); 651 cmdBuilder.append(COMMAND_BASE).append(COMMAND_GET_EAB_CONTACT) 652 .append(" ").append(phoneNum); 653 return TelephonyUtils.executeShellCommand(InstrumentationRegistry.getInstrumentation(), 654 cmdBuilder.toString()); 655 } 656 setProvisioningIntValue(int key, int value)657 private void setProvisioningIntValue(int key, int value) { 658 final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 659 try { 660 automan.adoptShellPermissionIdentity(); 661 ProvisioningManager provisioningManager = 662 ProvisioningManager.createForSubscriptionId(sTestSub); 663 provisioningManager.setProvisioningIntValue(key, value); 664 } finally { 665 automan.dropShellPermissionIdentity(); 666 } 667 } 668 waitingEabCapabilityExpire()669 private void waitingEabCapabilityExpire() throws Exception { 670 int retryTimes = POLLING_RETRY_TIMES; 671 long expirationTime; 672 do { 673 String capabilities = getEabCapabilities(formatNumber(getContext(), sTestPhoneNumber)); 674 String[] capabilityInfo = capabilities.split(","); 675 assertTrue(capabilityInfo.length > 4); 676 Thread.sleep(WAITING_IN_MILLI_SEC); 677 expirationTime = Long.parseLong(capabilityInfo[2]); 678 retryTimes--; 679 } while (retryTimes > 0 && Instant.now().getEpochSecond() < expirationTime); 680 } 681 } 682