Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e539d7f8 authored by Rambo Wang's avatar Rambo Wang Committed by Automerger Merge Worker
Browse files

[DO NOT MERGE] Revert "Remove VCN Carrier Privilege grace period" am: 3a8a004d

parents c944dd27 3a8a004d
Loading
Loading
Loading
Loading
+44 −16
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.telephony.SubscriptionManager.isValidSubscriptionId;


import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
@@ -167,6 +168,10 @@ public class VcnManagementService extends IVcnManagementService.Stub {
    static final String VCN_CONFIG_FILE =
    static final String VCN_CONFIG_FILE =
            new File(Environment.getDataSystemDirectory(), "vcn/configs.xml").getPath();
            new File(Environment.getDataSystemDirectory(), "vcn/configs.xml").getPath();


    // TODO(b/176956496): Directly use CarrierServiceBindHelper.UNBIND_DELAY_MILLIS
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static final long CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS = TimeUnit.SECONDS.toMillis(30);

    /* Binder context for this service */
    /* Binder context for this service */
    @NonNull private final Context mContext;
    @NonNull private final Context mContext;
    @NonNull private final Dependencies mDeps;
    @NonNull private final Dependencies mDeps;
@@ -360,15 +365,12 @@ public class VcnManagementService extends IVcnManagementService.Stub {


    /** Notifies the VcnManagementService that external dependencies can be set up. */
    /** Notifies the VcnManagementService that external dependencies can be set up. */
    public void systemReady() {
    public void systemReady() {
        // Always run on the handler thread to ensure consistency.
        mHandler.post(() -> {
        mNetworkProvider.register();
        mNetworkProvider.register();
        mContext.getSystemService(ConnectivityManager.class)
        mContext.getSystemService(ConnectivityManager.class)
                .registerNetworkCallback(
                .registerNetworkCallback(
                        new NetworkRequest.Builder().clearCapabilities().build(),
                        new NetworkRequest.Builder().clearCapabilities().build(),
                        mTrackingNetworkCallback);
                        mTrackingNetworkCallback);
        mTelephonySubscriptionTracker.register();
        mTelephonySubscriptionTracker.register();
        });
    }
    }


    private void enforcePrimaryUser() {
    private void enforcePrimaryUser() {
@@ -509,15 +511,22 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                        if (!mVcns.containsKey(subGrp)) {
                        if (!mVcns.containsKey(subGrp)) {
                            startVcnLocked(subGrp, entry.getValue());
                            startVcnLocked(subGrp, entry.getValue());
                        }
                        }

                        // Cancel any scheduled teardowns for active subscriptions
                        mHandler.removeCallbacksAndMessages(mVcns.get(subGrp));
                    }
                    }
                }
                }


                // Schedule teardown of any VCN instances that have lost carrier privileges
                // Schedule teardown of any VCN instances that have lost carrier privileges (after a
                // delay)
                for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) {
                for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) {
                    final ParcelUuid subGrp = entry.getKey();
                    final ParcelUuid subGrp = entry.getKey();
                    final VcnConfig config = mConfigs.get(subGrp);
                    final VcnConfig config = mConfigs.get(subGrp);


                    final boolean isActiveSubGrp = isActiveSubGroup(subGrp, snapshot);
                    final boolean isActiveSubGrp = isActiveSubGroup(subGrp, snapshot);
                    final boolean isValidActiveDataSubIdNotInVcnSubGrp =
                            isValidSubscriptionId(snapshot.getActiveDataSubscriptionId())
                                    && !isActiveSubGroup(subGrp, snapshot);


                    // TODO(b/193687515): Support multiple VCNs active at the same time
                    // TODO(b/193687515): Support multiple VCNs active at the same time
                    if (config == null
                    if (config == null
@@ -527,12 +536,31 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                        final ParcelUuid uuidToTeardown = subGrp;
                        final ParcelUuid uuidToTeardown = subGrp;
                        final Vcn instanceToTeardown = entry.getValue();
                        final Vcn instanceToTeardown = entry.getValue();


                        // TODO(b/193687515): Support multiple VCNs active at the same time
                        // If directly switching to a subscription not in the current group,
                        // teardown immediately to prevent other subscription's network from being
                        // outscored by the VCN. Otherwise, teardown after a delay to ensure that
                        // SIM profile switches do not trigger the VCN to cycle.
                        final long teardownDelayMs =
                                isValidActiveDataSubIdNotInVcnSubGrp
                                        ? 0
                                        : CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS;
                        mHandler.postDelayed(() -> {
                            synchronized (mLock) {
                                // Guard against case where this is run after a old instance was
                                // torn down, and a new instance was started. Verify to ensure
                                // correct instance is torn down. This could happen as a result of a
                                // Carrier App manually removing/adding a VcnConfig.
                                if (mVcns.get(uuidToTeardown) == instanceToTeardown) {
                                    stopVcnLocked(uuidToTeardown);
                                    stopVcnLocked(uuidToTeardown);


                                    // TODO(b/181789060): invoke asynchronously after Vcn notifies
                                    // TODO(b/181789060): invoke asynchronously after Vcn notifies
                                    // through VcnCallback
                                    // through VcnCallback
                                    notifyAllPermissionedStatusCallbacksLocked(
                                    notifyAllPermissionedStatusCallbacksLocked(
                                            uuidToTeardown, VCN_STATUS_CODE_INACTIVE);
                                            uuidToTeardown, VCN_STATUS_CODE_INACTIVE);
                                }
                            }
                        }, instanceToTeardown, teardownDelayMs);
                    } else {
                    } else {
                        // If this VCN's status has not changed, update it with the new snapshot
                        // If this VCN's status has not changed, update it with the new snapshot
                        entry.getValue().updateSubscriptionSnapshot(mLastSnapshot);
                        entry.getValue().updateSubscriptionSnapshot(mLastSnapshot);
+93 −7
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;


@@ -276,7 +277,6 @@ public class VcnManagementServiceTest {
    @Test
    @Test
    public void testSystemReady() throws Exception {
    public void testSystemReady() throws Exception {
        mVcnMgmtSvc.systemReady();
        mVcnMgmtSvc.systemReady();
        mTestLooper.dispatchAll();


        verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class));
        verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class));
        verify(mSubscriptionTracker).register();
        verify(mSubscriptionTracker).register();
@@ -494,8 +494,10 @@ public class VcnManagementServiceTest {
        mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
        mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);


        triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());
        triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());
        mTestLooper.dispatchAll();


        // Verify teardown after delay
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
        mTestLooper.dispatchAll();
        verify(vcn).teardownAsynchronously();
        verify(vcn).teardownAsynchronously();
        verify(mMockPolicyListener).onPolicyChanged();
        verify(mMockPolicyListener).onPolicyChanged();
    }
    }
@@ -521,6 +523,92 @@ public class VcnManagementServiceTest {
        assertEquals(0, mVcnMgmtSvc.getAllVcns().size());
        assertEquals(0, mVcnMgmtSvc.getAllVcns().size());
    }
    }


    /**
     * Tests an intermediate state where carrier privileges are marked as lost before active data
     * subId changes during a SIM ejection.
     *
     * <p>The expected outcome is that the VCN is torn down after a delay, as opposed to
     * immediately.
     */
    @Test
    public void testTelephonyNetworkTrackerCallbackLostCarrierPrivilegesBeforeActiveDataSubChanges()
            throws Exception {
        setupActiveSubscription(TEST_UUID_2);

        final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
        final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2);

        // Simulate privileges lost
        triggerSubscriptionTrackerCbAndGetSnapshot(
                TEST_SUBSCRIPTION_ID,
                TEST_UUID_2,
                Collections.emptySet(),
                Collections.emptyMap(),
                false /* hasCarrierPrivileges */);

        // Verify teardown after delay
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
        mTestLooper.dispatchAll();
        verify(vcn).teardownAsynchronously();
    }

    @Test
    public void testTelephonyNetworkTrackerCallbackSimSwitchesDoNotKillVcnInstances()
            throws Exception {
        setupActiveSubscription(TEST_UUID_2);

        final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
        final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2);

        // Simulate SIM unloaded
        triggerSubscriptionTrackerCbAndGetSnapshot(
                INVALID_SUBSCRIPTION_ID,
                null /* activeDataSubscriptionGroup */,
                Collections.emptySet(),
                Collections.emptyMap(),
                false /* hasCarrierPrivileges */);

        // Simulate new SIM loaded right during teardown delay.
        mTestLooper.moveTimeForward(
                VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
        mTestLooper.dispatchAll();
        triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2));

        // Verify that even after the full timeout duration, the VCN instance is not torn down
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
        mTestLooper.dispatchAll();
        verify(vcn, never()).teardownAsynchronously();
    }

    @Test
    public void testTelephonyNetworkTrackerCallbackDoesNotKillNewVcnInstances() throws Exception {
        setupActiveSubscription(TEST_UUID_2);

        final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
        final Vcn oldInstance = startAndGetVcnInstance(TEST_UUID_2);

        // Simulate SIM unloaded
        triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());

        // Config cleared, SIM reloaded & config re-added right before teardown delay, staring new
        // vcnInstance.
        mTestLooper.moveTimeForward(
                VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
        mTestLooper.dispatchAll();
        mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
        triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2));
        final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2);

        // Verify that new instance was different, and the old one was torn down
        assertTrue(oldInstance != newInstance);
        verify(oldInstance).teardownAsynchronously();

        // Verify that even after the full timeout duration, the new VCN instance is not torn down
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
        mTestLooper.dispatchAll();
        verify(newInstance, never()).teardownAsynchronously();
    }

    @Test
    @Test
    public void testPackageChangeListenerRegistered() throws Exception {
    public void testPackageChangeListenerRegistered() throws Exception {
        verify(mMockContext).registerReceiver(any(BroadcastReceiver.class), argThat(filter -> {
        verify(mMockContext).registerReceiver(any(BroadcastReceiver.class), argThat(filter -> {
@@ -910,8 +998,6 @@ public class VcnManagementServiceTest {
    private void setupSubscriptionAndStartVcn(
    private void setupSubscriptionAndStartVcn(
            int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) {
            int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) {
        mVcnMgmtSvc.systemReady();
        mVcnMgmtSvc.systemReady();
        mTestLooper.dispatchAll();

        triggerSubscriptionTrackerCbAndGetSnapshot(
        triggerSubscriptionTrackerCbAndGetSnapshot(
                subGrp,
                subGrp,
                Collections.singleton(subGrp),
                Collections.singleton(subGrp),
@@ -1007,7 +1093,6 @@ public class VcnManagementServiceTest {


    private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
    private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
        mVcnMgmtSvc.systemReady();
        mVcnMgmtSvc.systemReady();
        mTestLooper.dispatchAll();


        final ArgumentCaptor<NetworkCallback> captor =
        final ArgumentCaptor<NetworkCallback> captor =
                ArgumentCaptor.forClass(NetworkCallback.class);
                ArgumentCaptor.forClass(NetworkCallback.class);
@@ -1252,14 +1337,15 @@ public class VcnManagementServiceTest {
                true /* isActive */,
                true /* isActive */,
                true /* hasCarrierPrivileges */);
                true /* hasCarrierPrivileges */);


        // VCN is currently active. Lose carrier privileges for TEST_PACKAGE so the VCN goes
        // VCN is currently active. Lose carrier privileges for TEST_PACKAGE and hit teardown
        // inactive.
        // timeout so the VCN goes inactive.
        final TelephonySubscriptionSnapshot snapshot =
        final TelephonySubscriptionSnapshot snapshot =
                triggerSubscriptionTrackerCbAndGetSnapshot(
                triggerSubscriptionTrackerCbAndGetSnapshot(
                        TEST_UUID_1,
                        TEST_UUID_1,
                        Collections.singleton(TEST_UUID_1),
                        Collections.singleton(TEST_UUID_1),
                        Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1),
                        Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1),
                        false /* hasCarrierPrivileges */);
                        false /* hasCarrierPrivileges */);
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
        mTestLooper.dispatchAll();
        mTestLooper.dispatchAll();


        // Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE
        // Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE