Merge changes I61dd789f,I57c73264
* changes: Define add and remove for VCN policy listeners. Define VcnUnderlyingNetworkPolicy.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.net.vcn;
|
||||
|
||||
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
|
||||
import android.net.vcn.VcnConfig;
|
||||
import android.os.ParcelUuid;
|
||||
|
||||
@@ -25,4 +26,7 @@ import android.os.ParcelUuid;
|
||||
interface IVcnManagementService {
|
||||
void setVcnConfig(in ParcelUuid subscriptionGroup, in VcnConfig config, in String opPkgName);
|
||||
void clearVcnConfig(in ParcelUuid subscriptionGroup);
|
||||
|
||||
void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
|
||||
void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 */
|
||||
interface IVcnUnderlyingNetworkPolicyListener {
|
||||
void onPolicyChanged();
|
||||
}
|
||||
@@ -25,7 +25,12 @@ import android.os.ParcelUuid;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks.
|
||||
@@ -60,6 +65,11 @@ import java.io.IOException;
|
||||
public final class VcnManager {
|
||||
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
|
||||
|
||||
@VisibleForTesting
|
||||
public static final Map<
|
||||
VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
|
||||
REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final IVcnManagementService mService;
|
||||
|
||||
@@ -136,4 +146,101 @@ public final class VcnManager {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make VcnUnderlyingNetworkPolicyListener @SystemApi
|
||||
/**
|
||||
* 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 {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void onPolicyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 IllegalArgumentException if the specified VcnUnderlyingNetworkPolicyListener is
|
||||
* already registered
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
|
||||
public void addVcnUnderlyingNetworkPolicyListener(
|
||||
@NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener 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");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.addVcnUnderlyingNetworkPolicyListener(binder);
|
||||
} catch (RemoteException e) {
|
||||
REGISTERED_POLICY_LISTENERS.remove(listener);
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
requireNonNull(listener, "listener must not be null");
|
||||
|
||||
VcnUnderlyingNetworkPolicyListenerBinder binder =
|
||||
REGISTERED_POLICY_LISTENERS.remove(listener);
|
||||
if (binder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mService.removeVcnUnderlyingNetworkPolicyListener(binder);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System
|
||||
* Server.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
private static class VcnUnderlyingNetworkPolicyListenerBinder
|
||||
extends IVcnUnderlyingNetworkPolicyListener.Stub {
|
||||
@NonNull private final Executor mExecutor;
|
||||
@NonNull private final VcnUnderlyingNetworkPolicyListener mListener;
|
||||
|
||||
private VcnUnderlyingNetworkPolicyListenerBinder(
|
||||
Executor executor, VcnUnderlyingNetworkPolicyListener listener) {
|
||||
mExecutor = executor;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPolicyChanged() {
|
||||
mExecutor.execute(() -> mListener.onPolicyChanged());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.aidl
Normal file
20
core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 VcnUnderlyingNetworkPolicy;
|
||||
110
core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
Normal file
110
core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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;
|
||||
|
||||
/**
|
||||
* VcnUnderlyingNetworkPolicy represents the Network policy for a VCN-managed Network.
|
||||
*
|
||||
* <p>Transports that are bringing up networks capable of acting as a VCN's underlying network
|
||||
* should query for policy state upon major capability changes (e.g. changing of TRUSTED bit), and
|
||||
* when prompted by VcnManagementService via VcnUnderlyingNetworkPolicyListener.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class VcnUnderlyingNetworkPolicy implements Parcelable {
|
||||
private final boolean mIsTearDownRequested;
|
||||
private final NetworkCapabilities mMergedNetworkCapabilities;
|
||||
|
||||
/**
|
||||
* Constructs a VcnUnderlyingNetworkPolicy with the specified parameters.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public VcnUnderlyingNetworkPolicy(
|
||||
boolean isTearDownRequested, @NonNull NetworkCapabilities mergedNetworkCapabilities) {
|
||||
Objects.requireNonNull(
|
||||
mergedNetworkCapabilities, "mergedNetworkCapabilities must be nonnull");
|
||||
|
||||
mIsTearDownRequested = isTearDownRequested;
|
||||
mMergedNetworkCapabilities = mergedNetworkCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this Carrier VCN policy policy indicates that the underlying Network should
|
||||
* be torn down.
|
||||
*/
|
||||
public boolean isTeardownRequested() {
|
||||
return mIsTearDownRequested;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the NetworkCapabilities with Carrier VCN policy bits merged into the provided
|
||||
* capabilities.
|
||||
*/
|
||||
@NonNull
|
||||
public NetworkCapabilities getMergedNetworkCapabilities() {
|
||||
return mMergedNetworkCapabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mIsTearDownRequested, mMergedNetworkCapabilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof VcnUnderlyingNetworkPolicy)) return false;
|
||||
final VcnUnderlyingNetworkPolicy that = (VcnUnderlyingNetworkPolicy) o;
|
||||
|
||||
return mIsTearDownRequested == that.mIsTearDownRequested
|
||||
&& mMergedNetworkCapabilities.equals(that.mMergedNetworkCapabilities);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeBoolean(mIsTearDownRequested);
|
||||
dest.writeParcelable(mMergedNetworkCapabilities, 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));
|
||||
}
|
||||
|
||||
public VcnUnderlyingNetworkPolicy[] newArray(int size) {
|
||||
return new VcnUnderlyingNetworkPolicy[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.vcn.IVcnManagementService;
|
||||
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
|
||||
import android.net.vcn.VcnConfig;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
@@ -495,4 +496,20 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
||||
return Collections.unmodifiableMap(mVcns);
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds the provided listener for receiving VcnUnderlyingNetworkPolicy updates. */
|
||||
@Override
|
||||
public void addVcnUnderlyingNetworkPolicyListener(
|
||||
IVcnUnderlyingNetworkPolicyListener listener) {
|
||||
// TODO(b/175739863): implement policy listener registration
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/** Removes the provided listener from receiving VcnUnderlyingNetworkPolicy updates. */
|
||||
@Override
|
||||
public void removeVcnUnderlyingNetworkPolicyListener(
|
||||
IVcnUnderlyingNetworkPolicyListener listener) {
|
||||
// TODO(b/175739863): implement policy listener unregistration
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ android_test {
|
||||
"frameworks-base-testutils",
|
||||
"framework-protos",
|
||||
"mockito-target-minus-junit4",
|
||||
"net-tests-utils",
|
||||
"platform-test-annotations",
|
||||
"services.core",
|
||||
],
|
||||
|
||||
106
tests/vcn/java/android/net/vcn/VcnManagerTest.java
Normal file
106
tests/vcn/java/android/net/vcn/VcnManagerTest.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 static androidx.test.InstrumentationRegistry.getContext;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class VcnManagerTest {
|
||||
private static final Executor INLINE_EXECUTOR = Runnable::run;
|
||||
|
||||
private IVcnManagementService mMockVcnManagementService;
|
||||
private VcnUnderlyingNetworkPolicyListener mMockPolicyListener;
|
||||
|
||||
private Context mContext;
|
||||
private VcnManager mVcnManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mMockVcnManagementService = mock(IVcnManagementService.class);
|
||||
mMockPolicyListener = mock(VcnUnderlyingNetworkPolicyListener.class);
|
||||
|
||||
mContext = getContext();
|
||||
mVcnManager = new VcnManager(mContext, mMockVcnManagementService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception {
|
||||
mVcnManager.addVcnUnderlyingNetworkPolicyListener(INLINE_EXECUTOR, mMockPolicyListener);
|
||||
|
||||
ArgumentCaptor<IVcnUnderlyingNetworkPolicyListener> captor =
|
||||
ArgumentCaptor.forClass(IVcnUnderlyingNetworkPolicyListener.class);
|
||||
verify(mMockVcnManagementService).addVcnUnderlyingNetworkPolicyListener(captor.capture());
|
||||
|
||||
assertTrue(VcnManager.REGISTERED_POLICY_LISTENERS.containsKey(mMockPolicyListener));
|
||||
|
||||
IVcnUnderlyingNetworkPolicyListener listenerWrapper = captor.getValue();
|
||||
listenerWrapper.onPolicyChanged();
|
||||
verify(mMockPolicyListener).onPolicyChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveVcnUnderlyingNetworkPolicyListener() throws Exception {
|
||||
mVcnManager.addVcnUnderlyingNetworkPolicyListener(INLINE_EXECUTOR, mMockPolicyListener);
|
||||
|
||||
mVcnManager.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||
|
||||
assertFalse(VcnManager.REGISTERED_POLICY_LISTENERS.containsKey(mMockPolicyListener));
|
||||
verify(mMockVcnManagementService)
|
||||
.addVcnUnderlyingNetworkPolicyListener(
|
||||
any(IVcnUnderlyingNetworkPolicyListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveVcnUnderlyingNetworkPolicyListenerUnknownListener() throws Exception {
|
||||
mVcnManager.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||
|
||||
assertFalse(VcnManager.REGISTERED_POLICY_LISTENERS.containsKey(mMockPolicyListener));
|
||||
verify(mMockVcnManagementService, never())
|
||||
.addVcnUnderlyingNetworkPolicyListener(
|
||||
any(IVcnUnderlyingNetworkPolicyListener.class));
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testAddVcnUnderlyingNetworkPolicyListenerNullExecutor() throws Exception {
|
||||
mVcnManager.addVcnUnderlyingNetworkPolicyListener(null, mMockPolicyListener);
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testAddVcnUnderlyingNetworkPolicyListenerNullListener() throws Exception {
|
||||
mVcnManager.addVcnUnderlyingNetworkPolicyListener(INLINE_EXECUTOR, null);
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testRemoveVcnUnderlyingNetworkPolicyListenerNullListener() {
|
||||
mVcnManager.removeVcnUnderlyingNetworkPolicyListener(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 static com.android.testutils.ParcelUtils.assertParcelSane;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import android.net.NetworkCapabilities;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class VcnUnderlyingNetworkPolicyTest {
|
||||
private static final VcnUnderlyingNetworkPolicy DEFAULT_NETWORK_POLICY =
|
||||
new VcnUnderlyingNetworkPolicy(
|
||||
false /* isTearDownRequested */, new NetworkCapabilities());
|
||||
private static final VcnUnderlyingNetworkPolicy SAMPLE_NETWORK_POLICY =
|
||||
new VcnUnderlyingNetworkPolicy(
|
||||
true /* isTearDownRequested */,
|
||||
new NetworkCapabilities.Builder()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
.build());
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(DEFAULT_NETWORK_POLICY, DEFAULT_NETWORK_POLICY);
|
||||
assertEquals(SAMPLE_NETWORK_POLICY, SAMPLE_NETWORK_POLICY);
|
||||
|
||||
assertNotEquals(DEFAULT_NETWORK_POLICY, SAMPLE_NETWORK_POLICY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelUnparcel() {
|
||||
assertParcelSane(SAMPLE_NETWORK_POLICY, 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user