1 package android.telephony.cts; 2 3 import static org.junit.Assert.assertEquals; 4 import static org.junit.Assert.assertNotNull; 5 import static org.junit.Assert.assertNull; 6 import static org.junit.Assert.assertTrue; 7 import static org.junit.Assert.fail; 8 import static org.junit.Assume.assumeTrue; 9 10 import android.content.Context; 11 import android.content.pm.PackageManager; 12 import android.platform.test.annotations.AppModeNonSdkSandbox; 13 import android.platform.test.annotations.RequiresFlagsEnabled; 14 import android.platform.test.flag.junit.CheckFlagsRule; 15 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 16 import android.telephony.CallAttributes; 17 import android.telephony.CallState; 18 import android.telephony.PhoneStateListener; 19 import android.telephony.PreciseCallState; 20 import android.telephony.ServiceState; 21 import android.telephony.SignalStrength; 22 import android.telephony.SubscriptionManager; 23 import android.telephony.TelephonyCallback; 24 import android.telephony.TelephonyManager; 25 import android.telephony.TelephonyManager.CarrierPrivilegesCallback; 26 import android.telephony.TelephonyRegistryManager; 27 import android.telephony.emergency.EmergencyNumber; 28 import android.telephony.ims.ImsCallProfile; 29 import android.telephony.satellite.NtnSignalStrength; 30 import android.text.TextUtils; 31 import android.util.Log; 32 import android.util.Pair; 33 34 import androidx.annotation.NonNull; 35 import androidx.annotation.Nullable; 36 import androidx.test.InstrumentationRegistry; 37 38 import com.android.compatibility.common.util.ShellIdentityUtils; 39 import com.android.internal.telephony.flags.Flags; 40 41 import org.junit.After; 42 import org.junit.Before; 43 import org.junit.Rule; 44 import org.junit.Test; 45 46 import java.time.Duration; 47 import java.util.ArrayList; 48 import java.util.Arrays; 49 import java.util.HashSet; 50 import java.util.List; 51 import java.util.Set; 52 import java.util.concurrent.LinkedBlockingQueue; 53 import java.util.concurrent.Semaphore; 54 import java.util.concurrent.TimeUnit; 55 56 /** 57 * Test TelephonyRegistryManagerTest APIs. 58 */ 59 @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have access to TelephonyRegistryManager" 60 + "(telephony_registry)") 61 public class TelephonyRegistryManagerTest { 62 private TelephonyRegistryManager mTelephonyRegistryMgr; 63 private Boolean mWasLocationEnabled; 64 private static final long TIMEOUT_MILLIS = 1000; 65 private static final String TAG = "TelephonyRegistryManagerTest"; 66 67 @Rule 68 public final CheckFlagsRule mCheckFlagsRule = 69 DeviceFlagsValueProvider.createCheckFlagsRule(); 70 71 @Before setUp()72 public void setUp() throws Exception { 73 assumeTrue(InstrumentationRegistry.getContext().getPackageManager() 74 .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)); 75 76 mTelephonyRegistryMgr = (TelephonyRegistryManager) InstrumentationRegistry.getContext() 77 .getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 78 } 79 80 @After tearDown()81 public void tearDown() { 82 if (mWasLocationEnabled != null) { 83 TelephonyManagerTest.setLocationEnabled(mWasLocationEnabled); 84 mWasLocationEnabled = null; 85 } 86 } 87 88 /** 89 * expect security exception as there is no carrier privilege permission. 90 */ 91 @Test testNotifyCarrierNetworkChange()92 public void testNotifyCarrierNetworkChange() { 93 try { 94 mTelephonyRegistryMgr.notifyCarrierNetworkChange(true); 95 fail("Expected SecurityException for notifyCarrierNetworkChange"); 96 } catch (SecurityException ex) { 97 /* Expected */ 98 } 99 } 100 101 /** 102 * expect security exception as there is no carrier privilege permission. 103 */ 104 @Test testNotifyCarrierNetworkChangeWithSubscription()105 public void testNotifyCarrierNetworkChangeWithSubscription() { 106 try { 107 mTelephonyRegistryMgr.notifyCarrierNetworkChange( 108 SubscriptionManager.getDefaultSubscriptionId(), /*active=*/ true); 109 fail("Expected SecurityException for notifyCarrierNetworkChange with subscription"); 110 } catch (SecurityException expected) { 111 } 112 } 113 114 @Test testNotifyCallStateChangedForAllSubscriptions()115 public void testNotifyCallStateChangedForAllSubscriptions() throws Exception { 116 Context context = InstrumentationRegistry.getContext(); 117 118 LinkedBlockingQueue<Pair<Integer, String>> queue = new LinkedBlockingQueue<>(1); 119 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 120 @Override 121 public void onCallStateChanged(int state, String number) { 122 queue.offer(Pair.create(state, number)); 123 } 124 }; 125 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 126 tm.listen(psl, PhoneStateListener.LISTEN_CALL_STATE); 127 // clear the initial result from registering the listener. 128 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 129 130 String dummyNumber = "288124"; 131 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 132 (trm) -> trm.notifyCallStateChangedForAllSubscriptions( 133 TelephonyManager.CALL_STATE_IDLE, dummyNumber)); 134 135 Pair<Integer, String> result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 136 assertNotNull("Timed out waiting for phone state change", result); 137 assertEquals(TelephonyManager.CALL_STATE_IDLE, result.first.longValue()); 138 assertTrue(!TextUtils.isEmpty(result.second)); 139 } 140 141 @Test testNotifyCallStateChanged()142 public void testNotifyCallStateChanged() throws Exception { 143 Context context = InstrumentationRegistry.getContext(); 144 145 LinkedBlockingQueue<Pair<Integer, String>> queue = new LinkedBlockingQueue<>(1); 146 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 147 @Override 148 public void onCallStateChanged(int state, String number) { 149 queue.offer(Pair.create(state, number)); 150 } 151 }; 152 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 153 tm = tm.createForSubscriptionId(SubscriptionManager.getDefaultSubscriptionId()); 154 tm.listen(psl, PhoneStateListener.LISTEN_CALL_STATE); 155 // clear the initial result from registering the listener. 156 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 157 158 String dummyNumber = "288124"; 159 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 160 (trm) -> trm.notifyCallStateChanged( 161 SubscriptionManager.getSlotIndex( 162 SubscriptionManager.getDefaultSubscriptionId()), 163 SubscriptionManager.getDefaultSubscriptionId(), 164 TelephonyManager.CALL_STATE_IDLE, dummyNumber)); 165 166 Pair<Integer, String> result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 167 assertNotNull("Timed out waiting for phone state change", result); 168 assertEquals(TelephonyManager.CALL_STATE_IDLE, result.first.longValue()); 169 assertTrue(!TextUtils.isEmpty(result.second)); 170 } 171 172 @Test testNotifyServiceStateChanged()173 public void testNotifyServiceStateChanged() throws Exception { 174 TelephonyManagerTest.grantLocationPermissions(); 175 mWasLocationEnabled = TelephonyManagerTest.setLocationEnabled(true); 176 177 Context context = InstrumentationRegistry.getContext(); 178 179 LinkedBlockingQueue<ServiceState> queue = new LinkedBlockingQueue<>(1); 180 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 181 @Override 182 public void onServiceStateChanged(ServiceState ss) { 183 queue.offer(ss); 184 } 185 }; 186 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 187 tm.listen(psl, PhoneStateListener.LISTEN_SERVICE_STATE); 188 // clear the initial result from registering the listener. 189 ServiceState initialResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 190 Log.d(TAG, "initialResult: " + initialResult); 191 192 ServiceState dummyState = new ServiceState(); 193 dummyState.setCdmaSystemAndNetworkId(1234, 5678); 194 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 195 (trm) -> trm.notifyServiceStateChanged( 196 SubscriptionManager.getSlotIndex( 197 SubscriptionManager.getDefaultSubscriptionId()), 198 SubscriptionManager.getDefaultSubscriptionId(), 199 dummyState)); 200 201 ServiceState result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 202 assertNotNull("Timed out waiting for phone state change", result); 203 assertEquals(dummyState, result); 204 } 205 206 @Test testNotifySignalStrengthChanged()207 public void testNotifySignalStrengthChanged() throws Exception { 208 Context context = InstrumentationRegistry.getContext(); 209 210 LinkedBlockingQueue<SignalStrength> queue = new LinkedBlockingQueue<>(1); 211 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 212 @Override 213 public void onSignalStrengthsChanged(SignalStrength ss) { 214 queue.offer(ss); 215 } 216 }; 217 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 218 tm.listen(psl, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); 219 // clear the initial result from registering the listener. 220 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 221 222 SignalStrength testValue = new SignalStrength(); 223 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 224 (trm) -> trm.notifySignalStrengthChanged( 225 SubscriptionManager.getSlotIndex( 226 SubscriptionManager.getDefaultSubscriptionId()), 227 SubscriptionManager.getDefaultSubscriptionId(), 228 testValue)); 229 230 SignalStrength result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 231 assertNotNull("Timed out waiting for phone state change", result); 232 assertEquals(testValue, result); 233 } 234 235 @Test testNotifyMessageWaitingChanged()236 public void testNotifyMessageWaitingChanged() throws Exception { 237 Context context = InstrumentationRegistry.getContext(); 238 239 LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1); 240 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 241 @Override 242 public void onMessageWaitingIndicatorChanged(boolean msgWaitingInd) { 243 queue.offer(msgWaitingInd); 244 } 245 }; 246 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 247 tm.listen(psl, PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR); 248 // clear the initial result from registering the listener. 249 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 250 251 boolean testValue = true; 252 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 253 (trm) -> trm.notifyMessageWaitingChanged( 254 SubscriptionManager.getSlotIndex( 255 SubscriptionManager.getDefaultSubscriptionId()), 256 SubscriptionManager.getDefaultSubscriptionId(), 257 testValue)); 258 259 boolean result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 260 assertEquals(testValue, result); 261 } 262 263 @Test testNotifyCallForwardingChanged()264 public void testNotifyCallForwardingChanged() throws Exception { 265 Context context = InstrumentationRegistry.getContext(); 266 267 LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1); 268 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 269 @Override 270 public void onCallForwardingIndicatorChanged(boolean callForwarding) { 271 queue.offer(callForwarding); 272 } 273 }; 274 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 275 tm.listen(psl, PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR); 276 // clear the initial result from registering the listener. 277 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 278 279 boolean testValue = true; 280 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 281 (trm) -> trm.notifyCallForwardingChanged( 282 SubscriptionManager.getDefaultSubscriptionId(), 283 testValue)); 284 285 boolean result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 286 assertEquals(testValue, result); 287 } 288 289 @Test testNotifyDataActivityChangedWithSlot()290 public void testNotifyDataActivityChangedWithSlot() throws Exception { 291 Context context = InstrumentationRegistry.getContext(); 292 293 LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1); 294 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 295 @Override 296 public void onDataActivity(int activity) { 297 queue.offer(activity); 298 } 299 }; 300 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 301 tm.listen(psl, PhoneStateListener.LISTEN_DATA_ACTIVITY); 302 // clear the initial result from registering the listener. 303 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 304 305 int testValue = TelephonyManager.DATA_ACTIVITY_DORMANT; 306 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 307 (trm) -> trm.notifyDataActivityChanged( 308 SubscriptionManager.getSlotIndex( 309 SubscriptionManager.getDefaultSubscriptionId()), 310 SubscriptionManager.getDefaultSubscriptionId(), 311 testValue)); 312 313 int result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 314 assertEquals(testValue, result); 315 } 316 317 @Test testCarrierPrivilegesCallback()318 public void testCarrierPrivilegesCallback() throws Exception { 319 Context context = InstrumentationRegistry.getContext(); 320 321 LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue = 322 new LinkedBlockingQueue(2); 323 LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue = new LinkedBlockingQueue(2); 324 325 CarrierPrivilegesCallback cpc = new TestCarrierPrivilegesCallback(carrierPrivilegesQueue, 326 carrierServiceQueue); 327 CarrierPrivilegesCallback cpc2 = new TestCarrierPrivilegesCallback(carrierPrivilegesQueue, 328 carrierServiceQueue); 329 330 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 331 try { 332 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 333 telephonyManager, 334 tm -> tm.registerCarrierPrivilegesCallback(0, context.getMainExecutor(), cpc)); 335 // Clear the initial carrierPrivilegesResult from registering the listener. We can't 336 // necessarily guarantee this is empty so don't assert on it other than the fact we 337 // got _something_. We restore this at the end of the test. 338 Pair<Set<String>, Set<Integer>> initialCarrierPrivilegesState = 339 carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 340 assertNotNull(initialCarrierPrivilegesState); 341 Pair<String, Integer> initialCarrierServiceState = 342 carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 343 assertNotNull(initialCarrierServiceState); 344 345 // Update state 346 Set<String> privilegedPackageNames = 347 Set.of("com.carrier.package1", "com.carrier.package2"); 348 Set<Integer> privilegedUids = Set.of(12345, 54321); 349 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 350 mTelephonyRegistryMgr, 351 trm -> { 352 trm.notifyCarrierPrivilegesChanged( 353 0, privilegedPackageNames, privilegedUids); 354 trm.notifyCarrierServiceChanged(0, "com.carrier.package1", 12345); 355 }); 356 Pair<Set<String>, Set<Integer>> carrierPrivilegesResult = 357 carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 358 assertEquals(privilegedPackageNames, carrierPrivilegesResult.first); 359 assertEquals(privilegedUids, carrierPrivilegesResult.second); 360 361 Pair<String, Integer> carrierServiceResult = 362 carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 363 assertEquals("com.carrier.package1", carrierServiceResult.first); 364 assertEquals(12345, (long) carrierServiceResult.second); 365 366 // Update the state again, but only notify carrier privileges change this time 367 Set<String> newPrivilegedPackageNames = Set.of("com.carrier.package1", 368 "com.carrier.package3"); 369 Set<Integer> newPrivilegedUids = Set.of(12345, 678910); 370 371 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 372 mTelephonyRegistryMgr, 373 trm -> { 374 trm.notifyCarrierPrivilegesChanged( 375 0, newPrivilegedPackageNames, newPrivilegedUids); 376 }); 377 // The CarrierPrivileges pkgs and UIDs should be updated 378 carrierPrivilegesResult = 379 carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 380 assertEquals(newPrivilegedPackageNames, carrierPrivilegesResult.first); 381 assertEquals(newPrivilegedUids, carrierPrivilegesResult.second); 382 383 // And the CarrierService change notification should NOT be triggered 384 assertNull(carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); 385 386 // Registering cpc2 now immediately gets us the most recent state 387 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 388 telephonyManager, 389 tm -> tm.registerCarrierPrivilegesCallback(0, context.getMainExecutor(), cpc2)); 390 carrierPrivilegesResult = carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, 391 TimeUnit.MILLISECONDS); 392 assertEquals(newPrivilegedPackageNames, carrierPrivilegesResult.first); 393 assertEquals(newPrivilegedUids, carrierPrivilegesResult.second); 394 395 carrierServiceResult = carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 396 assertEquals("com.carrier.package1", carrierServiceResult.first); 397 assertEquals(12345, (long) carrierServiceResult.second); 398 399 // Removing cpc means it won't get the final callback when we restore the original state 400 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 401 telephonyManager, tm -> tm.unregisterCarrierPrivilegesCallback(cpc)); 402 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 403 mTelephonyRegistryMgr, 404 trm -> { 405 trm.notifyCarrierPrivilegesChanged( 406 0, initialCarrierPrivilegesState.first, 407 initialCarrierPrivilegesState.second); 408 trm.notifyCarrierServiceChanged(0, initialCarrierServiceState.first, 409 initialCarrierServiceState.second); 410 }); 411 412 carrierPrivilegesResult = carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, 413 TimeUnit.MILLISECONDS); 414 assertEquals(initialCarrierPrivilegesState.first, carrierPrivilegesResult.first); 415 assertEquals(initialCarrierPrivilegesState.second, carrierPrivilegesResult.second); 416 417 carrierServiceResult = carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 418 assertEquals(initialCarrierServiceState.first, carrierServiceResult.first); 419 assertEquals(initialCarrierServiceState.second, carrierServiceResult.second); 420 421 // No further callbacks received 422 assertNull(carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); 423 assertNull(carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); 424 } finally { 425 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 426 telephonyManager, 427 tm -> { 428 tm.unregisterCarrierPrivilegesCallback(cpc); // redundant, but still allowed 429 tm.unregisterCarrierPrivilegesCallback(cpc2); 430 }); 431 } 432 } 433 434 private class TestCarrierPrivilegesCallback implements CarrierPrivilegesCallback { 435 LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> mCarrierPrivilegesQueue; 436 LinkedBlockingQueue<Pair<String, Integer>> mCarrierServiceQueue; 437 TestCarrierPrivilegesCallback( LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue, LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue)438 TestCarrierPrivilegesCallback( 439 LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue, 440 LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue) { 441 mCarrierPrivilegesQueue = carrierPrivilegesQueue; 442 mCarrierServiceQueue = carrierServiceQueue; 443 } 444 445 @Override onCarrierPrivilegesChanged(@onNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids)446 public void onCarrierPrivilegesChanged(@NonNull Set<String> privilegedPackageNames, 447 @NonNull Set<Integer> privilegedUids) { 448 mCarrierPrivilegesQueue.offer(new Pair<>(privilegedPackageNames, privilegedUids)); 449 } 450 451 @Override onCarrierServiceChanged(@ullable String carrierServicePackageName, int carrierServiceUid)452 public void onCarrierServiceChanged(@Nullable String carrierServicePackageName, 453 int carrierServiceUid) { 454 mCarrierServiceQueue.offer(new Pair<>(carrierServicePackageName, carrierServiceUid)); 455 } 456 } 457 458 459 private static class SimultaneousCallingListener extends TelephonyCallback implements 460 TelephonyCallback.SimultaneousCellularCallingSupportListener { 461 462 private final LinkedBlockingQueue<Set<Integer>> mQueue; 463 SimultaneousCallingListener(LinkedBlockingQueue<Set<Integer>> queue)464 SimultaneousCallingListener(LinkedBlockingQueue<Set<Integer>> queue) { 465 mQueue = queue; 466 } 467 468 @Override onSimultaneousCellularCallingSubscriptionsChanged( @onNull Set<Integer> simultaneousCallingSubscriptionIds)469 public void onSimultaneousCellularCallingSubscriptionsChanged( 470 @NonNull Set<Integer> simultaneousCallingSubscriptionIds) { 471 mQueue.offer(simultaneousCallingSubscriptionIds); 472 } 473 } 474 475 @RequiresFlagsEnabled(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) 476 @Test testSimultaneousCellularCallingNotifications()477 public void testSimultaneousCellularCallingNotifications() throws Exception { 478 LinkedBlockingQueue<Set<Integer>> queue = new LinkedBlockingQueue<>(2); 479 SimultaneousCallingListener listener = new SimultaneousCallingListener(queue); 480 Context context = InstrumentationRegistry.getContext(); 481 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 482 483 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 484 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 485 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 486 // get the current value 487 Set<Integer> initialVal = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 488 Set<Integer> testVal = new HashSet<>(); 489 testVal.add(1000); 490 testVal.add(1100); 491 try { 492 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 493 (trm) -> trm.notifySimultaneousCellularCallingSubscriptionsChanged(testVal)); 494 Set<Integer> resultVal = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 495 assertEquals(testVal, resultVal); 496 } finally { 497 // set back the initial value so that we do not cause an invalid value to be returned. 498 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 499 (trm) -> trm.notifySimultaneousCellularCallingSubscriptionsChanged(initialVal)); 500 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 501 (tm) -> tm.unregisterTelephonyCallback(listener)); 502 } 503 } 504 505 private static class TestEmergencyCallbackModeListener extends TelephonyCallback implements 506 TelephonyCallback.EmergencyCallbackModeListener { 507 private final LinkedBlockingQueue<Pair<Integer, Long>> mStartedQueue; 508 private final LinkedBlockingQueue<Pair<Integer, Long>> mRestartedQueue; 509 private final LinkedBlockingQueue<Pair<Integer, Integer>> mStoppedQueue; 510 TestEmergencyCallbackModeListener( @ullable LinkedBlockingQueue<Pair<Integer, Long>> startedQueue, @Nullable LinkedBlockingQueue<Pair<Integer, Long>> restartedQueue, @Nullable LinkedBlockingQueue<Pair<Integer, Integer>> stoppedQueue)511 TestEmergencyCallbackModeListener( 512 @Nullable LinkedBlockingQueue<Pair<Integer, Long>> startedQueue, 513 @Nullable LinkedBlockingQueue<Pair<Integer, Long>> restartedQueue, 514 @Nullable LinkedBlockingQueue<Pair<Integer, Integer>> stoppedQueue) { 515 mStartedQueue = startedQueue; 516 mRestartedQueue = restartedQueue; 517 mStoppedQueue = stoppedQueue; 518 } 519 520 @Override onCallbackModeStarted(@elephonyManager.EmergencyCallbackModeType int type, @NonNull Duration timerDuration, int subId)521 public void onCallbackModeStarted(@TelephonyManager.EmergencyCallbackModeType int type, 522 @NonNull Duration timerDuration, int subId) { 523 if (mStartedQueue != null) { 524 mStartedQueue.offer(Pair.create(type, timerDuration.toMillis())); 525 } 526 } 527 528 @Override onCallbackModeRestarted(@elephonyManager.EmergencyCallbackModeType int type, @NonNull Duration timerDuration, int subId)529 public void onCallbackModeRestarted(@TelephonyManager.EmergencyCallbackModeType int type, 530 @NonNull Duration timerDuration, int subId) { 531 if (mRestartedQueue != null) { 532 mRestartedQueue.offer(Pair.create(type, timerDuration.toMillis())); 533 } 534 } 535 536 @Override onCallbackModeStopped(@elephonyManager.EmergencyCallbackModeType int type, @TelephonyManager.EmergencyCallbackModeStopReason int reason, int subId)537 public void onCallbackModeStopped(@TelephonyManager.EmergencyCallbackModeType int type, 538 @TelephonyManager.EmergencyCallbackModeStopReason int reason, int subId) { 539 if (mStoppedQueue != null) { 540 mStoppedQueue.offer(Pair.create(type, reason)); 541 } 542 } 543 } 544 545 @RequiresFlagsEnabled(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION) 546 @Test testNotifyCallbackModeStarted()547 public void testNotifyCallbackModeStarted() throws Exception { 548 LinkedBlockingQueue<Pair<Integer, Long>> queue = new LinkedBlockingQueue<>(2); 549 TestEmergencyCallbackModeListener listener = new TestEmergencyCallbackModeListener( 550 queue, null, null); 551 552 Context context = InstrumentationRegistry.getContext(); 553 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 554 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 555 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 556 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 557 558 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 559 int phoneId = SubscriptionManager.getSlotIndex(defaultSubId); 560 Pair<Integer, Long> testVal = Pair.create( 561 TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, 1000L); 562 563 // clear the initial result from registering the listener. 564 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 565 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 566 567 try { 568 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 569 (trm) -> trm.notifyCallbackModeStarted( 570 phoneId, defaultSubId, testVal.first, testVal.second)); 571 Pair<Integer, Long> resultVal = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 572 assertNotNull("No callback mode notification received", resultVal); 573 574 assertEquals(testVal.first, resultVal.first); 575 assertEquals(testVal.second, resultVal.second); 576 } finally { 577 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 578 (trm) -> trm.notifyCallbackModeStopped(phoneId, defaultSubId, 579 TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, 580 TelephonyManager.STOP_REASON_UNKNOWN)); 581 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 582 (tm) -> tm.unregisterTelephonyCallback(listener)); 583 } 584 } 585 586 @RequiresFlagsEnabled(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION) 587 @Test testNotifyCallbackModeRestarted()588 public void testNotifyCallbackModeRestarted() throws Exception { 589 LinkedBlockingQueue<Pair<Integer, Long>> queue = new LinkedBlockingQueue<>(2); 590 TestEmergencyCallbackModeListener listener = new TestEmergencyCallbackModeListener( 591 null, queue, null); 592 593 Context context = InstrumentationRegistry.getContext(); 594 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 595 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 596 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 597 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 598 599 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 600 int phoneId = SubscriptionManager.getSlotIndex(defaultSubId); 601 Pair<Integer, Long> testVal = Pair.create( 602 TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS, 1000L); 603 604 // clear the initial result from registering the listener. 605 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 606 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 607 608 try { 609 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 610 (trm) -> trm.notifyCallbackModeRestarted( 611 phoneId, defaultSubId, testVal.first, testVal.second)); 612 Pair<Integer, Long> resultVal = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 613 assertNotNull("No callback mode notification received", resultVal); 614 615 assertEquals(testVal.first, resultVal.first); 616 assertEquals(testVal.second, resultVal.second); 617 } finally { 618 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 619 (trm) -> trm.notifyCallbackModeStopped(phoneId, defaultSubId, 620 TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS, 621 TelephonyManager.STOP_REASON_UNKNOWN)); 622 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 623 (tm) -> tm.unregisterTelephonyCallback(listener)); 624 } 625 } 626 627 @RequiresFlagsEnabled(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION) 628 @Test testNotifyCallbackModeStopped()629 public void testNotifyCallbackModeStopped() throws Exception { 630 LinkedBlockingQueue<Pair<Integer, Integer>> queue = new LinkedBlockingQueue<>(2); 631 TestEmergencyCallbackModeListener listener = new TestEmergencyCallbackModeListener( 632 null, null, queue); 633 634 Context context = InstrumentationRegistry.getContext(); 635 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 636 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 637 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 638 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 639 640 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 641 int phoneId = SubscriptionManager.getSlotIndex(defaultSubId); 642 Pair<Integer, Integer> testVal = Pair.create( 643 TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, 644 TelephonyManager.STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED); 645 646 // clear the initial result from registering the listener. 647 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 648 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 649 650 try { 651 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 652 (trm) -> trm.notifyCallbackModeStopped( 653 phoneId, defaultSubId, testVal.first, testVal.second)); 654 Pair<Integer, Integer> resultVal = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 655 assertNotNull("No callback mode notification received", resultVal); 656 657 assertEquals(testVal.first, resultVal.first); 658 assertEquals(testVal.second, resultVal.second); 659 } finally { 660 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 661 (trm) -> trm.notifyCallbackModeStopped(phoneId, defaultSubId, 662 TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, 663 TelephonyManager.STOP_REASON_UNKNOWN)); 664 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 665 (tm) -> tm.unregisterTelephonyCallback(listener)); 666 } 667 } 668 669 @Test testNotifyPreciseCallStateWithImsCall()670 public void testNotifyPreciseCallStateWithImsCall() throws Exception { 671 Context context = InstrumentationRegistry.getContext(); 672 673 LinkedBlockingQueue<List<CallState>> queue = new LinkedBlockingQueue<>(1); 674 TestTelephonyCallback testCb = new TestTelephonyCallback(queue); 675 676 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 677 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 678 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); 679 // clear the initial result from registering the listener. 680 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 681 682 int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_INCOMING, 683 PreciseCallState.PRECISE_CALL_STATE_ACTIVE, 684 PreciseCallState.PRECISE_CALL_STATE_IDLE}; 685 String[] dummyImsCallIds = {"1", "0", "-1"}; 686 int[] dummyImsServiceTypes = {ImsCallProfile.SERVICE_TYPE_NORMAL, 687 ImsCallProfile.SERVICE_TYPE_NORMAL, 688 ImsCallProfile.SERVICE_TYPE_NONE}; 689 int[] dummyImsCallTypes = {ImsCallProfile.CALL_TYPE_VT, 690 ImsCallProfile.CALL_TYPE_VOICE, 691 ImsCallProfile.CALL_TYPE_NONE}; 692 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 693 (trm) -> trm.notifyPreciseCallState( 694 SubscriptionManager.getSlotIndex( 695 SubscriptionManager.getDefaultSubscriptionId()), 696 SubscriptionManager.getDefaultSubscriptionId(), 697 dummyCallStates, dummyImsCallIds, dummyImsServiceTypes, dummyImsCallTypes)); 698 699 List<CallState> testCallStatesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 700 assertNotNull("Timed out waiting for phone state change", testCallStatesResult); 701 assertEquals(2, testCallStatesResult.size()); 702 assertEquals(PreciseCallState.PRECISE_CALL_STATE_ACTIVE, 703 testCallStatesResult.get(0).getCallState()); 704 assertEquals(PreciseCallState.PRECISE_CALL_STATE_INCOMING, 705 testCallStatesResult.get(1).getCallState()); 706 assertEquals("0", 707 testCallStatesResult.get(0).getImsCallSessionId()); 708 assertEquals("1", 709 testCallStatesResult.get(1).getImsCallSessionId()); 710 assertEquals(ImsCallProfile.CALL_TYPE_VOICE, 711 testCallStatesResult.get(0).getImsCallType()); 712 assertEquals(ImsCallProfile.CALL_TYPE_VT, 713 testCallStatesResult.get(1).getImsCallType()); 714 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 715 (tm) -> tm.unregisterTelephonyCallback(testCb)); 716 } 717 718 @Test testNotifyPreciseCallStateWithCsCall()719 public void testNotifyPreciseCallStateWithCsCall() throws Exception { 720 Context context = InstrumentationRegistry.getContext(); 721 722 LinkedBlockingQueue<List<CallState>> queue = new LinkedBlockingQueue<>(1); 723 TestTelephonyCallback testCb = new TestTelephonyCallback(queue); 724 725 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 726 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 727 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); 728 // clear the initial result from registering the listener. 729 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 730 731 int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_INCOMING, 732 PreciseCallState.PRECISE_CALL_STATE_ACTIVE, 733 PreciseCallState.PRECISE_CALL_STATE_IDLE}; 734 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 735 (trm) -> trm.notifyPreciseCallState( 736 SubscriptionManager.getSlotIndex( 737 SubscriptionManager.getDefaultSubscriptionId()), 738 SubscriptionManager.getDefaultSubscriptionId(), 739 dummyCallStates, null, null, null)); 740 741 List<CallState> testCallStatesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 742 assertNotNull("Timed out waiting for phone state change", testCallStatesResult); 743 assertEquals(2, testCallStatesResult.size()); 744 assertEquals(PreciseCallState.PRECISE_CALL_STATE_ACTIVE, 745 testCallStatesResult.get(0).getCallState()); 746 assertEquals(PreciseCallState.PRECISE_CALL_STATE_INCOMING, 747 testCallStatesResult.get(1).getCallState()); 748 assertNull(testCallStatesResult.get(0).getImsCallSessionId()); 749 assertNull(testCallStatesResult.get(1).getImsCallSessionId()); 750 assertEquals(ImsCallProfile.SERVICE_TYPE_NONE, 751 testCallStatesResult.get(0).getImsCallServiceType()); 752 assertEquals(ImsCallProfile.SERVICE_TYPE_NONE, 753 testCallStatesResult.get(1).getImsCallServiceType()); 754 assertEquals(ImsCallProfile.CALL_TYPE_NONE, 755 testCallStatesResult.get(0).getImsCallType()); 756 assertEquals(ImsCallProfile.CALL_TYPE_NONE, 757 testCallStatesResult.get(1).getImsCallType()); 758 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 759 (tm) -> tm.unregisterTelephonyCallback(testCb)); 760 } 761 762 @Test testNotifyPreciseCallStateLegacyCallback()763 public void testNotifyPreciseCallStateLegacyCallback() throws Exception { 764 Context context = InstrumentationRegistry.getContext(); 765 766 LinkedBlockingQueue<CallAttributes> queue = new LinkedBlockingQueue<>(1); 767 TestTelephonyCallbackLegacy testCb = new TestTelephonyCallbackLegacy(queue); 768 769 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 770 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 771 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); 772 // clear the initial result from registering the listener. 773 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 774 775 int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_INCOMING, 776 PreciseCallState.PRECISE_CALL_STATE_HOLDING, 777 PreciseCallState.PRECISE_CALL_STATE_IDLE}; 778 String[] dummyImsCallIds = {"1", "0", "-1"}; 779 int[] dummyImsServiceTypes = {ImsCallProfile.SERVICE_TYPE_NORMAL, 780 ImsCallProfile.SERVICE_TYPE_NORMAL, 781 ImsCallProfile.SERVICE_TYPE_NONE}; 782 int[] dummyImsCallTypes = {ImsCallProfile.CALL_TYPE_VT, 783 ImsCallProfile.CALL_TYPE_VOICE, 784 ImsCallProfile.CALL_TYPE_NONE}; 785 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 786 (trm) -> trm.notifyPreciseCallState( 787 SubscriptionManager.getSlotIndex( 788 SubscriptionManager.getDefaultSubscriptionId()), 789 SubscriptionManager.getDefaultSubscriptionId(), 790 dummyCallStates, dummyImsCallIds, dummyImsServiceTypes, dummyImsCallTypes)); 791 792 CallAttributes testCallAttributesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 793 assertNotNull("Timed out waiting for phone state change", testCallAttributesResult); 794 795 assertEquals(PreciseCallState.PRECISE_CALL_STATE_HOLDING, 796 testCallAttributesResult.getPreciseCallState().getForegroundCallState()); 797 assertEquals(PreciseCallState.PRECISE_CALL_STATE_IDLE, 798 testCallAttributesResult.getPreciseCallState().getBackgroundCallState()); 799 assertEquals(PreciseCallState.PRECISE_CALL_STATE_INCOMING, 800 testCallAttributesResult.getPreciseCallState().getRingingCallState()); 801 802 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 803 (tm) -> tm.unregisterTelephonyCallback(testCb)); 804 } 805 806 @Test testNotifyPreciseCallStatePhoneStateListener()807 public void testNotifyPreciseCallStatePhoneStateListener() throws Exception { 808 Context context = InstrumentationRegistry.getContext(); 809 810 LinkedBlockingQueue<CallAttributes> queue = new LinkedBlockingQueue<>(1); 811 PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { 812 @Override 813 public void onCallAttributesChanged(CallAttributes ca) { 814 queue.offer(ca); 815 } 816 }; 817 818 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 819 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 820 (tm) -> tm.listen(psl, PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)); 821 // clear the initial result from registering the listener. 822 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 823 824 int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_IDLE, 825 PreciseCallState.PRECISE_CALL_STATE_ACTIVE, 826 PreciseCallState.PRECISE_CALL_STATE_HOLDING}; 827 String[] dummyImsCallIds = {"-1", "0", "1"}; 828 int[] dummyImsServiceTypes = {ImsCallProfile.SERVICE_TYPE_NONE, 829 ImsCallProfile.SERVICE_TYPE_NORMAL, 830 ImsCallProfile.SERVICE_TYPE_NORMAL}; 831 int[] dummyImsCallTypes = {ImsCallProfile.CALL_TYPE_NONE, 832 ImsCallProfile.CALL_TYPE_VOICE, 833 ImsCallProfile.CALL_TYPE_VT}; 834 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 835 (trm) -> trm.notifyPreciseCallState( 836 SubscriptionManager.getSlotIndex( 837 SubscriptionManager.getDefaultSubscriptionId()), 838 SubscriptionManager.getDefaultSubscriptionId(), 839 dummyCallStates, dummyImsCallIds, dummyImsServiceTypes, dummyImsCallTypes)); 840 841 CallAttributes testCallAttributesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 842 assertNotNull("Timed out waiting for phone state change", testCallAttributesResult); 843 844 assertEquals(PreciseCallState.PRECISE_CALL_STATE_ACTIVE, 845 testCallAttributesResult.getPreciseCallState().getForegroundCallState()); 846 assertEquals(PreciseCallState.PRECISE_CALL_STATE_HOLDING, 847 testCallAttributesResult.getPreciseCallState().getBackgroundCallState()); 848 assertEquals(PreciseCallState.PRECISE_CALL_STATE_IDLE, 849 testCallAttributesResult.getPreciseCallState().getRingingCallState()); 850 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 851 (tm) -> tm.listen(psl, PhoneStateListener.LISTEN_NONE)); 852 } 853 854 @Test testNotifyOutgoingEmergencyCall()855 public void testNotifyOutgoingEmergencyCall() throws Exception { 856 Context context = InstrumentationRegistry.getContext(); 857 String testEmergencyNumber = "9998887776655443210"; 858 EmergencyNumber emergencyNumber = new EmergencyNumber( 859 testEmergencyNumber, 860 "us", 861 "30", 862 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED, 863 new ArrayList<>(), 864 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING, 865 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL); 866 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 867 int phoneId = SubscriptionManager.getSlotIndex(defaultSubId); 868 869 LinkedBlockingQueue<List<CallState>> queue = new LinkedBlockingQueue<>(1); 870 TestTelephonyCallback testCb = new TestTelephonyCallback(queue); 871 872 // Register telephony callback. 873 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 874 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 875 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); 876 // clear the initial result from registering the listener. 877 queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 878 879 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 880 (trm) -> trm.notifyOutgoingEmergencyCall(phoneId, defaultSubId, emergencyNumber)); 881 assertTrue(testCb.mCallbackSemaphore.tryAcquire(15, TimeUnit.SECONDS)); 882 assertEquals(emergencyNumber, testCb.mLastOutgoingEmergencyNumber); 883 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 884 (tm) -> tm.unregisterTelephonyCallback(testCb)); 885 } 886 887 private static class TestTelephonyCallback extends TelephonyCallback 888 implements TelephonyCallback.CallAttributesListener, 889 TelephonyCallback.OutgoingEmergencyCallListener { 890 public Semaphore mCallbackSemaphore = new Semaphore(0); 891 LinkedBlockingQueue<List<CallState>> mTestCallStatesQueue; 892 private EmergencyNumber mLastOutgoingEmergencyNumber; 893 TestTelephonyCallback(LinkedBlockingQueue<List<CallState>> queue)894 TestTelephonyCallback(LinkedBlockingQueue<List<CallState>> queue) { 895 mTestCallStatesQueue = queue; 896 } 897 @Override onCallStatesChanged(@onNull List<CallState> callStateList)898 public void onCallStatesChanged(@NonNull List<CallState> callStateList) { 899 mTestCallStatesQueue.offer(callStateList); 900 } 901 902 @Override onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, int subscriptionId)903 public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, 904 int subscriptionId) { 905 Log.i(TAG, "onOutgoingEmergencyCall: telephony callback"); 906 mLastOutgoingEmergencyNumber = placedEmergencyNumber; 907 mCallbackSemaphore.release(); 908 } 909 } 910 911 private class TestTelephonyCallbackLegacy extends TelephonyCallback 912 implements TelephonyCallback.CallAttributesListener { 913 LinkedBlockingQueue<CallAttributes> mTestCallAttributes; TestTelephonyCallbackLegacy(LinkedBlockingQueue<CallAttributes> queue)914 TestTelephonyCallbackLegacy(LinkedBlockingQueue<CallAttributes> queue) { 915 mTestCallAttributes = queue; 916 } 917 @Override onCallAttributesChanged(@onNull CallAttributes callAttributes)918 public void onCallAttributesChanged(@NonNull CallAttributes callAttributes) { 919 mTestCallAttributes.offer(callAttributes); 920 } 921 } 922 923 private static class CarrierRoamingNtnListener extends TelephonyCallback 924 implements TelephonyCallback.CarrierRoamingNtnListener { 925 926 public LinkedBlockingQueue<Object> mModeQueue; 927 public LinkedBlockingQueue<Object> mEligibilityQueue; 928 public LinkedBlockingQueue<Object> mAvailableServicesQueue; 929 public LinkedBlockingQueue<Object> mSignalStrengthQueue; 930 CarrierRoamingNtnListener()931 CarrierRoamingNtnListener() { 932 mModeQueue = new LinkedBlockingQueue<>(1); 933 mEligibilityQueue = new LinkedBlockingQueue<>(1); 934 mAvailableServicesQueue = new LinkedBlockingQueue<>(1); 935 mSignalStrengthQueue = new LinkedBlockingQueue<>(1); 936 } 937 938 @Override onCarrierRoamingNtnModeChanged(boolean active)939 public void onCarrierRoamingNtnModeChanged(boolean active) { 940 mModeQueue.offer(active); 941 } 942 943 @Override onCarrierRoamingNtnEligibleStateChanged(boolean eligible)944 public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) { 945 mEligibilityQueue.offer(eligible); 946 } 947 948 @Override onCarrierRoamingNtnAvailableServicesChanged(int[] services)949 public void onCarrierRoamingNtnAvailableServicesChanged(int[] services) { 950 mAvailableServicesQueue.offer(services); 951 } 952 953 @Override onCarrierRoamingNtnSignalStrengthChanged( @onNull NtnSignalStrength ntnSignalStrength)954 public void onCarrierRoamingNtnSignalStrengthChanged( 955 @NonNull NtnSignalStrength ntnSignalStrength) { 956 mSignalStrengthQueue.offer(ntnSignalStrength); 957 } 958 } 959 960 @Test testCarrierRoamingNtnModeChanged()961 public void testCarrierRoamingNtnModeChanged() throws Exception { 962 CarrierRoamingNtnListener listener = new CarrierRoamingNtnListener(); 963 964 Context context = InstrumentationRegistry.getContext(); 965 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 966 telephonyManager = telephonyManager.createForSubscriptionId( 967 SubscriptionManager.getDefaultSubscriptionId()); 968 969 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 970 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 971 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 972 973 // Get the current value 974 Object objectInitialValue = listener.mModeQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 975 976 if (objectInitialValue instanceof Boolean) { 977 boolean initialValue = (Boolean) objectInitialValue; 978 try { 979 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 980 (trm) -> trm.notifyCarrierRoamingNtnModeChanged( 981 SubscriptionManager.getDefaultSubscriptionId(), true)); 982 Object resultVal = listener.mModeQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 983 assertTrue((boolean) resultVal); 984 } finally { 985 // set back the initial value so that we do not cause an invalid value to be 986 // returned. 987 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 988 (trm) -> trm.notifyCarrierRoamingNtnModeChanged( 989 SubscriptionManager.getDefaultSubscriptionId(), initialValue)); 990 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 991 (tm) -> tm.unregisterTelephonyCallback(listener)); 992 } 993 } 994 } 995 996 @Test 997 @RequiresFlagsEnabled(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) testCarrierRoamingNtnEligible()998 public void testCarrierRoamingNtnEligible() throws Exception { 999 CarrierRoamingNtnListener listener = new CarrierRoamingNtnListener(); 1000 1001 Context context = InstrumentationRegistry.getContext(); 1002 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 1003 telephonyManager = telephonyManager.createForSubscriptionId( 1004 SubscriptionManager.getDefaultSubscriptionId()); 1005 1006 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 1007 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 1008 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 1009 1010 // Get the current value 1011 Object objectInitialValue = listener.mEligibilityQueue.poll( 1012 TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 1013 1014 if (objectInitialValue instanceof Boolean) { 1015 boolean initialValue = (Boolean) objectInitialValue; 1016 try { 1017 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 1018 (trm) -> trm.notifyCarrierRoamingNtnEligibleStateChanged( 1019 SubscriptionManager.getDefaultSubscriptionId(), true)); 1020 Object resultVal = listener.mEligibilityQueue.poll( 1021 TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 1022 assertTrue((boolean) resultVal); 1023 } finally { 1024 // set back the initial value so that we do not cause an invalid value to be 1025 // returned. 1026 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 1027 (trm) -> trm.notifyCarrierRoamingNtnEligibleStateChanged( 1028 SubscriptionManager.getDefaultSubscriptionId(), initialValue)); 1029 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 1030 (tm) -> tm.unregisterTelephonyCallback(listener)); 1031 } 1032 } 1033 } 1034 1035 @Test 1036 @RequiresFlagsEnabled(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) testCarrierRoamingNtnAvailableServices()1037 public void testCarrierRoamingNtnAvailableServices() throws Exception { 1038 CarrierRoamingNtnListener listener = new CarrierRoamingNtnListener(); 1039 1040 Context context = InstrumentationRegistry.getContext(); 1041 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 1042 telephonyManager = telephonyManager.createForSubscriptionId( 1043 SubscriptionManager.getDefaultSubscriptionId()); 1044 1045 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 1046 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 1047 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 1048 1049 // Get the current value 1050 Object objectInitialValue = listener.mAvailableServicesQueue.poll( 1051 TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 1052 1053 if (objectInitialValue instanceof int[]) { 1054 int[] initialValue = (int[]) objectInitialValue; 1055 int[] testServices = {3, 6}; 1056 try { 1057 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 1058 (trm) -> trm.notifyCarrierRoamingNtnAvailableServicesChanged( 1059 SubscriptionManager.getDefaultSubscriptionId(), testServices)); 1060 Object resultVal = listener.mAvailableServicesQueue.poll( 1061 TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 1062 assertTrue(Arrays.equals(testServices, (int[]) resultVal)); 1063 } finally { 1064 // set back the initial value so that we do not cause an invalid value to be 1065 // returned. 1066 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 1067 (trm) -> trm.notifyCarrierRoamingNtnAvailableServicesChanged( 1068 SubscriptionManager.getDefaultSubscriptionId(), initialValue)); 1069 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 1070 (tm) -> tm.unregisterTelephonyCallback(listener)); 1071 } 1072 } 1073 } 1074 1075 @Test 1076 @RequiresFlagsEnabled(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) testCarrierRoamingNtnSignalStrengthChanged()1077 public void testCarrierRoamingNtnSignalStrengthChanged() throws Exception { 1078 CarrierRoamingNtnListener listener = new CarrierRoamingNtnListener(); 1079 1080 Context context = InstrumentationRegistry.getContext(); 1081 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 1082 telephonyManager = telephonyManager.createForSubscriptionId( 1083 SubscriptionManager.getDefaultSubscriptionId()); 1084 1085 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 1086 (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), listener), 1087 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 1088 1089 // Get the current value 1090 Object objectInitialValue = listener.mSignalStrengthQueue.poll( 1091 TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 1092 1093 if (objectInitialValue instanceof NtnSignalStrength) { 1094 NtnSignalStrength initialValue = (NtnSignalStrength) objectInitialValue; 1095 try { 1096 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 1097 (trm) -> trm.notifyCarrierRoamingNtnSignalStrengthChanged( 1098 SubscriptionManager.getDefaultSubscriptionId(), 1099 new NtnSignalStrength(NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD))); 1100 NtnSignalStrength resultVal = (NtnSignalStrength) listener.mSignalStrengthQueue 1101 .poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 1102 assertEquals(resultVal.getLevel(), NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD); 1103 } finally { 1104 // set back the initial value so that we do not cause an invalid value to be 1105 // returned. 1106 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, 1107 (trm) -> trm.notifyCarrierRoamingNtnSignalStrengthChanged( 1108 SubscriptionManager.getDefaultSubscriptionId(), initialValue)); 1109 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, 1110 (tm) -> tm.unregisterTelephonyCallback(listener)); 1111 } 1112 } 1113 } 1114 } 1115