• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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