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

Commit be331ab3 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Gerrit Code Review
Browse files

Merge changes I4256ca5f,I91528e1a,I48bd594c

* changes:
  Change ConnectivityServiceTest to prepare for VPN code move.
  Add to VpnManager the VPN APIs used by Settings and SystemUI.
  Remove temporary hack in VpnTest.
parents 385f58bf 9ce4107f
Loading
Loading
Loading
Loading
+104 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
@@ -28,6 +29,8 @@ import android.content.Intent;
import android.content.res.Resources;
import android.os.RemoteException;

import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;

import java.io.IOException;
@@ -161,4 +164,104 @@ public class VpnManager {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the VPN configuration for the given user ID.
     * @hide
     */
    @Nullable
    public VpnConfig getVpnConfig(@UserIdInt int userId) {
        try {
            return mService.getVpnConfig(userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Prepare for a VPN application.
     * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
     * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
     *
     * @param oldPackage Package name of the application which currently controls VPN, which will
     *                   be replaced. If there is no such application, this should should either be
     *                   {@code null} or {@link VpnConfig.LEGACY_VPN}.
     * @param newPackage Package name of the application which should gain control of VPN, or
     *                   {@code null} to disable.
     * @param userId User for whom to prepare the new VPN.
     *
     * @hide
     */
    public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
            int userId) {
        try {
            return mService.prepareVpn(oldPackage, newPackage, userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set whether the VPN package has the ability to launch VPNs without user intervention. This
     * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn}
     * class. If the caller is not {@code userId}, {@link
     * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
     *
     * @param packageName The package for which authorization state should change.
     * @param userId User for whom {@code packageName} is installed.
     * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN
     *     permissions should be granted. When unauthorizing an app, {@link
     *     VpnManager.TYPE_VPN_NONE} should be used.
     * @hide
     */
    public void setVpnPackageAuthorization(
            String packageName, int userId, @VpnManager.VpnType int vpnType) {
        try {
            mService.setVpnPackageAuthorization(packageName, userId, vpnType);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the legacy VPN information for the specified user ID.
     * @hide
     */
    public LegacyVpnInfo getLegacyVpnInfo(@UserIdInt int userId) {
        try {
            return mService.getLegacyVpnInfo(userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Starts a legacy VPN.
     * @hide
     */
    public void startLegacyVpn(VpnProfile profile) {
        try {
            mService.startLegacyVpn(profile);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Informs the service that legacy lockdown VPN state should be updated (e.g., if its keystore
     * entry has been updated). If the LockdownVpn mechanism is enabled, updates the vpn
     * with a reload of its profile.
     *
     * <p>This method can only be called by the system UID
     * @return a boolean indicating success
     *
     * @hide
     */
    public boolean updateLockdownVpn() {
        try {
            return mService.updateLockdownVpn();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
 No newline at end of file
+37 −37
Original line number Diff line number Diff line
@@ -1263,6 +1263,13 @@ public class ConnectivityServiceTest {
        }
    }

    private void processBroadcastForVpn(Intent intent) {
        // The BroadcastReceiver for this broadcast checks it is being run on the handler thread.
        final Handler handler = new Handler(mCsHandlerThread.getLooper());
        handler.post(() -> mServiceContext.sendBroadcast(intent));
        waitForIdle();
    }

    private void mockUidNetworkingBlocked() {
        doAnswer(i -> mContext.getSystemService(NetworkPolicyManager.class)
                .checkUidNetworkingBlocked(i.getArgument(0) /* uid */, mUidRules,
@@ -5405,20 +5412,20 @@ public class ConnectivityServiceTest {
        // MOBILE_IFNAME even though the default network is wifi.
        // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
        // applies to the system server UID should not have any bearing on network stats.
        mService.setUnderlyingNetworksForVpn(onlyCell);
        mMockVpn.setUnderlyingNetworks(onlyCell);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
                new String[]{MOBILE_IFNAME});
        reset(mStatsService);

        mService.setUnderlyingNetworksForVpn(cellAndWifi);
        mMockVpn.setUnderlyingNetworks(cellAndWifi);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
                new String[]{MOBILE_IFNAME, WIFI_IFNAME});
        reset(mStatsService);

        // Null underlying networks are ignored.
        mService.setUnderlyingNetworksForVpn(cellNullAndWifi);
        mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
                new String[]{MOBILE_IFNAME, WIFI_IFNAME});
@@ -5467,25 +5474,25 @@ public class ConnectivityServiceTest {
        // is probably a performance improvement (though it's very unlikely that a VPN would declare
        // no underlying networks).
        // Also, for the same reason as above, the active interface passed in is null.
        mService.setUnderlyingNetworksForVpn(new Network[0]);
        mMockVpn.setUnderlyingNetworks(new Network[0]);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, null);
        reset(mStatsService);

        // Specifying only a null underlying network is the same as no networks.
        mService.setUnderlyingNetworksForVpn(onlyNull);
        mMockVpn.setUnderlyingNetworks(onlyNull);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, null);
        reset(mStatsService);

        // Specifying networks that are all disconnected is the same as specifying no networks.
        mService.setUnderlyingNetworksForVpn(onlyCell);
        mMockVpn.setUnderlyingNetworks(onlyCell);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, null);
        reset(mStatsService);

        // Passing in null again means follow the default network again.
        mService.setUnderlyingNetworksForVpn(null);
        mMockVpn.setUnderlyingNetworks(null);
        waitForIdle();
        expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
                new String[]{WIFI_IFNAME});
@@ -5960,7 +5967,7 @@ public class ConnectivityServiceTest {
        mMockVpn.establishForMyUid(false, true, false);
        assertUidRangesUpdatedForMyUid(true);
        final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
        mService.setUnderlyingNetworksForVpn(new Network[]{wifiNetwork});
        mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
        callback.expectAvailableCallbacksUnvalidated(mMockVpn);
        assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
                .hasTransport(TRANSPORT_VPN));
@@ -6154,7 +6161,7 @@ public class ConnectivityServiceTest {

        final Set<UidRange> ranges = uidRangesForUid(uid);
        mMockVpn.registerAgent(ranges);
        mService.setUnderlyingNetworksForVpn(new Network[0]);
        mMockVpn.setUnderlyingNetworks(new Network[0]);

        // VPN networks do not satisfy the default request and are automatically validated
        // by NetworkMonitor
@@ -6402,7 +6409,7 @@ public class ConnectivityServiceTest {
        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
        mCellNetworkAgent.connect(true);

        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork() });

        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
@@ -6417,7 +6424,7 @@ public class ConnectivityServiceTest {
        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
        mWiFiNetworkAgent.connect(true);

        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });

        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
@@ -6428,7 +6435,7 @@ public class ConnectivityServiceTest {
        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);

        // Don't disconnect, but note the VPN is not using wifi any more.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork() });

        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
@@ -6459,7 +6466,7 @@ public class ConnectivityServiceTest {
        vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);

        // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mWiFiNetworkAgent.getNetwork() });

        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
@@ -6470,7 +6477,7 @@ public class ConnectivityServiceTest {
        assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);

        // Use both again.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });

        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
@@ -6485,7 +6492,7 @@ public class ConnectivityServiceTest {
        vpnNetworkCallback.assertNoCallback();

        // Stop using WiFi. The VPN is suspended again.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork() });
        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
                (caps) -> caps.hasTransport(TRANSPORT_VPN)
@@ -6496,7 +6503,7 @@ public class ConnectivityServiceTest {
        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);

        // Use both again.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });

        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
@@ -6631,9 +6638,7 @@ public class ConnectivityServiceTest {
        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);

        // Send a USER_ADDED broadcast for it.
        // The BroadcastReceiver for this broadcast checks that is being run on the handler thread.
        final Handler handler = new Handler(mCsHandlerThread.getLooper());
        handler.post(() -> mServiceContext.sendBroadcast(addedIntent));
        processBroadcastForVpn(addedIntent);

        // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
        // restricted user.
@@ -6657,7 +6662,7 @@ public class ConnectivityServiceTest {
        // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
        final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
        removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
        handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
        processBroadcastForVpn(removedIntent);

        // Expect that the VPN gains the UID range for the restricted user, and that the capability
        // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
@@ -6714,9 +6719,7 @@ public class ConnectivityServiceTest {
        // TODO: check that VPN app within restricted profile still has access, etc.
        final Intent addedIntent = new Intent(ACTION_USER_ADDED);
        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
        final Handler handler = new Handler(mCsHandlerThread.getLooper());
        handler.post(() -> mServiceContext.sendBroadcast(addedIntent));
        waitForIdle();
        processBroadcastForVpn(addedIntent);
        assertNull(mCm.getActiveNetworkForUid(uid));
        assertNull(mCm.getActiveNetworkForUid(restrictedUid));

@@ -6726,8 +6729,7 @@ public class ConnectivityServiceTest {
        // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
        final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
        removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
        handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
        waitForIdle();
        processBroadcastForVpn(removedIntent);
        assertNull(mCm.getActiveNetworkForUid(uid));
        assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));

@@ -6829,7 +6831,7 @@ public class ConnectivityServiceTest {
        // Ensure VPN is now the active network.
        assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
        // VPN is using Cell
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork() });
        waitForIdle();

@@ -6837,7 +6839,7 @@ public class ConnectivityServiceTest {
        assertTrue(mCm.isActiveNetworkMetered());

        // VPN is now using WiFi
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mWiFiNetworkAgent.getNetwork() });
        waitForIdle();

@@ -6845,7 +6847,7 @@ public class ConnectivityServiceTest {
        assertFalse(mCm.isActiveNetworkMetered());

        // VPN is using Cell | WiFi.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
        waitForIdle();

@@ -6853,7 +6855,7 @@ public class ConnectivityServiceTest {
        assertTrue(mCm.isActiveNetworkMetered());

        // VPN is using WiFi | Cell.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
        waitForIdle();

@@ -6861,7 +6863,7 @@ public class ConnectivityServiceTest {
        assertTrue(mCm.isActiveNetworkMetered());

        // VPN is not using any underlying networks.
        mService.setUnderlyingNetworksForVpn(new Network[0]);
        mMockVpn.setUnderlyingNetworks(new Network[0]);
        waitForIdle();

        // VPN without underlying networks is treated as metered.
@@ -6888,7 +6890,7 @@ public class ConnectivityServiceTest {
        assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());

        // VPN is tracking current platform default (WiFi).
        mService.setUnderlyingNetworksForVpn(null);
        mMockVpn.setUnderlyingNetworks(null);
        waitForIdle();

        // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
@@ -6896,7 +6898,7 @@ public class ConnectivityServiceTest {


        // VPN explicitly declares WiFi as its underlying network.
        mService.setUnderlyingNetworksForVpn(
        mMockVpn.setUnderlyingNetworks(
                new Network[] { mWiFiNetworkAgent.getNetwork() });
        waitForIdle();

@@ -7304,9 +7306,7 @@ public class ConnectivityServiceTest {
        final int userId = UserHandle.getUserId(Process.myUid());
        final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED);
        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
        final Handler handler = new Handler(mCsHandlerThread.getLooper());
        handler.post(() -> mServiceContext.sendBroadcast(addedIntent));
        waitForIdle();
        processBroadcastForVpn(addedIntent);

        // Lockdown VPN disables teardown and enables lockdown.
        assertFalse(mMockVpn.getEnableTeardown());
@@ -8748,7 +8748,7 @@ public class ConnectivityServiceTest {
        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION);

        assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {naiWithoutUid.network}));
        assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network}));
        waitForIdle();
        assertTrue(
                "Active VPN permission not applied",
@@ -8756,7 +8756,7 @@ public class ConnectivityServiceTest {
                        Process.myPid(), Process.myUid(), naiWithoutUid,
                        mContext.getOpPackageName()));

        assertTrue(mService.setUnderlyingNetworksForVpn(null));
        assertTrue(mMockVpn.setUnderlyingNetworks(null));
        waitForIdle();
        assertFalse(
                "VPN shouldn't receive callback on non-underlying network",
+1 −12
Original line number Diff line number Diff line
@@ -953,14 +953,7 @@ public class VpnTest {
    }

    private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception {
        // TODO(b/175883995): once these tests have been updated for the changes to the UserManager
        // API, remove this ad-hoc setup code and use setMockedUsers(primaryUser) again.
        // setMockedUsers(primaryUser);
        final ArrayList<UserInfo> users = new ArrayList<>();
        users.add(primaryUser);
        when(mUserManager.getAliveUsers()).thenReturn(users);
        when(mUserManager.getUserInfo(primaryUser.id)).thenReturn(primaryUser);
        when(mUserManager.canHaveRestrictedProfile()).thenReturn(false);
        setMockedUsers(primaryUser);

        // Dummy egress interface
        final LinkProperties lp = new LinkProperties();
@@ -1159,10 +1152,6 @@ public class VpnTest {
        doReturn(UserHandle.of(userId)).when(asUserContext).getUser();
        when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
                .thenReturn(asUserContext);
        when(asUserContext.getSystemServiceName(UserManager.class))
                .thenReturn(Context.USER_SERVICE);
        when(asUserContext.getSystemService(UserManager.class))
                .thenReturn(mUserManager);
        final TestLooper testLooper = new TestLooper();
        final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
                mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator);