Merge "Revert^2 "Revert "Add CTS tests for exclude VPN routes APIs"""
diff --git a/framework/Android.bp b/framework/Android.bp
index e765ee8..028701a 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -66,6 +66,7 @@
         ":net-utils-framework-common-srcs",
     ],
     aidl: {
+        generate_get_transaction_name: true,
         include_dirs: [
             // Include directories for parcelables that are part of the stable API, and need a
             // one-line "parcelable X" .aidl declaration to be used in AIDL interfaces.
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 6227bb2..a59b5d6 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -10235,12 +10235,8 @@
     }
 
     private void enforceAutomotiveDevice() {
-        final boolean isAutomotiveDevice =
-                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
-        if (!isAutomotiveDevice) {
-            throw new UnsupportedOperationException(
-                    "setOemNetworkPreference() is only available on automotive devices.");
-        }
+        PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE,
+                "setOemNetworkPreference() is only available on automotive devices.");
     }
 
     /**
diff --git a/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
index a3da05d..c86e699 100644
--- a/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
@@ -35,10 +35,12 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.usage.NetworkStats;
 import android.app.usage.NetworkStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -60,6 +62,7 @@
 import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 import android.util.DataUnit;
+import android.util.Range;
 import android.util.RecurrenceRule;
 
 import androidx.test.filters.SmallTest;
@@ -68,7 +71,6 @@
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.LocalServices;
 import com.android.server.net.NetworkPolicyManagerInternal;
-import com.android.server.net.NetworkStatsManagerInternal;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRunner;
 
@@ -87,6 +89,7 @@
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.temporal.ChronoUnit;
+import java.util.Set;
 
 @RunWith(DevSdkIgnoreRunner.class)
 @SmallTest
@@ -106,7 +109,6 @@
     @Mock private NetworkPolicyManager mNPM;
     @Mock private NetworkStatsManager mStatsManager;
     @Mock private NetworkPolicyManagerInternal mNPMI;
-    @Mock private NetworkStatsManagerInternal mNetworkStatsManagerInternal;
     @Mock private TelephonyManager mTelephonyManager;
     private MockContentResolver mContentResolver;
 
@@ -164,9 +166,6 @@
         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
         LocalServices.addService(NetworkPolicyManagerInternal.class, mNPMI);
 
-        LocalServices.removeServiceForTest(NetworkStatsManagerInternal.class);
-        LocalServices.addService(NetworkStatsManagerInternal.class, mNetworkStatsManagerInternal);
-
         mTracker = new MultipathPolicyTracker(mContext, mHandler, mDeps);
     }
 
@@ -201,6 +200,11 @@
         when(mNPMI.getSubscriptionOpportunisticQuota(TEST_NETWORK, QUOTA_TYPE_MULTIPATH))
                 .thenReturn(subscriptionQuota);
 
+        // Prepare stats to be mocked.
+        final NetworkStats.Bucket mockedStatsBucket = mock(NetworkStats.Bucket.class);
+        when(mockedStatsBucket.getTxBytes()).thenReturn(usedBytesToday / 3);
+        when(mockedStatsBucket.getRxBytes()).thenReturn(usedBytesToday - usedBytesToday / 3);
+
         // Setup user policy warning / limit
         if (policyWarning != WARNING_DISABLED || policyLimit != LIMIT_DISABLED) {
             final Instant recurrenceStart = Instant.parse("2017-04-01T00:00:00Z");
@@ -214,7 +218,9 @@
             final boolean snoozeLimit = policyLimit == POLICY_SNOOZED;
             when(mNPM.getNetworkPolicies()).thenReturn(new NetworkPolicy[] {
                     new NetworkPolicy(
-                            NetworkTemplate.buildTemplateMobileWildcard(),
+                            new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
+                                    .setSubscriberIds(Set.of(TEST_IMSI1))
+                                    .setMeteredness(android.net.NetworkStats.METERED_YES).build(),
                             recurrenceRule,
                             snoozeWarning ? 0 : policyWarning,
                             snoozeLimit ? 0 : policyLimit,
@@ -224,6 +230,13 @@
                             true /* metered */,
                             false /* inferred */)
             });
