Merge changes from topic "vcn-status-cb"
* changes: Call VcnStatusCallback#onVcnStatusChanged on register. Remove VcnStatusCallback#onEnteredSafemode(). Expose APIs for VcnStatusCallback.
This commit is contained in:
@@ -25711,7 +25711,22 @@ package android.net.vcn {
|
|||||||
|
|
||||||
public class VcnManager {
|
public class VcnManager {
|
||||||
method @RequiresPermission("carrier privileges") public void clearVcnConfig(@NonNull android.os.ParcelUuid) throws java.io.IOException;
|
method @RequiresPermission("carrier privileges") public void clearVcnConfig(@NonNull android.os.ParcelUuid) throws java.io.IOException;
|
||||||
|
method public void registerVcnStatusCallback(@NonNull android.os.ParcelUuid, @NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnStatusCallback);
|
||||||
method @RequiresPermission("carrier privileges") public void setVcnConfig(@NonNull android.os.ParcelUuid, @NonNull android.net.vcn.VcnConfig) throws java.io.IOException;
|
method @RequiresPermission("carrier privileges") public void setVcnConfig(@NonNull android.os.ParcelUuid, @NonNull android.net.vcn.VcnConfig) throws java.io.IOException;
|
||||||
|
method public void unregisterVcnStatusCallback(@NonNull android.net.vcn.VcnManager.VcnStatusCallback);
|
||||||
|
field public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1; // 0x1
|
||||||
|
field public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0; // 0x0
|
||||||
|
field public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2; // 0x2
|
||||||
|
field public static final int VCN_STATUS_CODE_ACTIVE = 2; // 0x2
|
||||||
|
field public static final int VCN_STATUS_CODE_INACTIVE = 1; // 0x1
|
||||||
|
field public static final int VCN_STATUS_CODE_NOT_CONFIGURED = 0; // 0x0
|
||||||
|
field public static final int VCN_STATUS_CODE_SAFE_MODE = 3; // 0x3
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class VcnManager.VcnStatusCallback {
|
||||||
|
ctor public VcnManager.VcnStatusCallback();
|
||||||
|
method public abstract void onGatewayConnectionError(@NonNull int[], int, @Nullable Throwable);
|
||||||
|
method public abstract void onVcnStatusChanged(int);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package android.net.vcn;
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
oneway interface IVcnStatusCallback {
|
oneway interface IVcnStatusCallback {
|
||||||
void onEnteredSafeMode();
|
|
||||||
void onVcnStatusChanged(int statusCode);
|
void onVcnStatusChanged(int statusCode);
|
||||||
void onGatewayConnectionError(
|
void onGatewayConnectionError(
|
||||||
in int[] gatewayNetworkCapabilities,
|
in int[] gatewayNetworkCapabilities,
|
||||||
|
|||||||
@@ -359,8 +359,6 @@ public class VcnManager {
|
|||||||
/**
|
/**
|
||||||
* Value indicating that the VCN for the subscription group is not configured, or that the
|
* Value indicating that the VCN for the subscription group is not configured, or that the
|
||||||
* callback is not privileged for the subscription group.
|
* callback is not privileged for the subscription group.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_STATUS_CODE_NOT_CONFIGURED = 0;
|
public static final int VCN_STATUS_CODE_NOT_CONFIGURED = 0;
|
||||||
|
|
||||||
@@ -369,8 +367,6 @@ public class VcnManager {
|
|||||||
*
|
*
|
||||||
* <p>A VCN is inactive if a {@link VcnConfig} is present for the subscription group, but the
|
* <p>A VCN is inactive if a {@link VcnConfig} is present for the subscription group, but the
|
||||||
* provisioning package is not privileged.
|
* provisioning package is not privileged.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_STATUS_CODE_INACTIVE = 1;
|
public static final int VCN_STATUS_CODE_INACTIVE = 1;
|
||||||
|
|
||||||
@@ -380,8 +376,6 @@ public class VcnManager {
|
|||||||
* <p>A VCN is active if a {@link VcnConfig} is present for the subscription, the provisioning
|
* <p>A VCN is active if a {@link VcnConfig} is present for the subscription, the provisioning
|
||||||
* package is privileged, and the VCN is not in Safe Mode. In other words, a VCN is considered
|
* package is privileged, and the VCN is not in Safe Mode. In other words, a VCN is considered
|
||||||
* active while it is connecting, fully connected, and disconnecting.
|
* active while it is connecting, fully connected, and disconnecting.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_STATUS_CODE_ACTIVE = 2;
|
public static final int VCN_STATUS_CODE_ACTIVE = 2;
|
||||||
|
|
||||||
@@ -391,8 +385,6 @@ public class VcnManager {
|
|||||||
* <p>A VCN will be put into Safe Mode if any of the gateway connections were unable to
|
* <p>A VCN will be put into Safe Mode if any of the gateway connections were unable to
|
||||||
* establish a connection within a system-determined timeout (while underlying networks were
|
* establish a connection within a system-determined timeout (while underlying networks were
|
||||||
* available).
|
* available).
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_STATUS_CODE_SAFE_MODE = 3;
|
public static final int VCN_STATUS_CODE_SAFE_MODE = 3;
|
||||||
|
|
||||||
@@ -407,8 +399,6 @@ public class VcnManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Value indicating that an internal failure occurred in this Gateway Connection.
|
* Value indicating that an internal failure occurred in this Gateway Connection.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0;
|
public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0;
|
||||||
|
|
||||||
@@ -416,8 +406,6 @@ public class VcnManager {
|
|||||||
* Value indicating that an error with this Gateway Connection's configuration occurred.
|
* Value indicating that an error with this Gateway Connection's configuration occurred.
|
||||||
*
|
*
|
||||||
* <p>For example, this error code will be returned after authentication failures.
|
* <p>For example, this error code will be returned after authentication failures.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1;
|
public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1;
|
||||||
|
|
||||||
@@ -427,37 +415,18 @@ public class VcnManager {
|
|||||||
* <p>For example, this error code will be returned if an underlying {@link android.net.Network}
|
* <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
|
* for this Gateway Connection is lost, or if an error occurs while resolving the connection
|
||||||
* endpoint address.
|
* endpoint address.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2;
|
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.
|
* VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs.
|
||||||
*
|
*
|
||||||
* <p>VcnStatusCallbacks may be registered before {@link VcnConfig}s are provided for a
|
* <p>VcnStatusCallbacks may be registered before {@link VcnConfig}s are provided for a
|
||||||
* subscription group.
|
* subscription group.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public abstract static class VcnStatusCallback {
|
public abstract static class VcnStatusCallback {
|
||||||
private VcnStatusCallbackBinder mCbBinder;
|
private VcnStatusCallbackBinder mCbBinder;
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when the VCN for this Callback's subscription group enters safe mode.
|
|
||||||
*
|
|
||||||
* <p>A VCN will be put into safe mode if any of the gateway connections were unable to
|
|
||||||
* establish a connection within a system-determined timeout (while underlying networks were
|
|
||||||
* available).
|
|
||||||
*
|
|
||||||
* <p>A VCN-configuring app may opt to exit safe mode by (re)setting the VCN configuration
|
|
||||||
* via {@link #setVcnConfig(ParcelUuid, VcnConfig)}.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public void onEnteredSafeMode() {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when status of the VCN for this callback's subscription group changes.
|
* Invoked when status of the VCN for this callback's subscription group changes.
|
||||||
*
|
*
|
||||||
@@ -467,15 +436,16 @@ public class VcnManager {
|
|||||||
public abstract void onVcnStatusChanged(@VcnStatusCode int statusCode);
|
public abstract void onVcnStatusChanged(@VcnStatusCode int statusCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription
|
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription group
|
||||||
* encounters an error.
|
* encounters an error.
|
||||||
*
|
*
|
||||||
* @param networkCapabilities an array of underlying NetworkCapabilities for the Gateway
|
* @param networkCapabilities an array of NetworkCapabilities.NET_CAPABILITY_* capabilities
|
||||||
* Connection that encountered the error for identification purposes. These will be a
|
* for the Gateway Connection that encountered the error, for identification purposes.
|
||||||
* sorted list with no duplicates, matching one of the {@link
|
* These will be a sorted list with no duplicates and will match {@link
|
||||||
|
* VcnGatewayConnectionConfig#getRequiredUnderlyingCapabilities()} for one of the {@link
|
||||||
* VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
|
* VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
|
||||||
* group.
|
* group.
|
||||||
* @param errorCode {@link VcnErrorCode} to indicate the error that occurred
|
* @param errorCode the code to indicate the error that occurred
|
||||||
* @param detail Throwable to provide additional information about the error, or {@code
|
* @param detail Throwable to provide additional information about the error, or {@code
|
||||||
* null} if none
|
* null} if none
|
||||||
*/
|
*/
|
||||||
@@ -496,6 +466,10 @@ public class VcnManager {
|
|||||||
* <p>A {@link VcnStatusCallback} will only be invoked if the registering package has carrier
|
* <p>A {@link VcnStatusCallback} will only be invoked if the registering package has carrier
|
||||||
* privileges for the specified subscription at the time of invocation.
|
* privileges for the specified subscription at the time of invocation.
|
||||||
*
|
*
|
||||||
|
* <p>A {@link VcnStatusCallback} is eligible to begin receiving callbacks once it is registered
|
||||||
|
* and there is a VCN active for its specified subscription group (this may happen after the
|
||||||
|
* callback is registered).
|
||||||
|
*
|
||||||
* <p>{@link VcnStatusCallback#onVcnStatusChanged(int)} will be invoked on registration with the
|
* <p>{@link VcnStatusCallback#onVcnStatusChanged(int)} will be invoked on registration with the
|
||||||
* current status for the specified subscription group's VCN. If the registrant is not
|
* current status for the specified subscription group's VCN. If the registrant is not
|
||||||
* privileged for this subscription group, {@link #VCN_STATUS_CODE_NOT_CONFIGURED} will be
|
* privileged for this subscription group, {@link #VCN_STATUS_CODE_NOT_CONFIGURED} will be
|
||||||
@@ -505,7 +479,6 @@ public class VcnManager {
|
|||||||
* @param executor The {@link Executor} to be used for invoking callbacks
|
* @param executor The {@link Executor} to be used for invoking callbacks
|
||||||
* @param callback The VcnStatusCallback to be registered
|
* @param callback The VcnStatusCallback to be registered
|
||||||
* @throws IllegalStateException if callback is currently registered with VcnManager
|
* @throws IllegalStateException if callback is currently registered with VcnManager
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public void registerVcnStatusCallback(
|
public void registerVcnStatusCallback(
|
||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@@ -538,7 +511,6 @@ public class VcnManager {
|
|||||||
* was registered with.
|
* was registered with.
|
||||||
*
|
*
|
||||||
* @param callback The callback to be unregistered
|
* @param callback The callback to be unregistered
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public void unregisterVcnStatusCallback(@NonNull VcnStatusCallback callback) {
|
public void unregisterVcnStatusCallback(@NonNull VcnStatusCallback callback) {
|
||||||
requireNonNull(callback, "callback must not be null");
|
requireNonNull(callback, "callback must not be null");
|
||||||
@@ -598,12 +570,6 @@ public class VcnManager {
|
|||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnteredSafeMode() {
|
|
||||||
Binder.withCleanCallingIdentity(
|
|
||||||
() -> mExecutor.execute(() -> mCallback.onEnteredSafeMode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
|
public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
|
||||||
Binder.withCleanCallingIdentity(
|
Binder.withCleanCallingIdentity(
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import android.net.vcn.IVcnManagementService;
|
|||||||
import android.net.vcn.IVcnStatusCallback;
|
import android.net.vcn.IVcnStatusCallback;
|
||||||
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
|
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
|
||||||
import android.net.vcn.VcnConfig;
|
import android.net.vcn.VcnConfig;
|
||||||
|
import android.net.vcn.VcnManager;
|
||||||
import android.net.vcn.VcnManager.VcnErrorCode;
|
import android.net.vcn.VcnManager.VcnErrorCode;
|
||||||
import android.net.vcn.VcnUnderlyingNetworkPolicy;
|
import android.net.vcn.VcnUnderlyingNetworkPolicy;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
@@ -724,6 +725,26 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isCallbackPermissioned(
|
||||||
|
@NonNull VcnStatusCallbackInfo cbInfo, @NonNull ParcelUuid subgroup) {
|
||||||
|
if (!subgroup.equals(cbInfo.mSubGroup)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subgroup, cbInfo.mPkgName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mLocationPermissionChecker.checkLocationPermission(
|
||||||
|
cbInfo.mPkgName,
|
||||||
|
"VcnStatusCallback" /* featureId */,
|
||||||
|
cbInfo.mUid,
|
||||||
|
null /* message */)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** Registers the provided callback for receiving VCN status updates. */
|
/** Registers the provided callback for receiving VCN status updates. */
|
||||||
@Override
|
@Override
|
||||||
public void registerVcnStatusCallback(
|
public void registerVcnStatusCallback(
|
||||||
@@ -758,6 +779,27 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mRegisteredStatusCallbacks.put(cbBinder, cbInfo);
|
mRegisteredStatusCallbacks.put(cbBinder, cbInfo);
|
||||||
|
|
||||||
|
// now that callback is registered, send it the VCN's current status
|
||||||
|
final VcnConfig vcnConfig = mConfigs.get(subGroup);
|
||||||
|
final Vcn vcn = mVcns.get(subGroup);
|
||||||
|
final int vcnStatus;
|
||||||
|
if (vcnConfig == null || !isCallbackPermissioned(cbInfo, subGroup)) {
|
||||||
|
vcnStatus = VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
|
||||||
|
} else if (vcn == null) {
|
||||||
|
vcnStatus = VcnManager.VCN_STATUS_CODE_INACTIVE;
|
||||||
|
} else if (vcn.isActive()) {
|
||||||
|
vcnStatus = VcnManager.VCN_STATUS_CODE_ACTIVE;
|
||||||
|
} else {
|
||||||
|
// TODO(b/181789060): create Vcn.getStatus() and Log.WTF() for unknown status
|
||||||
|
vcnStatus = VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
cbInfo.mCallback.onVcnStatusChanged(vcnStatus);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.d(TAG, "VcnStatusCallback threw on VCN status change", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
@@ -806,26 +848,6 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
mSubGroup = Objects.requireNonNull(subGroup, "Missing 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
|
@Override
|
||||||
public void onEnteredSafeMode() {
|
public void onEnteredSafeMode() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -838,7 +860,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
|
|
||||||
// Notify all registered StatusCallbacks for this subGroup
|
// Notify all registered StatusCallbacks for this subGroup
|
||||||
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
||||||
if (isCallbackPermissioned(cbInfo)) {
|
if (isCallbackPermissioned(cbInfo, mSubGroup)) {
|
||||||
Binder.withCleanCallingIdentity(
|
Binder.withCleanCallingIdentity(
|
||||||
() ->
|
() ->
|
||||||
cbInfo.mCallback.onVcnStatusChanged(
|
cbInfo.mCallback.onVcnStatusChanged(
|
||||||
@@ -862,7 +884,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
|
|
||||||
// Notify all registered StatusCallbacks for this subGroup
|
// Notify all registered StatusCallbacks for this subGroup
|
||||||
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
||||||
if (isCallbackPermissioned(cbInfo)) {
|
if (isCallbackPermissioned(cbInfo, mSubGroup)) {
|
||||||
Binder.withCleanCallingIdentity(
|
Binder.withCleanCallingIdentity(
|
||||||
() ->
|
() ->
|
||||||
cbInfo.mCallback.onGatewayConnectionError(
|
cbInfo.mCallback.onGatewayConnectionError(
|
||||||
|
|||||||
@@ -203,9 +203,6 @@ public class VcnManagerTest {
|
|||||||
IVcnStatusCallback cbBinder =
|
IVcnStatusCallback cbBinder =
|
||||||
new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback);
|
new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback);
|
||||||
|
|
||||||
cbBinder.onEnteredSafeMode();
|
|
||||||
verify(mMockStatusCallback).onEnteredSafeMode();
|
|
||||||
|
|
||||||
cbBinder.onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
|
cbBinder.onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
|
||||||
verify(mMockStatusCallback).onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
|
verify(mMockStatusCallback).onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ import java.util.UUID;
|
|||||||
public class VcnManagementServiceTest {
|
public class VcnManagementServiceTest {
|
||||||
private static final String TEST_PACKAGE_NAME =
|
private static final String TEST_PACKAGE_NAME =
|
||||||
VcnManagementServiceTest.class.getPackage().getName();
|
VcnManagementServiceTest.class.getPackage().getName();
|
||||||
|
private static final String TEST_CB_PACKAGE_NAME =
|
||||||
|
VcnManagementServiceTest.class.getPackage().getName() + ".callback";
|
||||||
private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
|
private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
|
||||||
private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
|
private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
|
||||||
private static final VcnConfig TEST_VCN_CONFIG;
|
private static final VcnConfig TEST_VCN_CONFIG;
|
||||||
@@ -288,6 +290,14 @@ public class VcnManagementServiceTest {
|
|||||||
|
|
||||||
private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot(
|
private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap) {
|
Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap) {
|
||||||
|
return triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
|
activeSubscriptionGroups, subIdToGroupMap, true /* hasCarrierPrivileges */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
|
Set<ParcelUuid> activeSubscriptionGroups,
|
||||||
|
Map<Integer, ParcelUuid> subIdToGroupMap,
|
||||||
|
boolean hasCarrierPrivileges) {
|
||||||
final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class);
|
final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class);
|
||||||
doReturn(activeSubscriptionGroups).when(snapshot).getActiveSubscriptionGroups();
|
doReturn(activeSubscriptionGroups).when(snapshot).getActiveSubscriptionGroups();
|
||||||
|
|
||||||
@@ -295,7 +305,7 @@ public class VcnManagementServiceTest {
|
|||||||
(activeSubscriptionGroups == null || activeSubscriptionGroups.isEmpty())
|
(activeSubscriptionGroups == null || activeSubscriptionGroups.isEmpty())
|
||||||
? Collections.emptySet()
|
? Collections.emptySet()
|
||||||
: Collections.singleton(TEST_PACKAGE_NAME);
|
: Collections.singleton(TEST_PACKAGE_NAME);
|
||||||
doReturn(true)
|
doReturn(hasCarrierPrivileges)
|
||||||
.when(snapshot)
|
.when(snapshot)
|
||||||
.packageHasPermissionsForSubscriptionGroup(
|
.packageHasPermissionsForSubscriptionGroup(
|
||||||
argThat(val -> activeSubscriptionGroups.contains(val)),
|
argThat(val -> activeSubscriptionGroups.contains(val)),
|
||||||
@@ -549,13 +559,6 @@ public class VcnManagementServiceTest {
|
|||||||
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpVcnSubscription(int subId, ParcelUuid subGroup) {
|
|
||||||
mVcnMgmtSvc.setVcnConfig(subGroup, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
|
|
||||||
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(
|
|
||||||
Collections.singleton(subGroup), Collections.singletonMap(subId, subGroup));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyMergedNetworkCapabilities(
|
private void verifyMergedNetworkCapabilities(
|
||||||
NetworkCapabilities mergedCapabilities,
|
NetworkCapabilities mergedCapabilities,
|
||||||
@Transport int transportType,
|
@Transport int transportType,
|
||||||
@@ -573,9 +576,23 @@ public class VcnManagementServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupSubscriptionAndStartVcn(int subId, ParcelUuid subGrp, boolean isVcnActive) {
|
private void setupSubscriptionAndStartVcn(int subId, ParcelUuid subGrp, boolean isVcnActive) {
|
||||||
setUpVcnSubscription(subId, subGrp);
|
setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive, true /* hasCarrierPrivileges */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSubscriptionAndStartVcn(
|
||||||
|
int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) {
|
||||||
|
mVcnMgmtSvc.systemReady();
|
||||||
|
triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
|
Collections.singleton(subGrp),
|
||||||
|
Collections.singletonMap(subId, subGrp),
|
||||||
|
hasCarrierPrivileges);
|
||||||
|
|
||||||
final Vcn vcn = startAndGetVcnInstance(subGrp);
|
final Vcn vcn = startAndGetVcnInstance(subGrp);
|
||||||
doReturn(isVcnActive).when(vcn).isActive();
|
doReturn(isVcnActive).when(vcn).isActive();
|
||||||
|
|
||||||
|
doReturn(true)
|
||||||
|
.when(mLocationPermissionChecker)
|
||||||
|
.checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport(
|
private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport(
|
||||||
@@ -721,7 +738,7 @@ public class VcnManagementServiceTest {
|
|||||||
verify(mMockPolicyListener).onPolicyChanged();
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyVcnCallback(
|
private void triggerVcnSafeMode(
|
||||||
@NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
|
@NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
verify(mMockDeps)
|
verify(mMockDeps)
|
||||||
@@ -732,20 +749,20 @@ public class VcnManagementServiceTest {
|
|||||||
eq(snapshot),
|
eq(snapshot),
|
||||||
mVcnCallbackCaptor.capture());
|
mVcnCallbackCaptor.capture());
|
||||||
|
|
||||||
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
|
||||||
|
|
||||||
VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
|
VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
|
||||||
vcnCallback.onEnteredSafeMode();
|
vcnCallback.onEnteredSafeMode();
|
||||||
|
|
||||||
verify(mMockPolicyListener).onPolicyChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVcnCallbackOnEnteredSafeMode() throws Exception {
|
public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception {
|
||||||
TelephonySubscriptionSnapshot snapshot =
|
TelephonySubscriptionSnapshot snapshot =
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
||||||
|
|
||||||
verifyVcnCallback(TEST_UUID_1, snapshot);
|
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||||
|
|
||||||
|
triggerVcnSafeMode(TEST_UUID_1, snapshot);
|
||||||
|
|
||||||
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerVcnStatusCallbackOnEnteredSafeMode(
|
private void triggerVcnStatusCallbackOnEnteredSafeMode(
|
||||||
@@ -758,6 +775,9 @@ public class VcnManagementServiceTest {
|
|||||||
TelephonySubscriptionSnapshot snapshot =
|
TelephonySubscriptionSnapshot snapshot =
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(subGroup));
|
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(subGroup));
|
||||||
|
|
||||||
|
setupSubscriptionAndStartVcn(
|
||||||
|
TEST_SUBSCRIPTION_ID, subGroup, true /* isActive */, hasPermissionsforSubGroup);
|
||||||
|
|
||||||
doReturn(hasPermissionsforSubGroup)
|
doReturn(hasPermissionsforSubGroup)
|
||||||
.when(snapshot)
|
.when(snapshot)
|
||||||
.packageHasPermissionsForSubscriptionGroup(eq(subGroup), eq(pkgName));
|
.packageHasPermissionsForSubscriptionGroup(eq(subGroup), eq(pkgName));
|
||||||
@@ -768,10 +788,7 @@ public class VcnManagementServiceTest {
|
|||||||
|
|
||||||
mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName);
|
mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName);
|
||||||
|
|
||||||
// Trigger systemReady() to set up LocationPermissionChecker
|
triggerVcnSafeMode(subGroup, snapshot);
|
||||||
mVcnMgmtSvc.systemReady();
|
|
||||||
|
|
||||||
verifyVcnCallback(subGroup, snapshot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -825,6 +842,83 @@ public class VcnManagementServiceTest {
|
|||||||
assertEquals(TEST_PACKAGE_NAME, cbInfo.mPkgName);
|
assertEquals(TEST_PACKAGE_NAME, cbInfo.mPkgName);
|
||||||
assertEquals(TEST_UID, cbInfo.mUid);
|
assertEquals(TEST_UID, cbInfo.mUid);
|
||||||
verify(mMockIBinder).linkToDeath(eq(cbInfo), anyInt());
|
verify(mMockIBinder).linkToDeath(eq(cbInfo), anyInt());
|
||||||
|
|
||||||
|
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterVcnStatusCallback_MissingPermission() throws Exception {
|
||||||
|
setupSubscriptionAndStartVcn(
|
||||||
|
TEST_SUBSCRIPTION_ID,
|
||||||
|
TEST_UUID_1,
|
||||||
|
true /* isActive */,
|
||||||
|
false /* hasCarrierPrivileges */);
|
||||||
|
|
||||||
|
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME);
|
||||||
|
|
||||||
|
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterVcnStatusCallback_VcnInactive() throws Exception {
|
||||||
|
setupSubscriptionAndStartVcn(
|
||||||
|
TEST_SUBSCRIPTION_ID,
|
||||||
|
TEST_UUID_1,
|
||||||
|
true /* isActive */,
|
||||||
|
true /* hasCarrierPrivileges */);
|
||||||
|
|
||||||
|
// VCN is currently active. Lose carrier privileges for TEST_PACKAGE and hit teardown
|
||||||
|
// timeout so the VCN goes inactive.
|
||||||
|
final TelephonySubscriptionSnapshot snapshot =
|
||||||
|
triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
|
Collections.singleton(TEST_UUID_1),
|
||||||
|
Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1),
|
||||||
|
false /* hasCarrierPrivileges */);
|
||||||
|
mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
// Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE
|
||||||
|
// when the status callback is registered). Instead, setup permissions for TEST_CB_PACKAGE
|
||||||
|
// so that it's permissioned to receive INACTIVE (instead of NOT_CONFIGURED) without
|
||||||
|
// reactivating the VCN.
|
||||||
|
doReturn(true)
|
||||||
|
.when(snapshot)
|
||||||
|
.packageHasPermissionsForSubscriptionGroup(
|
||||||
|
eq(TEST_UUID_1), eq(TEST_CB_PACKAGE_NAME));
|
||||||
|
doReturn(true)
|
||||||
|
.when(mLocationPermissionChecker)
|
||||||
|
.checkLocationPermission(eq(TEST_CB_PACKAGE_NAME), any(), eq(TEST_UID), any());
|
||||||
|
|
||||||
|
mVcnMgmtSvc.registerVcnStatusCallback(
|
||||||
|
TEST_UUID_1, mMockStatusCallback, TEST_CB_PACKAGE_NAME);
|
||||||
|
|
||||||
|
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_INACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterVcnStatusCallback_VcnActive() throws Exception {
|
||||||
|
setupSubscriptionAndStartVcn(
|
||||||
|
TEST_SUBSCRIPTION_ID,
|
||||||
|
TEST_UUID_1,
|
||||||
|
true /* isActive */,
|
||||||
|
true /* hasCarrierPrivileges */);
|
||||||
|
|
||||||
|
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME);
|
||||||
|
|
||||||
|
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterVcnStatusCallback_VcnSafeMode() throws Exception {
|
||||||
|
setupSubscriptionAndStartVcn(
|
||||||
|
TEST_SUBSCRIPTION_ID,
|
||||||
|
TEST_UUID_1,
|
||||||
|
false /* isActive */,
|
||||||
|
true /* hasCarrierPrivileges */);
|
||||||
|
|
||||||
|
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME);
|
||||||
|
|
||||||
|
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user