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

Commit 212c06aa authored by Cody Kesting's avatar Cody Kesting
Browse files

Notify VcnStatusCallbacks for VCN start/stop.

This CL updates VcnManagementService to notify VcnStatusCallbacks when a
VCN is started or stopped. VcnStatusCallbacks will also be notified for
config changes that cause a VCN to exit Safe Mode.

Bug: 180659281
Test: atest FrameworksVcnTests
Change-Id: I4168c868185880621333855dfcb51e46cb662741
parent 055977a3
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.server;

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_NOT_CONFIGURED;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;

import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
@@ -37,6 +40,7 @@ import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnManager.VcnErrorCode;
import android.net.vcn.VcnManager.VcnStatusCode;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.net.wifi.WifiInfo;
import android.os.Binder;
@@ -421,6 +425,11 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                                // Carrier App manually removing/adding a VcnConfig.
                                if (mVcns.get(uuidToTeardown) == instanceToTeardown) {
                                    stopVcnLocked(uuidToTeardown);

                                    // TODO(b/181789060): invoke asynchronously after Vcn notifies
                                    // through VcnCallback
                                    notifyAllPermissionedStatusCallbacksLocked(
                                            uuidToTeardown, VCN_STATUS_CODE_INACTIVE);
                                }
                            }
                        }, instanceToTeardown, CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
@@ -454,6 +463,17 @@ public class VcnManagementService extends IVcnManagementService.Stub {
        }
    }

    @GuardedBy("mLock")
    private void notifyAllPermissionedStatusCallbacksLocked(
            @NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) {
        for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
            if (isCallbackPermissioned(cbInfo, subGroup)) {
                Binder.withCleanCallingIdentity(
                        () -> cbInfo.mCallback.onVcnStatusChanged(statusCode));
            }
        }
    }

    @GuardedBy("mLock")
    private void startVcnLocked(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) {
        Slog.v(TAG, "Starting VCN config for subGrp: " + subscriptionGroup);
@@ -470,6 +490,9 @@ public class VcnManagementService extends IVcnManagementService.Stub {
        // Now that a new VCN has started, notify all registered listeners to refresh their
        // UnderlyingNetworkPolicy.
        notifyAllPolicyListenersLocked();

        // TODO(b/181789060): invoke asynchronously after Vcn notifies through VcnCallback
        notifyAllPermissionedStatusCallbacksLocked(subscriptionGroup, VCN_STATUS_CODE_ACTIVE);
    }

    @GuardedBy("mLock")
@@ -478,7 +501,16 @@ public class VcnManagementService extends IVcnManagementService.Stub {
        Slog.v(TAG, "Starting or updating VCN config for subGrp: " + subscriptionGroup);

        if (mVcns.containsKey(subscriptionGroup)) {
            mVcns.get(subscriptionGroup).updateConfig(config);
            final Vcn vcn = mVcns.get(subscriptionGroup);
            final boolean isActive = vcn.isActive();
            vcn.updateConfig(config);

            // Only notify VcnStatusCallbacks if this VCN was previously in Safe Mode
            if (!isActive) {
                // TODO(b/181789060): invoke asynchronously after Vcn notifies through VcnCallback
                notifyAllPermissionedStatusCallbacksLocked(
                        subscriptionGroup, VCN_STATUS_CODE_ACTIVE);
            }
        } else {
            startVcnLocked(subscriptionGroup, config);
        }
@@ -531,9 +563,17 @@ public class VcnManagementService extends IVcnManagementService.Stub {
        Binder.withCleanCallingIdentity(() -> {
            synchronized (mLock) {
                mConfigs.remove(subscriptionGroup);
                final boolean vcnExists = mVcns.containsKey(subscriptionGroup);

                stopVcnLocked(subscriptionGroup);

                if (vcnExists) {
                    // TODO(b/181789060): invoke asynchronously after Vcn notifies through
                    // VcnCallback
                    notifyAllPermissionedStatusCallbacksLocked(
                            subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED);
                }

                writeConfigsToDiskLocked();
            }
        });
@@ -857,16 +897,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                }

                notifyAllPolicyListenersLocked();

                // Notify all registered StatusCallbacks for this subGroup
                for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
                    if (isCallbackPermissioned(cbInfo, mSubGroup)) {
                        Binder.withCleanCallingIdentity(
                                () ->
                                        cbInfo.mCallback.onVcnStatusChanged(
                                                VCN_STATUS_CODE_SAFE_MODE));
                    }
                }
                notifyAllPermissionedStatusCallbacksLocked(mSubGroup, VCN_STATUS_CODE_SAFE_MODE);
            }
        }

+39 −0
Original line number Diff line number Diff line
@@ -460,6 +460,34 @@ public class VcnManagementServiceTest {
        verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
    }

    @Test
    public void testSetVcnConfigNotifiesStatusCallback() throws Exception {
        mVcnMgmtSvc.systemReady();
        doReturn(true)
                .when(mLocationPermissionChecker)
                .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any());
        triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2));

        mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED);

        // Use a different UUID to simulate a new VCN config.
        mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);

        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
    }

    @Test
    public void testSetVcnConfigInSafeModeNotifiesStatusCallback() throws Exception {
        setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */);
        mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);

        mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);

        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
    }

    @Test
    public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
        doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
@@ -502,6 +530,17 @@ public class VcnManagementServiceTest {
        verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
    }

    @Test
    public void testClearVcnConfigNotifiesStatusCallback() throws Exception {
        setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */);
        mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);

        mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2);

        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED);
    }

    @Test
    public void testSetVcnConfigClearVcnConfigStartsUpdatesAndTeardsDownVcns() throws Exception {
        // Use a different UUID to simulate a new VCN config.