| package android.telephony.cts; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.junit.Assume.assumeTrue; |
| |
| import android.content.Context; |
| import android.content.pm.PackageManager; |
| import android.platform.test.annotations.RequiresFlagsDisabled; |
| import android.platform.test.annotations.RequiresFlagsEnabled; |
| import android.platform.test.flag.junit.CheckFlagsRule; |
| import android.platform.test.flag.junit.DeviceFlagsValueProvider; |
| import android.telephony.CallAttributes; |
| import android.telephony.CallState; |
| import android.telephony.PhoneStateListener; |
| import android.telephony.PreciseCallState; |
| import android.telephony.ServiceState; |
| import android.telephony.SignalStrength; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.TelephonyCallback; |
| import android.telephony.TelephonyManager; |
| import android.telephony.TelephonyManager.CarrierPrivilegesCallback; |
| import android.telephony.TelephonyRegistryManager; |
| import android.telephony.ims.ImsCallProfile; |
| import android.text.TextUtils; |
| import android.util.Pair; |
| |
| import androidx.annotation.NonNull; |
| import androidx.annotation.Nullable; |
| import androidx.test.InstrumentationRegistry; |
| |
| import com.android.compatibility.common.util.ShellIdentityUtils; |
| import com.android.internal.telephony.flags.Flags; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.LinkedBlockingQueue; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * Test TelephonyRegistryManagerTest APIs. |
| */ |
| public class TelephonyRegistryManagerTest { |
| private TelephonyRegistryManager mTelephonyRegistryMgr; |
| private static final long TIMEOUT_MILLIS = 1000; |
| |
| @Rule |
| public final CheckFlagsRule mCheckFlagsRule = |
| DeviceFlagsValueProvider.createCheckFlagsRule(); |
| |
| @Before |
| public void setUp() throws Exception { |
| assumeTrue(InstrumentationRegistry.getContext().getPackageManager() |
| .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)); |
| |
| mTelephonyRegistryMgr = (TelephonyRegistryManager) InstrumentationRegistry.getContext() |
| .getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); |
| } |
| |
| /** |
| * expect security exception as there is no carrier privilege permission. |
| */ |
| @Test |
| public void testNotifyCarrierNetworkChange() { |
| try { |
| mTelephonyRegistryMgr.notifyCarrierNetworkChange(true); |
| fail("Expected SecurityException for notifyCarrierNetworkChange"); |
| } catch (SecurityException ex) { |
| /* Expected */ |
| } |
| } |
| |
| /** |
| * expect security exception as there is no carrier privilege permission. |
| */ |
| @Test |
| public void testNotifyCarrierNetworkChangeWithSubscription() { |
| try { |
| mTelephonyRegistryMgr.notifyCarrierNetworkChange( |
| SubscriptionManager.getDefaultSubscriptionId(), /*active=*/ true); |
| fail("Expected SecurityException for notifyCarrierNetworkChange with subscription"); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @Test |
| public void testNotifyCallStateChangedForAllSubscriptions() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Pair<Integer, String>> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onCallStateChanged(int state, String number) { |
| queue.offer(Pair.create(state, number)); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_CALL_STATE); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| String dummyNumber = "288124"; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyCallStateChangedForAllSubscriptions( |
| TelephonyManager.CALL_STATE_IDLE, dummyNumber)); |
| |
| Pair<Integer, String> result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", result); |
| assertEquals(TelephonyManager.CALL_STATE_IDLE, result.first.longValue()); |
| assertTrue(!TextUtils.isEmpty(result.second)); |
| } |
| |
| @Test |
| public void testNotifyCallStateChanged() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Pair<Integer, String>> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onCallStateChanged(int state, String number) { |
| queue.offer(Pair.create(state, number)); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm = tm.createForSubscriptionId(SubscriptionManager.getDefaultSubscriptionId()); |
| tm.listen(psl, PhoneStateListener.LISTEN_CALL_STATE); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| String dummyNumber = "288124"; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyCallStateChanged( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| TelephonyManager.CALL_STATE_IDLE, dummyNumber)); |
| |
| Pair<Integer, String> result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", result); |
| assertEquals(TelephonyManager.CALL_STATE_IDLE, result.first.longValue()); |
| assertTrue(!TextUtils.isEmpty(result.second)); |
| } |
| |
| @Test |
| public void testNotifyServiceStateChanged() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<ServiceState> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onServiceStateChanged(ServiceState ss) { |
| queue.offer(ss); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_SERVICE_STATE); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| ServiceState dummyState = new ServiceState(); |
| dummyState.setCdmaSystemAndNetworkId(1234, 5678); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyServiceStateChanged( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| dummyState)); |
| |
| ServiceState result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", result); |
| assertEquals(dummyState, result); |
| } |
| |
| @Test |
| public void testNotifySignalStrengthChanged() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<SignalStrength> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onSignalStrengthsChanged(SignalStrength ss) { |
| queue.offer(ss); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| SignalStrength testValue = new SignalStrength(); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifySignalStrengthChanged( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| testValue)); |
| |
| SignalStrength result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", result); |
| assertEquals(testValue, result); |
| } |
| |
| @Test |
| public void testNotifyMessageWaitingChanged() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onMessageWaitingIndicatorChanged(boolean msgWaitingInd) { |
| queue.offer(msgWaitingInd); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| boolean testValue = true; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyMessageWaitingChanged( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| testValue)); |
| |
| boolean result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(testValue, result); |
| } |
| |
| @Test |
| public void testNotifyCallForwardingChanged() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onCallForwardingIndicatorChanged(boolean callForwarding) { |
| queue.offer(callForwarding); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| boolean testValue = true; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyCallForwardingChanged( |
| SubscriptionManager.getDefaultSubscriptionId(), |
| testValue)); |
| |
| boolean result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(testValue, result); |
| } |
| |
| @Test |
| @RequiresFlagsDisabled(Flags.FLAG_NOTIFY_DATA_ACTIVITY_CHANGED_WITH_SLOT) |
| public void testNotifyDataActivityChanged() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onDataActivity(int activity) { |
| queue.offer(activity); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_DATA_ACTIVITY); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| int testValue = TelephonyManager.DATA_ACTIVITY_DORMANT; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyDataActivityChanged( |
| SubscriptionManager.getDefaultSubscriptionId(), |
| testValue)); |
| |
| int result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(testValue, result); |
| } |
| |
| @Test |
| @RequiresFlagsEnabled(Flags.FLAG_NOTIFY_DATA_ACTIVITY_CHANGED_WITH_SLOT) |
| public void testNotifyDataActivityChangedWithSlot() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onDataActivity(int activity) { |
| queue.offer(activity); |
| } |
| }; |
| TelephonyManager tm = context.getSystemService(TelephonyManager.class); |
| tm.listen(psl, PhoneStateListener.LISTEN_DATA_ACTIVITY); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| int testValue = TelephonyManager.DATA_ACTIVITY_DORMANT; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyDataActivityChanged( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| testValue)); |
| |
| int result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(testValue, result); |
| } |
| |
| @Test |
| public void testCarrierPrivilegesCallback() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue = |
| new LinkedBlockingQueue(2); |
| LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue = new LinkedBlockingQueue(2); |
| |
| CarrierPrivilegesCallback cpc = new TestCarrierPrivilegesCallback(carrierPrivilegesQueue, |
| carrierServiceQueue); |
| CarrierPrivilegesCallback cpc2 = new TestCarrierPrivilegesCallback(carrierPrivilegesQueue, |
| carrierServiceQueue); |
| |
| TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); |
| try { |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| telephonyManager, |
| tm -> tm.registerCarrierPrivilegesCallback(0, context.getMainExecutor(), cpc)); |
| // Clear the initial carrierPrivilegesResult from registering the listener. We can't |
| // necessarily guarantee this is empty so don't assert on it other than the fact we |
| // got _something_. We restore this at the end of the test. |
| Pair<Set<String>, Set<Integer>> initialCarrierPrivilegesState = |
| carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull(initialCarrierPrivilegesState); |
| Pair<String, Integer> initialCarrierServiceState = |
| carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull(initialCarrierServiceState); |
| |
| // Update state |
| Set<String> privilegedPackageNames = |
| Set.of("com.carrier.package1", "com.carrier.package2"); |
| Set<Integer> privilegedUids = Set.of(12345, 54321); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| mTelephonyRegistryMgr, |
| trm -> { |
| trm.notifyCarrierPrivilegesChanged( |
| 0, privilegedPackageNames, privilegedUids); |
| trm.notifyCarrierServiceChanged(0, "com.carrier.package1", 12345); |
| }); |
| Pair<Set<String>, Set<Integer>> carrierPrivilegesResult = |
| carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(privilegedPackageNames, carrierPrivilegesResult.first); |
| assertEquals(privilegedUids, carrierPrivilegesResult.second); |
| |
| Pair<String, Integer> carrierServiceResult = |
| carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals("com.carrier.package1", carrierServiceResult.first); |
| assertEquals(12345, (long) carrierServiceResult.second); |
| |
| // Update the state again, but only notify carrier privileges change this time |
| Set<String> newPrivilegedPackageNames = Set.of("com.carrier.package1", |
| "com.carrier.package3"); |
| Set<Integer> newPrivilegedUids = Set.of(12345, 678910); |
| |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| mTelephonyRegistryMgr, |
| trm -> { |
| trm.notifyCarrierPrivilegesChanged( |
| 0, newPrivilegedPackageNames, newPrivilegedUids); |
| }); |
| // The CarrierPrivileges pkgs and UIDs should be updated |
| carrierPrivilegesResult = |
| carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(newPrivilegedPackageNames, carrierPrivilegesResult.first); |
| assertEquals(newPrivilegedUids, carrierPrivilegesResult.second); |
| |
| // And the CarrierService change notification should NOT be triggered |
| assertNull(carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
| |
| // Registering cpc2 now immediately gets us the most recent state |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| telephonyManager, |
| tm -> tm.registerCarrierPrivilegesCallback(0, context.getMainExecutor(), cpc2)); |
| carrierPrivilegesResult = carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, |
| TimeUnit.MILLISECONDS); |
| assertEquals(newPrivilegedPackageNames, carrierPrivilegesResult.first); |
| assertEquals(newPrivilegedUids, carrierPrivilegesResult.second); |
| |
| carrierServiceResult = carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals("com.carrier.package1", carrierServiceResult.first); |
| assertEquals(12345, (long) carrierServiceResult.second); |
| |
| // Removing cpc means it won't get the final callback when we restore the original state |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| telephonyManager, tm -> tm.unregisterCarrierPrivilegesCallback(cpc)); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| mTelephonyRegistryMgr, |
| trm -> { |
| trm.notifyCarrierPrivilegesChanged( |
| 0, initialCarrierPrivilegesState.first, |
| initialCarrierPrivilegesState.second); |
| trm.notifyCarrierServiceChanged(0, initialCarrierServiceState.first, |
| initialCarrierServiceState.second); |
| }); |
| |
| carrierPrivilegesResult = carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, |
| TimeUnit.MILLISECONDS); |
| assertEquals(initialCarrierPrivilegesState.first, carrierPrivilegesResult.first); |
| assertEquals(initialCarrierPrivilegesState.second, carrierPrivilegesResult.second); |
| |
| carrierServiceResult = carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(initialCarrierServiceState.first, carrierServiceResult.first); |
| assertEquals(initialCarrierServiceState.second, carrierServiceResult.second); |
| |
| // No further callbacks received |
| assertNull(carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
| assertNull(carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
| } finally { |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( |
| telephonyManager, |
| tm -> { |
| tm.unregisterCarrierPrivilegesCallback(cpc); // redundant, but still allowed |
| tm.unregisterCarrierPrivilegesCallback(cpc2); |
| }); |
| } |
| } |
| |
| private class TestCarrierPrivilegesCallback implements CarrierPrivilegesCallback { |
| LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> mCarrierPrivilegesQueue; |
| LinkedBlockingQueue<Pair<String, Integer>> mCarrierServiceQueue; |
| |
| TestCarrierPrivilegesCallback( |
| LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue, |
| LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue) { |
| mCarrierPrivilegesQueue = carrierPrivilegesQueue; |
| mCarrierServiceQueue = carrierServiceQueue; |
| } |
| |
| @Override |
| public void onCarrierPrivilegesChanged(@NonNull Set<String> privilegedPackageNames, |
| @NonNull Set<Integer> privilegedUids) { |
| mCarrierPrivilegesQueue.offer(new Pair<>(privilegedPackageNames, privilegedUids)); |
| } |
| |
| @Override |
| public void onCarrierServiceChanged(@Nullable String carrierServicePackageName, |
| int carrierServiceUid) { |
| mCarrierServiceQueue.offer(new Pair<>(carrierServicePackageName, carrierServiceUid)); |
| } |
| } |
| |
| |
| @Test |
| public void testNotifyPreciseCallStateWithImsCall() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<List<CallState>> queue = new LinkedBlockingQueue<>(1); |
| TestTelephonyCallback testCb = new TestTelephonyCallback(queue); |
| |
| TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_INCOMING, |
| PreciseCallState.PRECISE_CALL_STATE_ACTIVE, |
| PreciseCallState.PRECISE_CALL_STATE_IDLE}; |
| String[] dummyImsCallIds = {"1", "0", "-1"}; |
| int[] dummyImsServiceTypes = {ImsCallProfile.SERVICE_TYPE_NORMAL, |
| ImsCallProfile.SERVICE_TYPE_NORMAL, |
| ImsCallProfile.SERVICE_TYPE_NONE}; |
| int[] dummyImsCallTypes = {ImsCallProfile.CALL_TYPE_VT, |
| ImsCallProfile.CALL_TYPE_VOICE, |
| ImsCallProfile.CALL_TYPE_NONE}; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyPreciseCallState( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| dummyCallStates, dummyImsCallIds, dummyImsServiceTypes, dummyImsCallTypes)); |
| |
| List<CallState> testCallStatesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", testCallStatesResult); |
| assertEquals(2, testCallStatesResult.size()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_ACTIVE, |
| testCallStatesResult.get(0).getCallState()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_INCOMING, |
| testCallStatesResult.get(1).getCallState()); |
| assertEquals("0", |
| testCallStatesResult.get(0).getImsCallSessionId()); |
| assertEquals("1", |
| testCallStatesResult.get(1).getImsCallSessionId()); |
| assertEquals(ImsCallProfile.CALL_TYPE_VOICE, |
| testCallStatesResult.get(0).getImsCallType()); |
| assertEquals(ImsCallProfile.CALL_TYPE_VT, |
| testCallStatesResult.get(1).getImsCallType()); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.unregisterTelephonyCallback(testCb)); |
| } |
| |
| @Test |
| public void testNotifyPreciseCallStateWithCsCall() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<List<CallState>> queue = new LinkedBlockingQueue<>(1); |
| TestTelephonyCallback testCb = new TestTelephonyCallback(queue); |
| |
| TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_INCOMING, |
| PreciseCallState.PRECISE_CALL_STATE_ACTIVE, |
| PreciseCallState.PRECISE_CALL_STATE_IDLE}; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyPreciseCallState( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| dummyCallStates, null, null, null)); |
| |
| List<CallState> testCallStatesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", testCallStatesResult); |
| assertEquals(2, testCallStatesResult.size()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_ACTIVE, |
| testCallStatesResult.get(0).getCallState()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_INCOMING, |
| testCallStatesResult.get(1).getCallState()); |
| assertNull(testCallStatesResult.get(0).getImsCallSessionId()); |
| assertNull(testCallStatesResult.get(1).getImsCallSessionId()); |
| assertEquals(ImsCallProfile.SERVICE_TYPE_NONE, |
| testCallStatesResult.get(0).getImsCallServiceType()); |
| assertEquals(ImsCallProfile.SERVICE_TYPE_NONE, |
| testCallStatesResult.get(1).getImsCallServiceType()); |
| assertEquals(ImsCallProfile.CALL_TYPE_NONE, |
| testCallStatesResult.get(0).getImsCallType()); |
| assertEquals(ImsCallProfile.CALL_TYPE_NONE, |
| testCallStatesResult.get(1).getImsCallType()); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.unregisterTelephonyCallback(testCb)); |
| } |
| |
| @Test |
| public void testNotifyPreciseCallStateLegacyCallback() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<CallAttributes> queue = new LinkedBlockingQueue<>(1); |
| TestTelephonyCallbackLegacy testCb = new TestTelephonyCallbackLegacy(queue); |
| |
| TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.registerTelephonyCallback(context.getMainExecutor(), testCb)); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_INCOMING, |
| PreciseCallState.PRECISE_CALL_STATE_HOLDING, |
| PreciseCallState.PRECISE_CALL_STATE_IDLE}; |
| String[] dummyImsCallIds = {"1", "0", "-1"}; |
| int[] dummyImsServiceTypes = {ImsCallProfile.SERVICE_TYPE_NORMAL, |
| ImsCallProfile.SERVICE_TYPE_NORMAL, |
| ImsCallProfile.SERVICE_TYPE_NONE}; |
| int[] dummyImsCallTypes = {ImsCallProfile.CALL_TYPE_VT, |
| ImsCallProfile.CALL_TYPE_VOICE, |
| ImsCallProfile.CALL_TYPE_NONE}; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyPreciseCallState( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| dummyCallStates, dummyImsCallIds, dummyImsServiceTypes, dummyImsCallTypes)); |
| |
| CallAttributes testCallAttributesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", testCallAttributesResult); |
| |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_HOLDING, |
| testCallAttributesResult.getPreciseCallState().getForegroundCallState()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_IDLE, |
| testCallAttributesResult.getPreciseCallState().getBackgroundCallState()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_INCOMING, |
| testCallAttributesResult.getPreciseCallState().getRingingCallState()); |
| |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.unregisterTelephonyCallback(testCb)); |
| } |
| |
| @Test |
| public void testNotifyPreciseCallStatePhoneStateListener() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| LinkedBlockingQueue<CallAttributes> queue = new LinkedBlockingQueue<>(1); |
| PhoneStateListener psl = new PhoneStateListener(context.getMainExecutor()) { |
| @Override |
| public void onCallAttributesChanged(CallAttributes ca) { |
| queue.offer(ca); |
| } |
| }; |
| |
| TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.listen(psl, PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)); |
| // clear the initial result from registering the listener. |
| queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| |
| int[] dummyCallStates = {PreciseCallState.PRECISE_CALL_STATE_IDLE, |
| PreciseCallState.PRECISE_CALL_STATE_ACTIVE, |
| PreciseCallState.PRECISE_CALL_STATE_HOLDING}; |
| String[] dummyImsCallIds = {"-1", "0", "1"}; |
| int[] dummyImsServiceTypes = {ImsCallProfile.SERVICE_TYPE_NONE, |
| ImsCallProfile.SERVICE_TYPE_NORMAL, |
| ImsCallProfile.SERVICE_TYPE_NORMAL}; |
| int[] dummyImsCallTypes = {ImsCallProfile.CALL_TYPE_NONE, |
| ImsCallProfile.CALL_TYPE_VOICE, |
| ImsCallProfile.CALL_TYPE_VT}; |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyRegistryMgr, |
| (trm) -> trm.notifyPreciseCallState( |
| SubscriptionManager.getSlotIndex( |
| SubscriptionManager.getDefaultSubscriptionId()), |
| SubscriptionManager.getDefaultSubscriptionId(), |
| dummyCallStates, dummyImsCallIds, dummyImsServiceTypes, dummyImsCallTypes)); |
| |
| CallAttributes testCallAttributesResult = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertNotNull("Timed out waiting for phone state change", testCallAttributesResult); |
| |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_ACTIVE, |
| testCallAttributesResult.getPreciseCallState().getForegroundCallState()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_HOLDING, |
| testCallAttributesResult.getPreciseCallState().getBackgroundCallState()); |
| assertEquals(PreciseCallState.PRECISE_CALL_STATE_IDLE, |
| testCallAttributesResult.getPreciseCallState().getRingingCallState()); |
| ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyManager, |
| (tm) -> tm.listen(psl, PhoneStateListener.LISTEN_NONE)); |
| } |
| |
| private class TestTelephonyCallback extends TelephonyCallback |
| implements TelephonyCallback.CallAttributesListener { |
| LinkedBlockingQueue<List<CallState>> mTestCallStatesQueue; |
| TestTelephonyCallback(LinkedBlockingQueue<List<CallState>> queue) { |
| mTestCallStatesQueue = queue; |
| } |
| @Override |
| public void onCallStatesChanged(@NonNull List<CallState> callStateList) { |
| mTestCallStatesQueue.offer(callStateList); |
| } |
| } |
| |
| private class TestTelephonyCallbackLegacy extends TelephonyCallback |
| implements TelephonyCallback.CallAttributesListener { |
| LinkedBlockingQueue<CallAttributes> mTestCallAttributes; |
| TestTelephonyCallbackLegacy(LinkedBlockingQueue<CallAttributes> queue) { |
| mTestCallAttributes = queue; |
| } |
| @Override |
| public void onCallAttributesChanged(@NonNull CallAttributes callAttributes) { |
| mTestCallAttributes.offer(callAttributes); |
| } |
| } |
| } |