1 /* 2 * Copyright (C) 2022 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 junit.framework.Assert.assertNotNull; 20 import static junit.framework.Assert.assertTrue; 21 22 import static org.junit.Assert.assertEquals; 23 24 import android.app.Instrumentation; 25 import android.app.UiAutomation; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.PackageManager; 31 import android.net.Uri; 32 import android.os.Bundle; 33 import android.os.PersistableBundle; 34 import android.telecom.Call; 35 import android.telecom.cts.TestUtils; 36 import android.telephony.CarrierConfigManager; 37 import android.telephony.SubscriptionManager; 38 import android.telephony.cts.InCallServiceStateValidator; 39 import android.telephony.cts.InCallServiceStateValidator.InCallServiceCallbacks; 40 import android.telephony.cts.util.TelephonyUtils; 41 import android.telephony.ims.feature.ImsFeature; 42 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities; 43 import android.telephony.ims.stub.ImsFeatureConfiguration; 44 import android.telephony.ims.stub.ImsRegistrationImplBase; 45 import android.util.Log; 46 47 import androidx.test.platform.app.InstrumentationRegistry; 48 49 import com.android.compatibility.common.util.ShellIdentityUtils; 50 51 import java.util.List; 52 import java.util.Map; 53 import java.util.Objects; 54 import java.util.concurrent.ConcurrentHashMap; 55 import java.util.concurrent.CountDownLatch; 56 import java.util.concurrent.TimeUnit; 57 58 /** Base class for ImsCall test. */ 59 public class ImsCallingBase { 60 61 protected static ImsServiceConnector sServiceConnector; 62 63 private static final String LOG_TAG = "ImsCallingBase"; 64 65 protected static final String PACKAGE = "android.telephony.ims.cts"; 66 protected static final String PACKAGE_CTS_DIALER = "android.telephony.cts"; 67 protected static final String COMMAND_SET_DEFAULT_DIALER = "telecom set-default-dialer "; 68 protected static final String COMMAND_GET_DEFAULT_DIALER = "telecom get-default-dialer"; 69 protected static final String TEST_EMERGENCY_NUMBER = "5553637"; 70 protected static final Uri TEST_EMERGENCY_URI = 71 Uri.fromParts("tel", TEST_EMERGENCY_NUMBER, null); 72 protected static final String INCALL_COMPONENT = 73 "android.telephony.cts/.InCallServiceStateValidator"; 74 75 // The timeout to wait in current state in milliseconds 76 protected static final int WAIT_IN_CURRENT_STATE = 100; 77 // The timeout to wait in current state after conference call merge failed in milliseconds 78 protected static final int WAIT_IN_CURRENT_STATE_MERGE_FAILED = 500; 79 80 public static final int WAIT_FOR_SERVICE_TO_UNBOUND = 40000; 81 public static final int WAIT_FOR_CONDITION = 3000; 82 public static final int WAIT_FOR_CALL_STATE = 10000; 83 public static final int WAIT_FOR_CALL_STATE_ACTIVE = 15000; 84 public static final int LATCH_INCALL_SERVICE_BOUND = 1; 85 public static final int LATCH_INCALL_SERVICE_UNBOUND = 2; 86 public static final int LATCH_IS_ON_CALL_ADDED = 3; 87 public static final int LATCH_IS_ON_CALL_REMOVED = 4; 88 public static final int LATCH_IS_CALL_DIALING = 5; 89 public static final int LATCH_IS_CALL_ACTIVE = 6; 90 public static final int LATCH_IS_CALL_DISCONNECTING = 7; 91 public static final int LATCH_IS_CALL_DISCONNECTED = 8; 92 public static final int LATCH_IS_CALL_RINGING = 9; 93 public static final int LATCH_IS_CALL_HOLDING = 10; 94 public static final int LATCH_IS_ON_CALL_REMOTELY_HELD = 11; 95 public static final int LATCH_IS_ON_CALL_REMOTELY_UNHELD = 12; 96 public static final int LATCH_IS_ON_CHILDREN_CHANGED = 13; 97 public static final int LATCH_IS_ON_MERGE_START = 14; 98 public static final int LATCH_IS_ON_MERGE_COMPLETE = 15; 99 public static final int LATCH_IS_ON_CONFERENCE_CALL_ADDED = 16; 100 public static final int LATCH_MAX = 17; 101 public static final int TEST_RTP_THRESHOLD_PACKET_LOSS_RATE = 47; 102 public static final int TEST_RTP_THRESHOLD_JITTER_MILLIS = 150; 103 public static final long TEST_RTP_THRESHOLD_INACTIVITY_TIME_MILLIS = 3000; 104 105 protected static boolean sIsBound = false; 106 protected static int sCounter = 5553639; 107 protected static int sTestSlot = 0; 108 protected static int sTestSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 109 protected static long sPreviousOptInStatus = 0; 110 protected static long sPreviousEn4GMode = 0; 111 protected static String sPreviousDefaultDialer; 112 private static CarrierConfigReceiver sReceiver; 113 private static SubscriptionManager sSubscriptionManager; 114 115 protected int mParticipantCount = 0; 116 protected static final Object mLock = new Object(); 117 protected InCallServiceCallbacks mServiceCallBack; 118 protected Context mContext; 119 protected ConcurrentHashMap<String, Call> mCalls = new ConcurrentHashMap<String, Call>(); 120 protected String mCurrentCallId = null; 121 122 protected static final CountDownLatch[] sLatches = new CountDownLatch[LATCH_MAX]; 123 private boolean mIsEmergencyCallingSetup = false; 124 initializeLatches()125 protected static void initializeLatches() { 126 synchronized (mLock) { 127 for (int i = 0; i < LATCH_MAX; i++) { 128 sLatches[i] = new CountDownLatch(1); 129 } 130 } 131 } 132 overrideLatchCount(int latchIndex, int count)133 protected static void overrideLatchCount(int latchIndex, int count) { 134 synchronized (mLock) { 135 sLatches[latchIndex] = new CountDownLatch(count); 136 } 137 } 138 139 callingTestLatchCountdown(int latchIndex, int waitMs)140 public boolean callingTestLatchCountdown(int latchIndex, int waitMs) { 141 boolean complete = false; 142 try { 143 CountDownLatch latch; 144 synchronized (mLock) { 145 latch = sLatches[latchIndex]; 146 } 147 complete = latch.await(waitMs, TimeUnit.MILLISECONDS); 148 } catch (InterruptedException e) { 149 // complete == false 150 } 151 synchronized (mLock) { 152 sLatches[latchIndex] = new CountDownLatch(1); 153 } 154 return complete; 155 } 156 countDownLatch(int latchIndex)157 public void countDownLatch(int latchIndex) { 158 synchronized (mLock) { 159 sLatches[latchIndex].countDown(); 160 } 161 } 162 163 protected abstract static class BaseReceiver extends BroadcastReceiver { 164 protected CountDownLatch mLatch = new CountDownLatch(1); 165 clearQueue()166 void clearQueue() { 167 mLatch = new CountDownLatch(1); 168 } 169 waitForChanged()170 void waitForChanged() throws Exception { 171 mLatch.await(5000, TimeUnit.MILLISECONDS); 172 } 173 } 174 175 protected static class CarrierConfigReceiver extends BaseReceiver { 176 private final int mSubId; 177 CarrierConfigReceiver(int subId)178 CarrierConfigReceiver(int subId) { 179 mSubId = subId; 180 } 181 182 @Override onReceive(Context context, Intent intent)183 public void onReceive(Context context, Intent intent) { 184 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) { 185 int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1); 186 if (mSubId == subId) { 187 mLatch.countDown(); 188 } 189 } 190 } 191 } 192 193 public interface Condition { expected()194 Object expected(); actual()195 Object actual(); 196 } 197 sleep(long ms)198 protected void sleep(long ms) { 199 try { 200 Thread.sleep(ms); 201 } catch (Exception e) { 202 Log.d(LOG_TAG, "InterruptedException"); 203 } 204 } 205 waitUntilConditionIsTrueOrTimeout( Condition condition, long timeout, String description)206 protected void waitUntilConditionIsTrueOrTimeout( 207 Condition condition, long timeout, String description) { 208 final long start = System.currentTimeMillis(); 209 while (!Objects.equals(condition.expected(), condition.actual()) 210 && System.currentTimeMillis() - start < timeout) { 211 sleep(50); 212 } 213 assertEquals(description, condition.expected(), condition.actual()); 214 } 215 beforeAllTestsBase()216 public static void beforeAllTestsBase() throws Exception { 217 sServiceConnector = new ImsServiceConnector(InstrumentationRegistry.getInstrumentation()); 218 // Remove all live ImsServices until after these tests are done 219 sServiceConnector.clearAllActiveImsServices(sTestSlot); 220 221 sReceiver = new CarrierConfigReceiver(sTestSub); 222 IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 223 // ACTION_CARRIER_CONFIG_CHANGED is sticky, so we will get a callback right away. 224 InstrumentationRegistry.getInstrumentation() 225 .getContext() 226 .registerReceiver(sReceiver, filter); 227 228 UiAutomation ui = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 229 try { 230 ui.adoptShellPermissionIdentity(); 231 // Get the default dialer and save it to restore after test ends. 232 sPreviousDefaultDialer = getDefaultDialer(InstrumentationRegistry.getInstrumentation()); 233 // Set dialer as "android.telephony.cts" 234 setDefaultDialer(InstrumentationRegistry.getInstrumentation(), PACKAGE_CTS_DIALER); 235 236 sSubscriptionManager = 237 InstrumentationRegistry.getInstrumentation() 238 .getContext() 239 .getSystemService(SubscriptionManager.class); 240 // Get the default Subscription values and save it to restore after test ends. 241 sPreviousOptInStatus = 242 sSubscriptionManager.getLongSubscriptionProperty( 243 sTestSub, SubscriptionManager.VOIMS_OPT_IN_STATUS, 0, getContext()); 244 sPreviousEn4GMode = 245 sSubscriptionManager.getLongSubscriptionProperty( 246 sTestSub, 247 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, 248 0, 249 getContext()); 250 // Set the new Sunbscription values 251 sSubscriptionManager.setSubscriptionProperty( 252 sTestSub, SubscriptionManager.VOIMS_OPT_IN_STATUS, String.valueOf(1)); 253 sSubscriptionManager.setSubscriptionProperty( 254 sTestSub, SubscriptionManager.ENHANCED_4G_MODE_ENABLED, String.valueOf(1)); 255 256 // Override the carrier configurartions 257 CarrierConfigManager configurationManager = 258 InstrumentationRegistry.getInstrumentation() 259 .getContext() 260 .getSystemService(CarrierConfigManager.class); 261 PersistableBundle bundle = new PersistableBundle(1); 262 bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL, true); 263 bundle.putBoolean(CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL, true); 264 bundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, false); 265 bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true); 266 bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false); 267 268 sReceiver.clearQueue(); 269 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 270 configurationManager, (m) -> m.overrideConfig(sTestSub, bundle)); 271 } finally { 272 ui.dropShellPermissionIdentity(); 273 } 274 sReceiver.waitForChanged(); 275 } 276 afterAllTestsBase()277 public static void afterAllTestsBase() throws Exception { 278 UiAutomation ui = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 279 try { 280 ui.adoptShellPermissionIdentity(); 281 // Set the default Sunbscription values. 282 sSubscriptionManager.setSubscriptionProperty( 283 sTestSub, 284 SubscriptionManager.VOIMS_OPT_IN_STATUS, 285 String.valueOf(sPreviousOptInStatus)); 286 sSubscriptionManager.setSubscriptionProperty( 287 sTestSub, 288 SubscriptionManager.ENHANCED_4G_MODE_ENABLED, 289 String.valueOf(sPreviousEn4GMode)); 290 // Set default dialer 291 setDefaultDialer(InstrumentationRegistry.getInstrumentation(), sPreviousDefaultDialer); 292 293 // Restore all ImsService configurations that existed before the test. 294 if (sServiceConnector != null && sIsBound) { 295 sServiceConnector.disconnectServices(); 296 sIsBound = false; 297 } 298 sServiceConnector = null; 299 overrideCarrierConfig(null); 300 301 if (sReceiver != null) { 302 InstrumentationRegistry.getInstrumentation() 303 .getContext() 304 .unregisterReceiver(sReceiver); 305 sReceiver = null; 306 } 307 } finally { 308 ui.dropShellPermissionIdentity(); 309 } 310 } 311 bindImsService()312 public void bindImsService() throws Exception { 313 bindImsService(ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 314 } 315 bindImsService(int radioTech)316 public void bindImsService(int radioTech) throws Exception { 317 MmTelCapabilities capabilities = 318 new MmTelCapabilities(MmTelCapabilities.CAPABILITY_TYPE_VOICE); 319 // Set Registered and VoLTE capable 320 bindImsServiceForCapabilities(radioTech, capabilities); 321 } 322 bindImsServiceForCapabilities(int radioTech, MmTelCapabilities capabilities)323 public void bindImsServiceForCapabilities(int radioTech, MmTelCapabilities capabilities) 324 throws Exception { 325 // Connect to the ImsService with the MmTel feature. 326 assertTrue( 327 sServiceConnector.connectCarrierImsService( 328 new ImsFeatureConfiguration.Builder() 329 .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL) 330 .addFeature(sTestSlot, ImsFeature.FEATURE_EMERGENCY_MMTEL) 331 .build())); 332 sIsBound = true; 333 // The MmTelFeature is created when the ImsService is bound. If it wasn't created, then the 334 // Framework did not call it. 335 sServiceConnector 336 .getCarrierService() 337 .waitForLatchCountdown(TestImsService.LATCH_CREATE_MMTEL); 338 assertNotNull( 339 "ImsService created, but ImsService#createMmTelFeature was not called!", 340 sServiceConnector.getCarrierService().getMmTelFeature()); 341 342 sServiceConnector 343 .getCarrierService() 344 .waitForLatchCountdown(TestImsService.LATCH_MMTEL_CAP_SET); 345 346 // Set Registered with given capabilities 347 sServiceConnector 348 .getCarrierService() 349 .getImsService() 350 .getRegistrationForSubscription(sTestSlot, sTestSub) 351 .onRegistered(radioTech); 352 sServiceConnector.getCarrierService().getMmTelFeature().setCapabilities(capabilities); 353 sServiceConnector 354 .getCarrierService() 355 .getMmTelFeature() 356 .notifyCapabilitiesStatusChanged(capabilities); 357 358 // Wait a second for the notifyCapabilitiesStatusChanged indication to be processed on the 359 // main telephony thread - currently no better way of knowing that telephony has processed 360 // this command. SmsManager#isImsSmsSupported() is @hide and must be updated to use new API. 361 Thread.sleep(3000); 362 } 363 waitForUnboundService()364 public void waitForUnboundService() { 365 waitUntilConditionIsTrueOrTimeout( 366 new Condition() { 367 @Override 368 public Object expected() { 369 return true; 370 } 371 372 @Override 373 public Object actual() { 374 InCallServiceStateValidator inCallService = mServiceCallBack.getService(); 375 return (inCallService.isServiceUnBound()) ? true : false; 376 } 377 }, 378 WAIT_FOR_SERVICE_TO_UNBOUND, 379 "Service Unbound"); 380 } 381 isCallActive(Call call, TestImsCallSessionImpl callsession)382 public void isCallActive(Call call, TestImsCallSessionImpl callsession) { 383 if (call.getDetails().getState() != Call.STATE_ACTIVE) { 384 assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_ACTIVE, WAIT_FOR_CALL_STATE)); 385 } 386 assertNotNull("Unable to get callSession, its null", callsession); 387 388 waitUntilConditionIsTrueOrTimeout( 389 new Condition() { 390 @Override 391 public Object expected() { 392 return true; 393 } 394 395 @Override 396 public Object actual() { 397 return (callsession.isInCall() 398 && call.getDetails().getState() == Call.STATE_ACTIVE) 399 ? true 400 : false; 401 } 402 }, 403 WAIT_FOR_CONDITION, 404 "Call Active"); 405 } 406 isCallDisconnected(Call call, TestImsCallSessionImpl callsession)407 public void isCallDisconnected(Call call, TestImsCallSessionImpl callsession) { 408 assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTED, WAIT_FOR_CALL_STATE)); 409 assertNotNull("Unable to get callSession, its null", callsession); 410 411 waitUntilConditionIsTrueOrTimeout( 412 new Condition() { 413 @Override 414 public Object expected() { 415 return true; 416 } 417 418 @Override 419 public Object actual() { 420 return (callsession.isInTerminated() 421 && call.getDetails().getState() == Call.STATE_DISCONNECTED) 422 ? true 423 : false; 424 } 425 }, WAIT_FOR_CONDITION, 426 "session " + callsession.getState() + ", call " 427 + call.getDetails().getState() + ", Call Disconnected"); 428 } 429 isCallHolding(Call call, TestImsCallSessionImpl callsession)430 public void isCallHolding(Call call, TestImsCallSessionImpl callsession) { 431 assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE)); 432 assertNotNull("Unable to get callSession, its null", callsession); 433 waitUntilConditionIsTrueOrTimeout( 434 new Condition() { 435 @Override 436 public Object expected() { 437 return true; 438 } 439 440 @Override 441 public Object actual() { 442 return (callsession.isSessionOnHold() 443 && call.getDetails().getState() == Call.STATE_HOLDING) ? true 444 : false; 445 } 446 }, WAIT_FOR_CONDITION, "Call Holding"); 447 } 448 setCallID(String callid)449 protected void setCallID(String callid) { 450 assertNotNull("Call Id is set to null", callid); 451 mCurrentCallId = callid; 452 } 453 addCall(Call call)454 public void addCall(Call call) { 455 String callid = getCallId(call); 456 setCallID(callid); 457 synchronized (mCalls) { 458 mCalls.put(callid, call); 459 } 460 } 461 getCallId(Call call)462 public String getCallId(Call call) { 463 String str = call.toString(); 464 String[] arrofstr = str.split(",", 3); 465 int index = arrofstr[0].indexOf(":"); 466 String callId = arrofstr[0].substring(index + 1); 467 return callId; 468 } 469 getCall(String callId)470 public Call getCall(String callId) { 471 synchronized (mCalls) { 472 if (mCalls.isEmpty()) { 473 return null; 474 } 475 476 for (Map.Entry<String, Call> entry : mCalls.entrySet()) { 477 if (entry.getKey().equals(callId)) { 478 Call call = entry.getValue(); 479 assertNotNull("Call is not added, its null", call); 480 return call; 481 } 482 } 483 } 484 return null; 485 } 486 removeCall(Call call)487 protected void removeCall(Call call) { 488 if (mCalls.isEmpty()) { 489 return; 490 } 491 492 String callid = getCallId(call); 493 Map.Entry<String, Call>[] entries = mCalls.entrySet().toArray(new Map.Entry[mCalls.size()]); 494 for (Map.Entry<String, Call> entry : entries) { 495 if (entry.getKey().equals(callid)) { 496 mCalls.remove(entry.getKey()); 497 mCurrentCallId = null; 498 } 499 } 500 } 501 502 protected class ServiceCallBack extends InCallServiceCallbacks { 503 504 @Override onCallAdded(Call call, int numCalls)505 public void onCallAdded(Call call, int numCalls) { 506 Log.i(LOG_TAG, "onCallAdded, Call: " + call + ", Num Calls: " + numCalls); 507 addCall(call); 508 countDownLatch(LATCH_IS_ON_CALL_ADDED); 509 if (call.getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE)) { 510 countDownLatch(LATCH_IS_ON_CONFERENCE_CALL_ADDED); 511 } 512 } 513 514 @Override onCallRemoved(Call call, int numCalls)515 public void onCallRemoved(Call call, int numCalls) { 516 Log.i(LOG_TAG, "onCallRemoved, Call: " + call + ", Num Calls: " + numCalls); 517 removeCall(call); 518 countDownLatch(LATCH_IS_ON_CALL_REMOVED); 519 } 520 521 @Override onCallStateChanged(Call call, int state)522 public void onCallStateChanged(Call call, int state) { 523 Log.i(LOG_TAG, "onCallStateChanged " + state + "Call: " + call); 524 525 switch (state) { 526 case Call.STATE_DIALING: 527 countDownLatch(LATCH_IS_CALL_DIALING); 528 break; 529 case Call.STATE_ACTIVE: 530 countDownLatch(LATCH_IS_CALL_ACTIVE); 531 break; 532 case Call.STATE_DISCONNECTING: 533 countDownLatch(LATCH_IS_CALL_DISCONNECTING); 534 break; 535 case Call.STATE_DISCONNECTED: 536 countDownLatch(LATCH_IS_CALL_DISCONNECTED); 537 break; 538 case Call.STATE_RINGING: 539 countDownLatch(LATCH_IS_CALL_RINGING); 540 break; 541 case Call.STATE_HOLDING: 542 countDownLatch(LATCH_IS_CALL_HOLDING); 543 break; 544 default: 545 break; 546 } 547 } 548 549 @Override onChildrenChanged(Call call, List<Call> children)550 public void onChildrenChanged(Call call, List<Call> children) { 551 if (call.getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE)) { 552 Log.i(LOG_TAG, "onChildrenChanged, Call: " + call + " , size " + children.size()); 553 mParticipantCount = children.size(); 554 countDownLatch(LATCH_IS_ON_CHILDREN_CHANGED); 555 } 556 } 557 558 @Override onConnectionEvent(Call call, String event, Bundle extras)559 public void onConnectionEvent(Call call, String event, Bundle extras) { 560 Log.i(LOG_TAG, "onConnectionEvent, Call: " + call + " , event " + event); 561 if (event.equals(android.telecom.Connection.EVENT_CALL_REMOTELY_HELD)) { 562 countDownLatch(LATCH_IS_ON_CALL_REMOTELY_HELD); 563 } else if (event.equals(android.telecom.Connection.EVENT_CALL_REMOTELY_UNHELD)) { 564 countDownLatch(LATCH_IS_ON_CALL_REMOTELY_UNHELD); 565 } else if (event.equals(android.telecom.Connection.EVENT_MERGE_START)) { 566 countDownLatch(LATCH_IS_ON_MERGE_START); 567 } else if (event.equals(android.telecom.Connection.EVENT_MERGE_COMPLETE)) { 568 countDownLatch(LATCH_IS_ON_MERGE_COMPLETE); 569 } 570 } 571 } 572 getContext()573 protected static Context getContext() { 574 return InstrumentationRegistry.getInstrumentation().getContext(); 575 } 576 577 /** Checks whether the system feature is supported. */ hasFeature(String feature)578 protected static boolean hasFeature(String feature) { 579 final PackageManager pm = getContext().getPackageManager(); 580 if (!pm.hasSystemFeature(feature)) { 581 Log.d(LOG_TAG, "Skipping test that requires " + feature); 582 return false; 583 } 584 return true; 585 } 586 setDefaultDialer(Instrumentation instrumentation, String packageName)587 protected static String setDefaultDialer(Instrumentation instrumentation, String packageName) 588 throws Exception { 589 String str = 590 TelephonyUtils.executeShellCommand( 591 instrumentation, COMMAND_SET_DEFAULT_DIALER + packageName); 592 return str; 593 } 594 getDefaultDialer(Instrumentation instrumentation)595 protected static String getDefaultDialer(Instrumentation instrumentation) throws Exception { 596 String str = 597 TelephonyUtils.executeShellCommand(instrumentation, COMMAND_GET_DEFAULT_DIALER); 598 return str; 599 } 600 overrideCarrierConfig(PersistableBundle bundle)601 protected static void overrideCarrierConfig(PersistableBundle bundle) throws Exception { 602 CarrierConfigManager carrierConfigManager = 603 InstrumentationRegistry.getInstrumentation() 604 .getContext() 605 .getSystemService(CarrierConfigManager.class); 606 sReceiver.clearQueue(); 607 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 608 carrierConfigManager, (m) -> m.overrideConfig(sTestSub, bundle)); 609 sReceiver.waitForChanged(); 610 } 611 setupForEmergencyCalling(String testNumber)612 protected void setupForEmergencyCalling(String testNumber) throws Exception { 613 enableCarrierUseImsFirstForEmergency(); 614 TestUtils.setSystemDialerOverride( 615 InstrumentationRegistry.getInstrumentation(), INCALL_COMPONENT); 616 TestUtils.addTestEmergencyNumber(InstrumentationRegistry.getInstrumentation(), testNumber); 617 mIsEmergencyCallingSetup = true; 618 } 619 tearDownEmergencyCalling()620 protected void tearDownEmergencyCalling() throws Exception { 621 if (!mIsEmergencyCallingSetup) return; 622 mIsEmergencyCallingSetup = false; 623 TestUtils.clearSystemDialerOverride(InstrumentationRegistry.getInstrumentation()); 624 TestUtils.clearTestEmergencyNumbers(InstrumentationRegistry.getInstrumentation()); 625 TelephonyUtils.endBlockSuppression(InstrumentationRegistry.getInstrumentation()); 626 } 627 enableCarrierUseImsFirstForEmergency()628 private static void enableCarrierUseImsFirstForEmergency() throws Exception { 629 PersistableBundle bundle = new PersistableBundle(); 630 bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true); 631 overrideCarrierConfig(bundle); 632 } 633 } 634