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

Commit 053df0e7 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN
Browse files

Remove hidden preconditions, binder usage in Vpn

The hidden APIs cause problems when Vpn is used in connectivity tests,
as their package (com.android.internal.util for Preconditions and
ThrowingRunnable used by lambdas) gets jarjared by Connectivity, but the
utils are not actually statically linked into the tests.

Remove usage of the hidden utilities, which will also be useful if Vpn
needs to build against SDK in the near future.

Bug: 187935317
Test: atest ConnectivityCoverageTests:ConnectivityServiceTest
Change-Id: I6152f07e7e88a88c202d78f03e370173fdd9a016
parent a30c27e8
Loading
Loading
Loading
Loading
+65 −55
Original line number Diff line number Diff line
@@ -23,8 +23,7 @@ import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
import static android.os.UserHandle.PER_USER_RANGE;

import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static java.util.Objects.requireNonNull;

import android.Manifest;
import android.annotation.NonNull;
@@ -1096,13 +1095,14 @@ public class Vpn {
            return Process.myUid();
        }
        PackageManager pm = mContext.getPackageManager();
        return Binder.withCleanCallingIdentity(() -> {
        final long token = Binder.clearCallingIdentity();
        try {
            return pm.getPackageUidAsUser(app, userId);
        } catch (NameNotFoundException e) {
            return -1;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        });
    }

    private boolean doesPackageTargetAtLeastQ(String packageName) {
@@ -1278,15 +1278,16 @@ public class Vpn {
                // We are user controlled, not driven by NetworkRequest.
            }
        };
        Binder.withCleanCallingIdentity(() -> {
        final long token = Binder.clearCallingIdentity();
        try {
            mNetworkAgent.register();
        } catch (final Exception e) {
            // If register() throws, don't keep an unregistered agent.
            mNetworkAgent = null;
            throw e;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        });
        mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null)
                ? Arrays.asList(mConfig.underlyingNetworks) : null);
        updateState(DetailedState.CONNECTED, "agentConnect");
@@ -2024,13 +2025,16 @@ public class Vpn {
    }

    private void enforceNotRestrictedUser() {
        Binder.withCleanCallingIdentity(() -> {
        final long token = Binder.clearCallingIdentity();
        try {
            final UserInfo user = mUserManager.getUserInfo(mUserId);

            if (user.isRestricted()) {
                throw new SecurityException("Restricted users cannot configure VPNs");
            }
        });
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    /**
@@ -2823,8 +2827,10 @@ public class Vpn {

        LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) {
            super(TAG);
            checkArgument(racoon != null || mtpd != null, "Arguments to racoon and mtpd "
                    + "must not both be null");
            if (racoon == null && mtpd == null) {
                throw new IllegalArgumentException(
                        "Arguments to racoon and mtpd must not both be null");
            }
            mConfig = config;
            mDaemons = new String[] {"racoon", "mtpd"};
            // TODO: clear arguments from memory once launched
@@ -3149,8 +3155,8 @@ public class Vpn {
     */
    public synchronized boolean provisionVpnProfile(
            @NonNull String packageName, @NonNull VpnProfile profile) {
        checkNotNull(packageName, "No package name provided");
        checkNotNull(profile, "No profile provided");
        requireNonNull(packageName, "No package name provided");
        requireNonNull(profile, "No profile provided");

        verifyCallingUidAndPackage(packageName);
        enforceNotRestrictedUser();
@@ -3167,12 +3173,12 @@ public class Vpn {
        }

        // Permissions checked during startVpnProfile()
        Binder.withCleanCallingIdentity(
                () -> {
                    getVpnProfileStore().put(
                            getProfileNameForPackage(packageName),
                            encodedProfile);
                });
        final long token = Binder.clearCallingIdentity();
        try {
            getVpnProfileStore().put(getProfileNameForPackage(packageName), encodedProfile);
        } finally {
            Binder.restoreCallingIdentity(token);
        }

        // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop.
        // This mirrors the prepareAndAuthorize that is used by VpnService.
@@ -3192,13 +3198,13 @@ public class Vpn {
     */
    public synchronized void deleteVpnProfile(
            @NonNull String packageName) {
        checkNotNull(packageName, "No package name provided");
        requireNonNull(packageName, "No package name provided");

        verifyCallingUidAndPackage(packageName);
        enforceNotRestrictedUser();

        Binder.withCleanCallingIdentity(
                () -> {
        final long token = Binder.clearCallingIdentity();
        try {
            // If this profile is providing the current VPN, turn it off, disabling
            // always-on as well if enabled.
            if (isCurrentIkev2VpnLocked(packageName)) {
@@ -3211,7 +3217,9 @@ public class Vpn {
            }

            getVpnProfileStore().remove(getProfileNameForPackage(packageName));
                });
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    /**
@@ -3245,7 +3253,7 @@ public class Vpn {
     */
    public synchronized void startVpnProfile(
            @NonNull String packageName) {
        checkNotNull(packageName, "No package name provided");
        requireNonNull(packageName, "No package name provided");

        enforceNotRestrictedUser();

@@ -3254,15 +3262,17 @@ public class Vpn {
            throw new SecurityException("User consent not granted for package " + packageName);
        }

        Binder.withCleanCallingIdentity(
                () -> {
        final long token = Binder.clearCallingIdentity();
        try {
            final VpnProfile profile = getVpnProfilePrivileged(packageName);
            if (profile == null) {
                throw new IllegalArgumentException("No profile found for " + packageName);
            }

            startVpnProfilePrivileged(profile, packageName);
                });
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private synchronized void startVpnProfilePrivileged(
@@ -3323,7 +3333,7 @@ public class Vpn {
     * @param packageName the package name of the app provisioning this profile
     */
    public synchronized void stopVpnProfile(@NonNull String packageName) {
        checkNotNull(packageName, "No package name provided");
        requireNonNull(packageName, "No package name provided");

        enforceNotRestrictedUser();