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:
@@ -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 */);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user