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

Commit 901dc86e authored by Cody Kesting's avatar Cody Kesting
Browse files

Define VcnNetworkPolicyListener for VCN transports.

This CL defines VcnNetworkPolicyListener and VCN Network policy
functions for VcnManager. Specifically, VcnNetworkPolicyListeners should
be added and removed by Network factories as they bring up and teardown
data Networks.

VcnNetworkPolicyListeners are used by VcnManagementService to notify
transports when they should re-query for their updated
VcnNetworkPolicyResults - done via VcnManager#applyVcnNetworkPolicy.
Policy results inform transports what the current NetworkCapabilities
are based on their VCN policy, and also whether the transport should
teardown and restart.

Bug: 177020190
Test: atest FrameworksVcnTests
Change-Id: Ide2c73025f4ffceabf7955f219a79be5a9bdc0d9
parent 35575305
Loading
Loading
Loading
Loading
+103 −38
Original line number Diff line number Diff line
@@ -72,8 +72,7 @@ import java.util.concurrent.Executor;
public class VcnManager {
    @NonNull private static final String TAG = VcnManager.class.getSimpleName();

    private static final Map<
                    VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
    private static final Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
            REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();

    @NonNull private final Context mContext;
@@ -93,13 +92,13 @@ public class VcnManager {
    }

    /**
     * Get all currently registered VcnUnderlyingNetworkPolicyListeners for testing purposes.
     * Get all currently registered VcnNetworkPolicyListeners for testing purposes.
     *
     * @hide
     */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    @NonNull
    public static Map<VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
    public static Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
            getAllPolicyListeners() {
        return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS);
    }
@@ -161,45 +160,115 @@ public class VcnManager {
        }
    }

    // TODO: make VcnUnderlyingNetworkPolicyListener @SystemApi
    // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using
    // the new VcnNetworkPolicyListener API
    /**
     * VcnUnderlyingNetworkPolicyListener is the interface through which internal system components
     * can register to receive updates for VCN-underlying Network policies from the System Server.
     *
     * @hide
     */
    public interface VcnUnderlyingNetworkPolicyListener {
    public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyListener {}

    /**
     * Add a listener for VCN-underlying network policy updates.
     *
     * @param executor the Executor that will be used for invoking all calls to the specified
     *     Listener
     * @param listener the VcnUnderlyingNetworkPolicyListener to be added
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @throws IllegalStateException if the specified VcnUnderlyingNetworkPolicyListener is already
     *     registered
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public void addVcnUnderlyingNetworkPolicyListener(
            @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) {
        addVcnNetworkPolicyListener(executor, listener);
    }

    /**
     * Remove the specified VcnUnderlyingNetworkPolicyListener from VcnManager.
     *
     * <p>If the specified listener is not currently registered, this is a no-op.
     *
     * @param listener the VcnUnderlyingNetworkPolicyListener that will be removed
     * @hide
     */
    public void removeVcnUnderlyingNetworkPolicyListener(
            @NonNull VcnUnderlyingNetworkPolicyListener listener) {
        removeVcnNetworkPolicyListener(listener);
    }

    /**
     * Queries the underlying network policy for a network with the given parameters.
     *
     * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
     * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network
     * Provider MUST poll for the updated Network policy based on that Network's capabilities and
     * properties.
     *
     * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
     *     policy for this Network.
     * @param linkProperties the LinkProperties to be used in determining the Network policy for
     *     this Network.
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @return the VcnUnderlyingNetworkPolicy to be used for this Network.
     * @hide
     */
    @NonNull
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
            @NonNull NetworkCapabilities networkCapabilities,
            @NonNull LinkProperties linkProperties) {
        requireNonNull(networkCapabilities, "networkCapabilities must not be null");
        requireNonNull(linkProperties, "linkProperties must not be null");

        try {
            return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    // TODO: make VcnNetworkPolicyListener @SystemApi
    /**
     * VcnNetworkPolicyListener is the interface through which internal system components can
     * register to receive updates for VCN-underlying Network policies from the System Server.
     *
     * @hide
     */
    public interface VcnNetworkPolicyListener {
        /**
         * Notifies the implementation that the VCN's underlying Network policy has changed.
         *
         * <p>After receiving this callback, implementations MUST poll VcnManager for the updated
         * VcnUnderlyingNetworkPolicy via VcnManager#getUnderlyingNetworkPolicy.
         * <p>After receiving this callback, implementations should get the current {@link
         * VcnNetworkPolicyResult} via {@link #applyVcnNetworkPolicy(NetworkCapabilities,
         * LinkProperties)}.
         */
        void onPolicyChanged();
    }

    /**
     * Add a listener for VCN-underlying network policy updates.
     * Add a listener for VCN-underlying Network policy updates.
     *
     * @param executor the Executor that will be used for invoking all calls to the specified
     *     Listener
     * @param listener the VcnUnderlyingNetworkPolicyListener to be added
     * @param listener the VcnNetworkPolicyListener to be added
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @throws IllegalArgumentException if the specified VcnUnderlyingNetworkPolicyListener is
     *     already registered
     * @throws IllegalStateException if the specified VcnNetworkPolicyListener is already registered
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public void addVcnUnderlyingNetworkPolicyListener(
            @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) {
    public void addVcnNetworkPolicyListener(
            @NonNull Executor executor, @NonNull VcnNetworkPolicyListener listener) {
        requireNonNull(executor, "executor must not be null");
        requireNonNull(listener, "listener must not be null");

        VcnUnderlyingNetworkPolicyListenerBinder binder =
                new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener);
        if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) {
            throw new IllegalArgumentException(
                    "Attempting to add a listener that is already in use");
            throw new IllegalStateException("listener is already registered with VcnManager");
        }

        try {
@@ -211,15 +280,14 @@ public class VcnManager {
    }

    /**
     * Remove the specified VcnUnderlyingNetworkPolicyListener from VcnManager.
     * Remove the specified VcnNetworkPolicyListener from VcnManager.
     *
     * <p>If the specified listener is not currently registered, this is a no-op.
     *
     * @param listener the VcnUnderlyingNetworkPolicyListener that will be removed
     * @param listener the VcnNetworkPolicyListener that will be removed
     * @hide
     */
    public void removeVcnUnderlyingNetworkPolicyListener(
            @NonNull VcnUnderlyingNetworkPolicyListener listener) {
    public void removeVcnNetworkPolicyListener(@NonNull VcnNetworkPolicyListener listener) {
        requireNonNull(listener, "listener must not be null");

        VcnUnderlyingNetworkPolicyListenerBinder binder =
@@ -236,34 +304,32 @@ public class VcnManager {
    }

    /**
     * Queries the underlying network policy for a network with the given parameters.
     * Applies the network policy for a {@link android.net.Network} with the given parameters.
     *
     * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
     * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network
     * Provider MUST poll for the updated Network policy based on that Network's capabilities and
     * properties.
     * may have changed via {@link VcnNetworkPolicyListener#onPolicyChanged()}, a Network Provider
     * MUST poll for the updated Network policy based on that Network's capabilities and properties.
     *
     * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
     *     policy for this Network.
     * @param linkProperties the LinkProperties to be used in determining the Network policy for
     *     this Network.
     *     policy result for this Network.
     * @param linkProperties the LinkProperties to be used in determining the Network policy result
     *     for this Network.
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @return the VcnUnderlyingNetworkPolicy to be used for this Network.
     * @return the {@link VcnNetworkPolicyResult} to be used for this Network.
     * @hide
     */
    @NonNull
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
    public VcnNetworkPolicyResult applyVcnNetworkPolicy(
            @NonNull NetworkCapabilities networkCapabilities,
            @NonNull LinkProperties linkProperties) {
        requireNonNull(networkCapabilities, "networkCapabilities must not be null");
        requireNonNull(linkProperties, "linkProperties must not be null");

        try {
            return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        final VcnUnderlyingNetworkPolicy policy =
                getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
        return new VcnNetworkPolicyResult(
                policy.isTeardownRequested(), policy.getMergedNetworkCapabilities());
    }

    /** @hide */
@@ -415,18 +481,17 @@ public class VcnManager {
    }

    /**
     * Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System
     * Server.
     * Binder wrapper for added VcnNetworkPolicyListeners to receive signals from System Server.
     *
     * @hide
     */
    private static class VcnUnderlyingNetworkPolicyListenerBinder
            extends IVcnUnderlyingNetworkPolicyListener.Stub {
        @NonNull private final Executor mExecutor;
        @NonNull private final VcnUnderlyingNetworkPolicyListener mListener;
        @NonNull private final VcnNetworkPolicyListener mListener;

        private VcnUnderlyingNetworkPolicyListenerBinder(
                Executor executor, VcnUnderlyingNetworkPolicyListener listener) {
                Executor executor, VcnNetworkPolicyListener listener) {
            mExecutor = executor;
            mListener = listener;
        }
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.vcn;

/** @hide */
parcelable VcnNetworkPolicyResult;
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.vcn;

import android.annotation.NonNull;
import android.net.NetworkCapabilities;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * VcnNetworkPolicyResult represents the Network policy result for a Network transport applying its
 * VCN policy via {@link VcnManager#applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
 *
 * <p>Transports that are bringing up networks capable of acting as a VCN's underlying network
 * should query for policy state upon any capability changes (e.g. changing of TRUSTED bit), and
 * when prompted by VcnManagementService via VcnNetworkPolicyListener.
 *
 * @hide
 */
public final class VcnNetworkPolicyResult implements Parcelable {
    private final boolean mIsTearDownRequested;
    private final NetworkCapabilities mNetworkCapabilities;

    /**
     * Constructs a VcnNetworkPolicyResult with the specified parameters.
     *
     * @hide
     */
    public VcnNetworkPolicyResult(
            boolean isTearDownRequested, @NonNull NetworkCapabilities networkCapabilities) {
        Objects.requireNonNull(networkCapabilities, "networkCapabilities must be non-null");

        mIsTearDownRequested = isTearDownRequested;
        mNetworkCapabilities = networkCapabilities;
    }

    /**
     * Returns whether this Carrier VCN policy policy result requires that the underlying Network
     * should be torn down.
     */
    public boolean isTeardownRequested() {
        return mIsTearDownRequested;
    }

    /**
     * Returns the NetworkCapabilities with Carrier VCN policy bits applied to the provided
     * capabilities.
     */
    @NonNull
    public NetworkCapabilities getNetworkCapabilities() {
        return mNetworkCapabilities;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mIsTearDownRequested, mNetworkCapabilities);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof VcnNetworkPolicyResult)) return false;
        final VcnNetworkPolicyResult that = (VcnNetworkPolicyResult) o;

        return mIsTearDownRequested == that.mIsTearDownRequested
                && mNetworkCapabilities.equals(that.mNetworkCapabilities);
    }

    /** {@inheritDoc} */
    @Override
    public int describeContents() {
        return 0;
    }

    /** {@inheritDoc} */
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeBoolean(mIsTearDownRequested);
        dest.writeParcelable(mNetworkCapabilities, flags);
    }

    /** Implement the Parcelable interface */
    public static final @NonNull Creator<VcnNetworkPolicyResult> CREATOR =
            new Creator<VcnNetworkPolicyResult>() {
                public VcnNetworkPolicyResult createFromParcel(Parcel in) {
                    return new VcnNetworkPolicyResult(in.readBoolean(), in.readParcelable(null));
                }

                public VcnNetworkPolicyResult[] newArray(int size) {
                    return new VcnNetworkPolicyResult[size];
                }
            };
}
+14 −13
Original line number Diff line number Diff line
@@ -33,8 +33,7 @@ import java.util.Objects;
 * @hide
 */
public final class VcnUnderlyingNetworkPolicy implements Parcelable {
    private final boolean mIsTearDownRequested;
    private final NetworkCapabilities mMergedNetworkCapabilities;
    private final VcnNetworkPolicyResult mVcnNetworkPolicyResult;

    /**
     * Constructs a VcnUnderlyingNetworkPolicy with the specified parameters.
@@ -46,8 +45,13 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable {
        Objects.requireNonNull(
                mergedNetworkCapabilities, "mergedNetworkCapabilities must be nonnull");

        mIsTearDownRequested = isTearDownRequested;
        mMergedNetworkCapabilities = mergedNetworkCapabilities;
        mVcnNetworkPolicyResult =
                new VcnNetworkPolicyResult(isTearDownRequested, mergedNetworkCapabilities);
    }

    private VcnUnderlyingNetworkPolicy(@NonNull VcnNetworkPolicyResult vcnNetworkPolicyResult) {
        this.mVcnNetworkPolicyResult =
                Objects.requireNonNull(vcnNetworkPolicyResult, "vcnNetworkPolicyResult");
    }

    /**
@@ -55,7 +59,7 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable {
     * be torn down.
     */
    public boolean isTeardownRequested() {
        return mIsTearDownRequested;
        return mVcnNetworkPolicyResult.isTeardownRequested();
    }

    /**
@@ -64,12 +68,12 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable {
     */
    @NonNull
    public NetworkCapabilities getMergedNetworkCapabilities() {
        return mMergedNetworkCapabilities;
        return mVcnNetworkPolicyResult.getNetworkCapabilities();
    }

    @Override
    public int hashCode() {
        return Objects.hash(mIsTearDownRequested, mMergedNetworkCapabilities);
        return Objects.hash(mVcnNetworkPolicyResult);
    }

    @Override
@@ -78,8 +82,7 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable {
        if (!(o instanceof VcnUnderlyingNetworkPolicy)) return false;
        final VcnUnderlyingNetworkPolicy that = (VcnUnderlyingNetworkPolicy) o;

        return mIsTearDownRequested == that.mIsTearDownRequested
                && mMergedNetworkCapabilities.equals(that.mMergedNetworkCapabilities);
        return mVcnNetworkPolicyResult.equals(that.mVcnNetworkPolicyResult);
    }

    /** {@inheritDoc} */
@@ -91,16 +94,14 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable {
    /** {@inheritDoc} */
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeBoolean(mIsTearDownRequested);
        dest.writeParcelable(mMergedNetworkCapabilities, flags);
        dest.writeParcelable(mVcnNetworkPolicyResult, flags);
    }

    /** Implement the Parcelable interface */
    public static final @NonNull Creator<VcnUnderlyingNetworkPolicy> CREATOR =
            new Creator<VcnUnderlyingNetworkPolicy>() {
                public VcnUnderlyingNetworkPolicy createFromParcel(Parcel in) {
                    return new VcnUnderlyingNetworkPolicy(
                            in.readBoolean(), in.readParcelable(null));
                    return new VcnUnderlyingNetworkPolicy(in.readParcelable(null));
                }

                public VcnUnderlyingNetworkPolicy[] newArray(int size) {
+1 −1
Original line number Diff line number Diff line
@@ -46,6 +46,6 @@ public class VcnUnderlyingNetworkPolicyTest {

    @Test
    public void testParcelUnparcel() {
        assertParcelSane(SAMPLE_NETWORK_POLICY, 2);
        assertParcelSane(SAMPLE_NETWORK_POLICY, 1);
    }
}