+
+            // Mock stats for this month.
+            final Range<ZonedDateTime> cycleOfTheMonth = recurrenceRule.cycleIterator().next();
+            when(mStatsManager.querySummaryForDevice(any(),
+                    eq(cycleOfTheMonth.getLower().toInstant().toEpochMilli()),
+                    eq(cycleOfTheMonth.getUpper().toInstant().toEpochMilli())))
+                    .thenReturn(mockedStatsBucket);
         } else {
             when(mNPM.getNetworkPolicies()).thenReturn(new NetworkPolicy[0]);
         }
@@ -235,10 +248,10 @@
         when(mResources.getInteger(R.integer.config_networkDefaultDailyMultipathQuotaBytes))
                 .thenReturn((int) defaultResSetting);
 
-        when(mNetworkStatsManagerInternal.getNetworkTotalBytes(
-                any(),
+        // Mock stats for today.
+        when(mStatsManager.querySummaryForDevice(any(),
                 eq(startOfDay.toInstant().toEpochMilli()),
-                eq(now.toInstant().toEpochMilli()))).thenReturn(usedBytesToday);
+                eq(now.toInstant().toEpochMilli()))).thenReturn(mockedStatsBucket);
 
         ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallback =
                 ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
@@ -291,8 +304,10 @@
         testGetMultipathPreference(
                 DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */,
                 OPPORTUNISTIC_QUOTA_UNKNOWN,
-                // 29 days from Apr. 2nd to May 1st
-                DataUnit.MEGABYTES.toBytes(15 * 29 * 20) /* policyWarning */,
+                // Remaining days are 29 days from Apr. 2nd to May 1st.
+                // Set limit so that 15MB * remaining days will be 5% of the remaining limit,
+                // so it will be 15 * 29 / 0.05 + used bytes.
+                DataUnit.MEGABYTES.toBytes(15 * 29 * 20 + 7) /* policyWarning */,
                 LIMIT_DISABLED,
                 DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */,
                 2_500_000 /* defaultResSetting */,
@@ -308,9 +323,11 @@
         testGetMultipathPreference(
                 DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */,
                 OPPORTUNISTIC_QUOTA_UNKNOWN,
-                // 29 days from Apr. 2nd to May 1st
                 POLICY_SNOOZED /* policyWarning */,
-                DataUnit.MEGABYTES.toBytes(15 * 29 * 20) /* policyLimit */,
+                // Remaining days are 29 days from Apr. 2nd to May 1st.
+                // Set limit so that 15MB * remaining days will be 5% of the remaining limit,
+                // so it will be 15 * 29 / 0.05 + used bytes.
+                DataUnit.MEGABYTES.toBytes(15 * 29 * 20 + 7) /* policyLimit */,
                 DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */,
                 2_500_000 /* defaultResSetting */,
                 false /* roaming */);
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 6416808..d82a756 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -96,6 +96,7 @@
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.TelephonyNetworkSpecifier;
+import android.net.TetheringManager;
 import android.net.UnderlyingNetworkInfo;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.net.wifi.WifiInfo;
@@ -184,6 +185,7 @@
     private @Mock TelephonyManager mTelephonyManager;
     private static @Mock WifiInfo sWifiInfo;
     private @Mock INetworkManagementService mNetManager;
+    private @Mock TetheringManager mTetheringManager;
     private @Mock NetworkStatsFactory mStatsFactory;
     private @Mock NetworkStatsSettings mSettings;
     private @Mock IBinder mBinder;
@@ -197,6 +199,7 @@
     private INetworkManagementEventObserver mNetworkObserver;
     private ContentObserver mContentObserver;
     private Handler mHandler;
+    private TetheringManager.TetheringEventCallback mTetheringEventCallback;
 
     private class MockContext extends BroadcastInterceptingContext {
         private final Context mBaseContext;
@@ -209,6 +212,7 @@
         @Override
         public Object getSystemService(String name) {
             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
+            if (Context.TETHERING_SERVICE.equals(name)) return mTetheringManager;
             return mBaseContext.getSystemService(name);
         }
 
@@ -279,11 +283,18 @@
         mSession = mService.openSession();
         assertNotNull("openSession() failed", mSession);
 
-        // catch INetworkManagementEventObserver during systemReady()
+        // Catch INetworkManagementEventObserver during systemReady().
         ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
                 ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
         verify(mNetManager).registerObserver(networkObserver.capture());
         mNetworkObserver = networkObserver.getValue();
+
+        // Catch TetheringEventCallback during systemReady().
+        ArgumentCaptor<TetheringManager.TetheringEventCallback> tetheringEventCbCaptor =
+                ArgumentCaptor.forClass(TetheringManager.TetheringEventCallback.class);
+        verify(mTetheringManager).registerTetheringEventCallback(
+                any(), tetheringEventCbCaptor.capture());
+        mTetheringEventCallback = tetheringEventCbCaptor.getValue();
     }
 
     @NonNull
@@ -296,7 +307,7 @@
 
             @Override
             public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(
-                    @NonNull Context context, @NonNull Looper looper, @NonNull Executor executor,
+                    @NonNull Context context, @NonNull Executor executor,
                     @NonNull NetworkStatsService service) {
 
                 return mNetworkStatsSubscriptionsMonitor;
@@ -1649,6 +1660,21 @@
                 DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 2);
     }
 
