Merge "Implement Policy Listener add/remove in VcnService." am: 59035bd8c7 am: 3661eba6cc

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Id9399ea6e21930adfa0c44767b7714f7e35cf64a
This commit is contained in:
Cody Kesting
2021-01-22 17:40:04 +00:00
committed by Automerger Merge Worker
2 changed files with 104 additions and 6 deletions

View File

@@ -31,16 +31,19 @@ import android.net.vcn.VcnConfig;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.ParcelUuid; import android.os.ParcelUuid;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.os.Process; import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceSpecificException; import android.os.ServiceSpecificException;
import android.os.UserHandle; import android.os.UserHandle;
import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog; import android.util.Slog;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
@@ -155,6 +158,11 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private final PersistableBundleUtils.LockingReadWriteHelper mConfigDiskRwHelper; @NonNull private final PersistableBundleUtils.LockingReadWriteHelper mConfigDiskRwHelper;
@GuardedBy("mLock")
@NonNull
private final Map<IBinder, PolicyListenerBinderDeath> mRegisteredPolicyListeners =
new ArrayMap<>();
@VisibleForTesting(visibility = Visibility.PRIVATE) @VisibleForTesting(visibility = Visibility.PRIVATE)
VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) { VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
mContext = requireNonNull(context, "Missing context"); mContext = requireNonNull(context, "Missing context");
@@ -497,19 +505,60 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} }
} }
/** Binder death recipient used to remove a registered policy listener. */
private class PolicyListenerBinderDeath implements Binder.DeathRecipient {
@NonNull private final IVcnUnderlyingNetworkPolicyListener mListener;
PolicyListenerBinderDeath(@NonNull IVcnUnderlyingNetworkPolicyListener listener) {
mListener = listener;
}
@Override
public void binderDied() {
Log.e(TAG, "app died without removing VcnUnderlyingNetworkPolicyListener");
removeVcnUnderlyingNetworkPolicyListener(mListener);
}
}
/** Adds the provided listener for receiving VcnUnderlyingNetworkPolicy updates. */ /** Adds the provided listener for receiving VcnUnderlyingNetworkPolicy updates. */
@GuardedBy("mLock")
@Override @Override
public void addVcnUnderlyingNetworkPolicyListener( public void addVcnUnderlyingNetworkPolicyListener(
IVcnUnderlyingNetworkPolicyListener listener) { @NonNull IVcnUnderlyingNetworkPolicyListener listener) {
// TODO(b/175739863): implement policy listener registration requireNonNull(listener, "listener was null");
throw new UnsupportedOperationException("Not yet implemented");
mContext.enforceCallingPermission(
android.Manifest.permission.NETWORK_FACTORY,
"Must have permission NETWORK_FACTORY to register a policy listener");
PolicyListenerBinderDeath listenerBinderDeath = new PolicyListenerBinderDeath(listener);
synchronized (mLock) {
mRegisteredPolicyListeners.put(listener.asBinder(), listenerBinderDeath);
try {
listener.asBinder().linkToDeath(listenerBinderDeath, 0 /* flags */);
} catch (RemoteException e) {
// Remote binder already died - cleanup registered Listener
listenerBinderDeath.binderDied();
}
}
} }
/** Removes the provided listener from receiving VcnUnderlyingNetworkPolicy updates. */ /** Removes the provided listener from receiving VcnUnderlyingNetworkPolicy updates. */
@GuardedBy("mLock")
@Override @Override
public void removeVcnUnderlyingNetworkPolicyListener( public void removeVcnUnderlyingNetworkPolicyListener(
IVcnUnderlyingNetworkPolicyListener listener) { @NonNull IVcnUnderlyingNetworkPolicyListener listener) {
// TODO(b/175739863): implement policy listener unregistration requireNonNull(listener, "listener was null");
throw new UnsupportedOperationException("Not yet implemented");
synchronized (mLock) {
PolicyListenerBinderDeath listenerBinderDeath =
mRegisteredPolicyListeners.remove(listener.asBinder());
if (listenerBinderDeath != null) {
listener.asBinder().unlinkToDeath(listenerBinderDeath, 0 /* flags */);
}
}
} }
} }

View File

@@ -23,10 +23,15 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq; import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@@ -35,8 +40,10 @@ import static org.mockito.Mockito.verify;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig; import android.net.vcn.VcnConfig;
import android.net.vcn.VcnConfigTest; import android.net.vcn.VcnConfigTest;
import android.os.IBinder;
import android.os.ParcelUuid; import android.os.ParcelUuid;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.os.Process; import android.os.Process;
@@ -126,6 +133,10 @@ public class VcnManagementServiceTest {
private final VcnManagementService mVcnMgmtSvc; private final VcnManagementService mVcnMgmtSvc;
private final IVcnUnderlyingNetworkPolicyListener mMockPolicyListener =
mock(IVcnUnderlyingNetworkPolicyListener.class);
private final IBinder mMockIBinder = mock(IBinder.class);
public VcnManagementServiceTest() throws Exception { public VcnManagementServiceTest() throws Exception {
setupSystemService(mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); setupSystemService(mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
setupSystemService(mTelMgr, Context.TELEPHONY_SERVICE, TelephonyManager.class); setupSystemService(mTelMgr, Context.TELEPHONY_SERVICE, TelephonyManager.class);
@@ -169,6 +180,8 @@ public class VcnManagementServiceTest {
setupMockedCarrierPrivilege(true); setupMockedCarrierPrivilege(true);
mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps); mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
doReturn(mMockIBinder).when(mMockPolicyListener).asBinder();
// Make sure the profiles are loaded. // Make sure the profiles are loaded.
mTestLooper.dispatchAll(); mTestLooper.dispatchAll();
} }
@@ -438,4 +451,40 @@ public class VcnManagementServiceTest {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2);
verify(vcnInstance).teardownAsynchronously(); verify(vcnInstance).teardownAsynchronously();
} }
@Test
public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception {
doNothing()
.when(mMockContext)
.enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
verify(mMockIBinder).linkToDeath(any(), anyInt());
}
@Test(expected = SecurityException.class)
public void testAddVcnUnderlyingNetworkPolicyListenerInvalidPermission() {
doThrow(new SecurityException())
.when(mMockContext)
.enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
@Test
public void testRemoveVcnUnderlyingNetworkPolicyListener() {
// verify listener added
doNothing()
.when(mMockContext)
.enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
@Test
public void testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered() {
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
} }