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

Commit 3283a267 authored by Cody Kesting's avatar Cody Kesting Committed by Automerger Merge Worker
Browse files

Merge changes I0cadd145,I3be3cac4,I9ea6e9e8 am: 4ea84f0b

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1590414

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ia3f0b51482a8f71152380d2ecc747c9e66717e2c
parents f08e1215 4ea84f0b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -19,4 +19,9 @@ package android.net.vcn;
/** @hide */
interface IVcnStatusCallback {
    void onEnteredSafeMode();
    void onGatewayConnectionError(
            in int[] gatewayNetworkCapabilities,
            int errorCode,
            in String exceptionClass,
            in String exceptionMessage);
}
 No newline at end of file
+92 −2
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@ package android.net.vcn;

import static java.util.Objects.requireNonNull;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.content.Context;
@@ -32,6 +34,8 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -262,6 +266,42 @@ public class VcnManager {
        }
    }

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
        VCN_ERROR_CODE_INTERNAL_ERROR,
        VCN_ERROR_CODE_CONFIG_ERROR,
        VCN_ERROR_CODE_NETWORK_ERROR
    })
    public @interface VcnErrorCode {}

    /**
     * Value indicating that an internal failure occurred in this Gateway Connection.
     *
     * @hide
     */
    public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0;

    /**
     * Value indicating that an error with this Gateway Connection's configuration occurred.
     *
     * <p>For example, this error code will be returned after authentication failures.
     *
     * @hide
     */
    public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1;

    /**
     * Value indicating that a Network error occurred with this Gateway Connection.
     *
     * <p>For example, this error code will be returned if an underlying {@link android.net.Network}
     * for this Gateway Connection is lost, or if an error occurs while resolving the connection
     * endpoint address.
     *
     * @hide
     */
    public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2;

    // TODO: make VcnStatusCallback @SystemApi
    /**
     * VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs.
@@ -285,6 +325,24 @@ public class VcnManager {
         * via {@link #setVcnConfig(ParcelUuid, VcnConfig)}.
         */
        public abstract void onEnteredSafeMode();

        /**
         * Invoked when a VCN Gateway Connection corresponding to this callback's subscription
         * encounters an error.
         *
         * @param networkCapabilities an array of underlying NetworkCapabilities for the Gateway
         *     Connection that encountered the error for identification purposes. These will be a
         *     sorted list with no duplicates, matching one of the {@link
         *     VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
         *     group.
         * @param errorCode {@link VcnErrorCode} to indicate the error that occurred
         * @param detail Throwable to provide additional information about the error, or {@code
         *     null} if none
         */
        public abstract void onGatewayConnectionError(
                @NonNull int[] networkCapabilities,
                @VcnErrorCode int errorCode,
                @Nullable Throwable detail);
    }

    /**
@@ -385,11 +443,12 @@ public class VcnManager {
     *
     * @hide
     */
    private class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    public static class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
        @NonNull private final Executor mExecutor;
        @NonNull private final VcnStatusCallback mCallback;

        private VcnStatusCallbackBinder(
        public VcnStatusCallbackBinder(
                @NonNull Executor executor, @NonNull VcnStatusCallback callback) {
            mExecutor = executor;
            mCallback = callback;
@@ -400,5 +459,36 @@ public class VcnManager {
            Binder.withCleanCallingIdentity(
                    () -> mExecutor.execute(() -> mCallback.onEnteredSafeMode()));
        }

        // TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
        @Override
        public void onGatewayConnectionError(
                @NonNull int[] networkCapabilities,
                @VcnErrorCode int errorCode,
                @Nullable String exceptionClass,
                @Nullable String exceptionMessage) {
            final Throwable cause = createThrowableByClassName(exceptionClass, exceptionMessage);

            Binder.withCleanCallingIdentity(
                    () ->
                            mExecutor.execute(
                                    () ->
                                            mCallback.onGatewayConnectionError(
                                                    networkCapabilities, errorCode, cause)));
        }

        private static Throwable createThrowableByClassName(
                @Nullable String className, @Nullable String message) {
            if (className == null) {
                return null;
            }

            try {
                Class<?> c = Class.forName(className);
                return (Throwable) c.getConstructor(String.class).newInstance(message);
            } catch (ReflectiveOperationException | ClassCastException e) {
                return new RuntimeException(className + ": " + message);
            }
        }
    }
}
+64 −25
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnManager.VcnErrorCode;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.net.wifi.WifiInfo;
import android.os.Binder;
@@ -304,8 +305,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                @NonNull ParcelUuid subscriptionGroup,
                @NonNull VcnConfig config,
                @NonNull TelephonySubscriptionSnapshot snapshot,
                @NonNull VcnSafeModeCallback safeModeCallback) {
            return new Vcn(vcnContext, subscriptionGroup, config, snapshot, safeModeCallback);
                @NonNull VcnCallback vcnCallback) {
            return new Vcn(vcnContext, subscriptionGroup, config, snapshot, vcnCallback);
        }

        /** Gets the subId indicated by the given {@link WifiInfo}. */
@@ -457,12 +458,10 @@ public class VcnManagementService extends IVcnManagementService.Stub {
        // TODO(b/176939047): Support multiple VCNs active at the same time, or limit to one active
        //                    VCN.

        final VcnSafeModeCallbackImpl safeModeCallback =
                new VcnSafeModeCallbackImpl(subscriptionGroup);
        final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup);

        final Vcn newInstance =
                mDeps.newVcn(
                        mVcnContext, subscriptionGroup, config, mLastSnapshot, safeModeCallback);
                mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback);
        mVcns.put(subscriptionGroup, newInstance);

        // Now that a new VCN has started, notify all registered listeners to refresh their
@@ -784,20 +783,47 @@ public class VcnManagementService extends IVcnManagementService.Stub {
    }

    // TODO(b/180452282): Make name more generic and implement directly with VcnManagementService
    /** Callback for signalling when a Vcn has entered safe mode. */
    public interface VcnSafeModeCallback {
    /** Callback for Vcn signals sent up to VcnManagementService. */
    public interface VcnCallback {
        /** Called by a Vcn to signal that it has entered safe mode. */
        void onEnteredSafeMode();

        /** Called by a Vcn to signal that an error occurred. */
        void onGatewayConnectionError(
                @NonNull int[] networkCapabilities,
                @VcnErrorCode int errorCode,
                @Nullable String exceptionClass,
                @Nullable String exceptionMessage);
    }

    /** VcnSafeModeCallback is used by Vcns to notify VcnManagementService on entering safe mode. */
    private class VcnSafeModeCallbackImpl implements VcnSafeModeCallback {
    /** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */
    private class VcnCallbackImpl implements VcnCallback {
        @NonNull private final ParcelUuid mSubGroup;

        private VcnSafeModeCallbackImpl(@NonNull final ParcelUuid subGroup) {
        private VcnCallbackImpl(@NonNull final ParcelUuid subGroup) {
            mSubGroup = Objects.requireNonNull(subGroup, "Missing subGroup");
        }

        private boolean isCallbackPermissioned(@NonNull VcnStatusCallbackInfo cbInfo) {
            if (!mSubGroup.equals(cbInfo.mSubGroup)) {
                return false;
            }

            if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(
                    mSubGroup, cbInfo.mPkgName)) {
                return false;
            }

            if (!mLocationPermissionChecker.checkLocationPermission(
                    cbInfo.mPkgName,
                    "VcnStatusCallback" /* featureId */,
                    cbInfo.mUid,
                    null /* message */)) {
                return false;
            }
            return true;
        }

        @Override
        public void onEnteredSafeMode() {
            synchronized (mLock) {
@@ -810,23 +836,36 @@ public class VcnManagementService extends IVcnManagementService.Stub {

                // Notify all registered StatusCallbacks for this subGroup
                for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
                    if (!mSubGroup.equals(cbInfo.mSubGroup)) {
                        continue;
                    if (isCallbackPermissioned(cbInfo)) {
                        Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode());
                    }
                }
            }
                    if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(
                            mSubGroup, cbInfo.mPkgName)) {
                        continue;
        }

                    if (!mLocationPermissionChecker.checkLocationPermission(
                            cbInfo.mPkgName,
                            "VcnStatusCallback" /* featureId */,
                            cbInfo.mUid,
                            null /* message */)) {
                        continue;
        @Override
        public void onGatewayConnectionError(
                @NonNull int[] networkCapabilities,
                @VcnErrorCode int errorCode,
                @Nullable String exceptionClass,
                @Nullable String exceptionMessage) {
            synchronized (mLock) {
                // Ignore if this subscription group doesn't exist anymore
                if (!mVcns.containsKey(mSubGroup)) {
                    return;
                }

                    Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode());
                // Notify all registered StatusCallbacks for this subGroup
                for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
                    if (isCallbackPermissioned(cbInfo)) {
                        Binder.withCleanCallingIdentity(
                                () ->
                                        cbInfo.mCallback.onGatewayConnectionError(
                                                networkCapabilities,
                                                errorCode,
                                                exceptionClass,
                                                exceptionMessage));
                    }
                }
            }
        }
+26 −14
Original line number Diff line number Diff line
@@ -19,10 +19,12 @@ package com.android.server.vcn;
import static com.android.server.VcnManagementService.VDBG;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnManager.VcnErrorCode;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
@@ -30,7 +32,7 @@ import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.server.VcnManagementService.VcnSafeModeCallback;
import com.android.server.VcnManagementService.VcnCallback;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;

import java.util.Collections;
@@ -97,7 +99,7 @@ public class Vcn extends Handler {
    @NonNull private final ParcelUuid mSubscriptionGroup;
    @NonNull private final Dependencies mDeps;
    @NonNull private final VcnNetworkRequestListener mRequestListener;
    @NonNull private final VcnSafeModeCallback mVcnSafeModeCallback;
    @NonNull private final VcnCallback mVcnCallback;

    @NonNull
    private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
@@ -125,14 +127,8 @@ public class Vcn extends Handler {
            @NonNull ParcelUuid subscriptionGroup,
            @NonNull VcnConfig config,
            @NonNull TelephonySubscriptionSnapshot snapshot,
            @NonNull VcnSafeModeCallback vcnSafeModeCallback) {
        this(
                vcnContext,
                subscriptionGroup,
                config,
                snapshot,
                vcnSafeModeCallback,
                new Dependencies());
            @NonNull VcnCallback vcnCallback) {
        this(vcnContext, subscriptionGroup, config, snapshot, vcnCallback, new Dependencies());
    }

    @VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -141,13 +137,12 @@ public class Vcn extends Handler {
            @NonNull ParcelUuid subscriptionGroup,
            @NonNull VcnConfig config,
            @NonNull TelephonySubscriptionSnapshot snapshot,
            @NonNull VcnSafeModeCallback vcnSafeModeCallback,
            @NonNull VcnCallback vcnCallback,
            @NonNull Dependencies deps) {
        super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
        mVcnContext = vcnContext;
        mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
        mVcnSafeModeCallback =
                Objects.requireNonNull(vcnSafeModeCallback, "Missing vcnSafeModeCallback");
        mVcnCallback = Objects.requireNonNull(vcnCallback, "Missing vcnCallback");
        mDeps = Objects.requireNonNull(deps, "Missing deps");
        mRequestListener = new VcnNetworkRequestListener();

@@ -246,7 +241,7 @@ public class Vcn extends Handler {
    private void handleEnterSafeMode() {
        handleTeardown();

        mVcnSafeModeCallback.onEnteredSafeMode();
        mVcnCallback.onEnteredSafeMode();
    }

    private void handleNetworkRequested(
@@ -337,6 +332,13 @@ public class Vcn extends Handler {
    public interface VcnGatewayStatusCallback {
        /** Called by a VcnGatewayConnection to indicate that it has entered safe mode. */
        void onEnteredSafeMode();

        /** Callback by a VcnGatewayConnection to indicate that an error occurred. */
        void onGatewayConnectionError(
                @NonNull int[] networkCapabilities,
                @VcnErrorCode int errorCode,
                @Nullable String exceptionClass,
                @Nullable String exceptionMessage);
    }

    private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
@@ -344,6 +346,16 @@ public class Vcn extends Handler {
        public void onEnteredSafeMode() {
            sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
        }

        @Override
        public void onGatewayConnectionError(
                @NonNull int[] networkCapabilities,
                @VcnErrorCode int errorCode,
                @Nullable String exceptionClass,
                @Nullable String exceptionMessage) {
            mVcnCallback.onGatewayConnectionError(
                    networkCapabilities, errorCode, exceptionClass, exceptionMessage);
        }
    }

    /** External dependencies used by Vcn, for injection in tests */
+65 −4
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;

import static com.android.server.VcnManagementService.VDBG;

@@ -52,7 +55,9 @@ import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionConfiguration;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnTransportInfo;
@@ -951,15 +956,68 @@ public class VcnGatewayConnection extends StateMachine {
        removeEqualMessages(EVENT_SAFE_MODE_TIMEOUT_EXCEEDED);
    }

    private void sessionLost(int token, @Nullable Exception exception) {
    private void sessionLostWithoutCallback(int token, @Nullable Exception exception) {
        sendMessageAndAcquireWakeLock(
                EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
    }

    private void sessionLost(int token, @Nullable Exception exception) {
        // Only notify mGatewayStatusCallback if the session was lost with an error. All
        // authentication and DNS failures are sent through
        // IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed()
        if (exception != null) {
            mGatewayStatusCallback.onGatewayConnectionError(
                    mConnectionConfig.getRequiredUnderlyingCapabilities(),
                    VCN_ERROR_CODE_INTERNAL_ERROR,
                    "java.lang.RuntimeException",
                    "Received "
                            + exception.getClass().getSimpleName()
                            + " with message: "
                            + exception.getMessage());
        }

        sessionLostWithoutCallback(token, exception);
    }

    private void notifyStatusCallbackForSessionClosed(@NonNull Exception exception) {
        final int errorCode;
        final String exceptionClass;
        final String exceptionMessage;

        if (exception instanceof AuthenticationFailedException) {
            errorCode = VCN_ERROR_CODE_CONFIG_ERROR;
            exceptionClass = exception.getClass().getName();
            exceptionMessage = exception.getMessage();
        } else if (exception instanceof IkeInternalException
                && exception.getCause() instanceof IOException) {
            errorCode = VCN_ERROR_CODE_NETWORK_ERROR;
            exceptionClass = "java.io.IOException";
            exceptionMessage = exception.getCause().getMessage();
        } else {
            errorCode = VCN_ERROR_CODE_INTERNAL_ERROR;
            exceptionClass = "java.lang.RuntimeException";
            exceptionMessage =
                    "Received "
                            + exception.getClass().getSimpleName()
                            + " with message: "
                            + exception.getMessage();
        }

        mGatewayStatusCallback.onGatewayConnectionError(
                mConnectionConfig.getRequiredUnderlyingCapabilities(),
                errorCode,
                exceptionClass,
                exceptionMessage);
    }

    private void sessionClosed(int token, @Nullable Exception exception) {
        if (exception != null) {
            notifyStatusCallbackForSessionClosed(exception);
        }

        // SESSION_LOST MUST be sent before SESSION_CLOSED to ensure that the SM moves to the
        // Disconnecting state.
        sessionLost(token, exception);
        sessionLostWithoutCallback(token, exception);
        sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, token);
    }

@@ -1084,6 +1142,8 @@ public class VcnGatewayConnection extends StateMachine {
        }

        protected void handleDisconnectRequested(String msg) {
            // TODO(b/180526152): notify VcnStatusCallback for Network loss

            Slog.v(TAG, "Tearing down. Cause: " + msg);
            mIsRunning = false;

@@ -1228,6 +1288,8 @@ public class VcnGatewayConnection extends StateMachine {

                    String reason = ((EventDisconnectRequestedInfo) msg.obj).reason;
                    if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) {
                        // TODO(b/180526152): notify VcnStatusCallback for Network loss

                        // Will trigger EVENT_SESSION_CLOSED immediately.
                        mIkeSession.kill();
                        break;
@@ -1573,8 +1635,7 @@ public class VcnGatewayConnection extends StateMachine {

        @Override
        protected void exitState() {
            // Attempt to set the safe mode alarm - this requires the Vcn Network being validated
            // while in ConnectedState (which cancels the previous alarm)
            // Will only set a new alarm if no safe mode alarm is currently scheduled.
            setSafeModeAlarm();
        }
    }
Loading