+    @Test
+    public void testTetheringEventCallback_onUpstreamChanged() throws Exception {
+        // Register custom provider and retrieve callback.
+        final TestableNetworkStatsProviderBinder provider =
+                new TestableNetworkStatsProviderBinder();
+        final INetworkStatsProviderCallback cb =
+                mService.registerNetworkStatsProvider("TEST-TETHERING-OFFLOAD", provider);
+        assertNotNull(cb);
+        provider.assertNoCallback();
+
+        // Post upstream changed event, verify the service will pull for stats.
+        mTetheringEventCallback.onUpstreamChanged(WIFI_NETWORK);
+        provider.expectOnRequestStatsUpdate(0 /* unused */);
+    }
+
     private static File getBaseDir(File statsDir) {
         File baseDir = new File(statsDir, "netstats");
         baseDir.mkdirs();
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
index 2bc385c..58cdc7f 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
@@ -35,12 +35,13 @@
 import android.content.Context;
 import android.net.NetworkTemplate;
 import android.os.Build;
-import android.os.test.TestLooper;
+import android.os.Looper;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.util.SparseArray;
 
 import com.android.internal.util.CollectionUtils;
 import com.android.server.net.NetworkStatsSubscriptionsMonitor.RatTypeListener;
@@ -71,26 +72,30 @@
     @Mock private Context mContext;
     @Mock private SubscriptionManager mSubscriptionManager;
     @Mock private TelephonyManager mTelephonyManager;
+    private final SparseArray<TelephonyManager> mTelephonyManagerOfSub = new SparseArray<>();
+    private final SparseArray<RatTypeListener> mRatTypeListenerOfSub = new SparseArray<>();
     @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate;
     private final List<Integer> mTestSubList = new ArrayList<>();
 
     private final Executor mExecutor = Executors.newSingleThreadExecutor();
     private NetworkStatsSubscriptionsMonitor mMonitor;
-    private TestLooper mTestLooper = new TestLooper();
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+        // TODO(b/213280079): Start a different thread and prepare the looper, create the monitor
+        //  on that thread instead of using the test main thread looper.
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
 
         when(mContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
                 .thenReturn(mSubscriptionManager);
         when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE)))
                 .thenReturn(mTelephonyManager);
 
-        mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mTestLooper.getLooper(),
-                mExecutor, mDelegate);
+        mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mExecutor, mDelegate);
     }
 
     @Test
@@ -116,12 +121,10 @@
         return list;
     }
 
-    private void setRatTypeForSub(List<RatTypeListener> listeners,
-            int subId, int type) {
+    private void setRatTypeForSub(int subId, int type) {
         final ServiceState serviceState = mock(ServiceState.class);
         when(serviceState.getDataNetworkType()).thenReturn(type);
-        final RatTypeListener match = CollectionUtils
-                .find(listeners, it -> it.getSubId() == subId);
+        final RatTypeListener match = mRatTypeListenerOfSub.get(subId);
         if (match == null) {
             fail("Could not find listener with subId: " + subId);
         }
@@ -136,21 +139,41 @@
 
         final int[] subList = convertArrayListToIntArray(mTestSubList);
         when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList);
-        when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);
-        mMonitor.onSubscriptionsChanged();
+        updateSubscriberIdForTestSub(subId, subscriberId);
     }
 
     private void updateSubscriberIdForTestSub(int subId, @Nullable final String subscriberId) {
-        when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);
+        final TelephonyManager telephonyManagerOfSub;
+        if (mTelephonyManagerOfSub.contains(subId)) {
+            telephonyManagerOfSub = mTelephonyManagerOfSub.get(subId);
+        } else {
+            telephonyManagerOfSub = mock(TelephonyManager.class);
+            mTelephonyManagerOfSub.put(subId, telephonyManagerOfSub);
+        }
+        when(telephonyManagerOfSub.getSubscriberId()).thenReturn(subscriberId);
+        when(mTelephonyManager.createForSubscriptionId(subId)).thenReturn(telephonyManagerOfSub);
         mMonitor.onSubscriptionsChanged();
     }
 
+    private void assertAndCaptureRatTypeListenerRegistrationWith(int subId, int listenedState) {
+        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
+                ArgumentCaptor.forClass(RatTypeListener.class);
+        verify(mTelephonyManagerOfSub.get(subId)).listen(ratTypeListenerCaptor.capture(),
+                eq(listenedState));
+        final RatTypeListener listener = CollectionUtils
+                .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == subId);
+        assertNotNull(listener);
+        mRatTypeListenerOfSub.put(subId, listener);
+    }
+
     private void removeTestSub(int subId) {
         // Remove subId from TestSubList.
         mTestSubList.removeIf(it -> it == subId);
         final int[] subList = convertArrayListToIntArray(mTestSubList);
         when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList);
         mMonitor.onSubscriptionsChanged();
+        mRatTypeListenerOfSub.delete(subId);
+        // Keep TelephonyManagerOfSubs so the test could verify de-registration.
     }
 
     private void assertRatTypeChangedForSub(String subscriberId, int ratType) {
@@ -171,9 +194,6 @@
 
     @Test
     public void testSubChangedAndRatTypeChanged() {
-        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
-                ArgumentCaptor.forClass(RatTypeListener.class);
-
         mMonitor.start();
         // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
         // before changing RAT type.
@@ -183,15 +203,16 @@
         // Insert sim2.
         addTestSub(TEST_SUBID2, TEST_IMSI2);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
-        verify(mTelephonyManager, times(2)).listen(ratTypeListenerCaptor.capture(),
-                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID2,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
         reset(mDelegate);
 
         // Set RAT type of sim1 to UMTS.
         // Verify RAT type of sim1 after subscription gets onCollapsedRatTypeChanged() callback
         // and others remain untouched.
-        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_UMTS);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN);
@@ -200,8 +221,7 @@
         // Set RAT type of sim2 to LTE.
         // Verify RAT type of sim2 after subscription gets onCollapsedRatTypeChanged() callback
         // and others remain untouched.
-        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID2,
-                TelephonyManager.NETWORK_TYPE_LTE);
+        setRatTypeForSub(TEST_SUBID2, TelephonyManager.NETWORK_TYPE_LTE);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_LTE);
         assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN);
@@ -210,7 +230,8 @@
         // Remove sim2 and verify that callbacks are fired and RAT type is correct for sim2.
         // while the other two remain untouched.
         removeTestSub(TEST_SUBID2);
-        verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID2,
+                PhoneStateListener.LISTEN_NONE);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN);
@@ -218,13 +239,15 @@
 
         // Set RAT type of sim1 to UNKNOWN. Then stop monitoring subscription changes
         // and verify that the listener for sim1 is removed.
-        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         reset(mDelegate);
 
         mMonitor.stop();
-        verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_NONE);
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID2,
+                PhoneStateListener.LISTEN_NONE);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
     }
 
@@ -236,13 +259,9 @@
         // before changing RAT type. Also capture listener for later use.
         addTestSub(TEST_SUBID1, TEST_IMSI1);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
-        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
-                ArgumentCaptor.forClass(RatTypeListener.class);
-        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
-                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
-        final RatTypeListener listener = CollectionUtils
-                .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1);
-        assertNotNull(listener);
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
+        final RatTypeListener listener = mRatTypeListenerOfSub.get(TEST_SUBID1);
 
         // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs
         // NETWORK_TYPE_5G_NSA.
@@ -267,8 +286,7 @@
         reset(mDelegate);
 
         // Set RAT type to 5G standalone mode, the RAT type should be NR.
-        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_NR);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_NR);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
         reset(mDelegate);
 
@@ -281,59 +299,53 @@
 
     @Test
     public void testSubscriberIdUnavailable() {
-        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
-                ArgumentCaptor.forClass(RatTypeListener.class);
-
         mMonitor.start();
         // Insert sim1, set subscriberId to null which is normal in SIM PIN locked case.
         // Verify RAT type is NETWORK_TYPE_UNKNOWN and service will not perform listener
         // registration.
         addTestSub(TEST_SUBID1, null);
-        verify(mTelephonyManager, never()).listen(any(), anyInt());
+        verify(mTelephonyManagerOfSub.get(TEST_SUBID1), never()).listen(any(), anyInt());
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
 
         // Set IMSI for sim1, verify the listener will be registered.
         updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
-        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
-                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
         reset(mTelephonyManager);
-        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
 
         // Set RAT type of sim1 to UMTS. Verify RAT type of sim1 is changed.
-        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_UMTS);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
         reset(mDelegate);
 
         // Set IMSI to null again to simulate somehow IMSI is not available, such as
         // modem crash. Verify service should unregister listener.
         updateSubscriberIdForTestSub(TEST_SUBID1, null);
-        verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
-                eq(PhoneStateListener.LISTEN_NONE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_NONE);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         reset(mDelegate);
-        clearInvocations(mTelephonyManager);
+        clearInvocations(mTelephonyManagerOfSub.get(TEST_SUBID1));
 
         // Simulate somehow IMSI is back. Verify service will register with
         // another listener and fire callback accordingly.
         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor2 =
                 ArgumentCaptor.forClass(RatTypeListener.class);
         updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
-        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(),
-                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         reset(mDelegate);
-        clearInvocations(mTelephonyManager);
+        clearInvocations(mTelephonyManagerOfSub.get(TEST_SUBID1));
 
         // Set RAT type of sim1 to LTE. Verify RAT type of sim1 still works.
-        setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_LTE);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_LTE);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
         reset(mDelegate);
 
         mMonitor.stop();
-        verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor2.getValue()),
-                eq(PhoneStateListener.LISTEN_NONE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_NONE);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
     }
 
@@ -349,30 +361,26 @@
         // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
         // before changing RAT type.
         addTestSub(TEST_SUBID1, TEST_IMSI1);
-        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
-                ArgumentCaptor.forClass(RatTypeListener.class);
-        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
-                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
 
         // Set RAT type of sim1 to UMTS.
         // Verify RAT type of sim1 changes accordingly.
-        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_UMTS);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
         reset(mDelegate);
-        clearInvocations(mTelephonyManager);
+        clearInvocations(mTelephonyManagerOfSub.get(TEST_SUBID1));
 
         // Simulate IMSI of sim1 changed to IMSI2. Verify the service will register with
         // another listener and remove the old one. The RAT type of new IMSI stays at
         // NETWORK_TYPE_UNKNOWN until received initial callback from telephony.
-        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor2 =
-                ArgumentCaptor.forClass(RatTypeListener.class);
         updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI2);
-        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(),
-                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
-        verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
-                eq(PhoneStateListener.LISTEN_NONE));
+        final RatTypeListener oldListener = mRatTypeListenerOfSub.get(TEST_SUBID1);
+        assertAndCaptureRatTypeListenerRegistrationWith(TEST_SUBID1,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
+        verify(mTelephonyManagerOfSub.get(TEST_SUBID1), times(1))
+                .listen(eq(oldListener), eq(PhoneStateListener.LISTEN_NONE));
         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         reset(mDelegate);
@@ -380,8 +388,7 @@
         // Set RAT type of sim1 to UMTS for new listener to simulate the initial callback received
         // from telephony after registration. Verify RAT type of sim1 changes with IMSI2
         // accordingly.
-        setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1,
-                TelephonyManager.NETWORK_TYPE_UMTS);
+        setRatTypeForSub(TEST_SUBID1, TelephonyManager.NETWORK_TYPE_UMTS);
         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
         assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UMTS);
         reset(mDelegate);