diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 434e9241c7424..4fd9373ad1df9 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -40,7 +40,6 @@ import android.net.vcn.IVcnManagementService; import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.VcnConfig; -import android.net.vcn.VcnManager; import android.net.vcn.VcnManager.VcnErrorCode; import android.net.vcn.VcnManager.VcnStatusCode; import android.net.vcn.VcnUnderlyingNetworkPolicy; @@ -532,11 +531,12 @@ public class VcnManagementService extends IVcnManagementService.Stub { if (mVcns.containsKey(subscriptionGroup)) { final Vcn vcn = mVcns.get(subscriptionGroup); - final boolean isActive = vcn.isActive(); + final int status = vcn.getStatus(); vcn.updateConfig(config); + // TODO(b/183174340): Remove this once opportunistic-safe-mode is supported // Only notify VcnStatusCallbacks if this VCN was previously in Safe Mode - if (!isActive) { + if (status == VCN_STATUS_CODE_SAFE_MODE) { // TODO(b/181789060): invoke asynchronously after Vcn notifies through VcnCallback notifyAllPermissionedStatusCallbacksLocked( subscriptionGroup, VCN_STATUS_CODE_ACTIVE); @@ -769,7 +769,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { synchronized (mLock) { final Vcn vcn = mVcns.get(subGrp); if (vcn != null) { - if (vcn.isActive()) { + if (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE) { isVcnManagedNetwork = true; } @@ -880,20 +880,23 @@ public class VcnManagementService extends IVcnManagementService.Stub { // 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; + final int vcnStatus = + vcn == null ? VCN_STATUS_CODE_NOT_CONFIGURED : vcn.getStatus(); + final int resultStatus; if (vcnConfig == null || !isCallbackPermissioned(cbInfo, subGroup)) { - vcnStatus = VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED; + resultStatus = 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; + resultStatus = VCN_STATUS_CODE_INACTIVE; + } else if (vcnStatus == VCN_STATUS_CODE_ACTIVE + || vcnStatus == VCN_STATUS_CODE_SAFE_MODE) { + resultStatus = vcnStatus; } else { - // TODO(b/181789060): create Vcn.getStatus() and Log.WTF() for unknown status - vcnStatus = VcnManager.VCN_STATUS_CODE_SAFE_MODE; + Slog.wtf(TAG, "Unknown VCN status: " + vcnStatus); + resultStatus = VCN_STATUS_CODE_NOT_CONFIGURED; } try { - cbInfo.mCallback.onVcnStatusChanged(vcnStatus); + cbInfo.mCallback.onVcnStatusChanged(resultStatus); } catch (RemoteException e) { Slog.d(TAG, "VcnStatusCallback threw on VCN status change", e); } diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index 069c5c3fc7144..ab9de77005b30 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -118,7 +118,7 @@ public class UnderlyingNetworkTracker { if (!mIsQuitting) { mRouteSelectionCallback = new RouteSelectionCallback(); mConnectivityManager.requestBackgroundNetwork( - getBaseNetworkRequestBuilder().build(), mHandler, mRouteSelectionCallback); + getRouteSelectionRequest(), mHandler, mRouteSelectionCallback); mWifiBringupCallback = new NetworkBringupCallback(); mConnectivityManager.requestBackgroundNetwork( @@ -149,12 +149,48 @@ public class UnderlyingNetworkTracker { } } - private NetworkRequest getWifiNetworkRequest() { + /** + * Builds the Route selection request + * + *
This request is guaranteed to select carrier-owned, non-VCN underlying networks by virtue + * of a populated set of subIds as expressed in NetworkCapabilities#getSubIds(). Only carrier + * owned networks may be selected, as the request specifies only subIds in the VCN's + * subscription group, while the VCN networks are excluded by virtue of not having subIds set on + * the VCN-exposed networks. + */ + private NetworkRequest getRouteSelectionRequest() { return getBaseNetworkRequestBuilder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) .build(); } + /** + * Builds the WiFi bringup request + * + *
This request is built specifically to match only carrier-owned WiFi networks, but is also + * built to ONLY keep Carrier WiFi Networks alive (but never bring them up). This is a result of + * the WifiNetworkFactory not advertising a list of subIds, and therefore not accepting this + * request. As such, it will bind to a Carrier WiFi Network that has already been brought up, + * but will NEVER bring up a Carrier WiFi network itself. + */ + private NetworkRequest getWifiNetworkRequest() { + return getBaseNetworkRequestBuilder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) + .build(); + } + + /** + * Builds a Cellular bringup request for a given subId + * + *
This request is filed in order to ensure that the Telephony stack always has a + * NetworkRequest to bring up a VCN underlying cellular network. It is required in order to + * ensure that even when a VCN (appears as Cellular) satisfies the default request, Telephony + * will bring up additional underlying Cellular networks. + * + *
Since this request MUST make it to the TelephonyNetworkFactory, subIds are not specified + * in the NetworkCapabilities, but rather in the TelephonyNetworkSpecifier. + */ private NetworkRequest getCellNetworkRequestForSubId(int subId) { return getBaseNetworkRequestBuilder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) @@ -164,20 +200,13 @@ public class UnderlyingNetworkTracker { /** * Builds and returns a NetworkRequest builder common to all Underlying Network requests - * - *
This request is guaranteed to select carrier-owned, non-VCN underlying networks by virtue - * of a populated set of subIds as expressed in NetworkCapabilities#getSubIds(). Only carrier - * owned networks may be selected, as the request specifies only subIds in the VCN's - * subscription group, while the VCN networks are excluded by virtue of not having subIds set on - * the VCN-exposed networks. */ private NetworkRequest.Builder getBaseNetworkRequestBuilder() { return new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)); + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); } /** diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index c0130da7ddbca..54689358802f1 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -17,6 +17,9 @@ package com.android.server.vcn; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; +import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; +import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE; +import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; import static com.android.server.VcnManagementService.VDBG; @@ -44,7 +47,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; /** * Represents an single instance of a VCN. @@ -137,17 +139,14 @@ public class Vcn extends Handler { @NonNull private TelephonySubscriptionSnapshot mLastSnapshot; /** - * Whether this Vcn instance is active and running. + * The current status of this Vcn instance * - *
The value will be {@code true} while running. It will be {@code false} if the VCN has been - * shut down or has entered safe mode. - * - *
This AtomicBoolean is required in order to ensure consistency and correctness across - * multiple threads. Unlike the rest of the Vcn, this is queried synchronously on Binder threads - * from VcnManagementService, and therefore cannot rely on guarantees of running on the VCN - * Looper. + *
The value will be {@link VCN_STATUS_CODE_ACTIVE} while all VcnGatewayConnections are in
+ * good standing, {@link VCN_STATUS_CODE_SAFE_MODE} if any VcnGatewayConnections are in safe
+ * mode, and {@link VCN_STATUS_CODE_INACTIVE} once a teardown has been commanded.
*/
- private final AtomicBoolean mIsActive = new AtomicBoolean(true);
+ // Accessed from different threads, but always under lock in VcnManagementService
+ private volatile int mCurrentStatus = VCN_STATUS_CODE_ACTIVE;
public Vcn(
@NonNull VcnContext vcnContext,
@@ -199,9 +198,15 @@ public class Vcn extends Handler {
sendMessageAtFrontOfQueue(obtainMessage(MSG_CMD_TEARDOWN));
}
- /** Synchronously checks whether this Vcn is active. */
- public boolean isActive() {
- return mIsActive.get();
+ /** Synchronously retrieves the current status code. */
+ public int getStatus() {
+ return mCurrentStatus;
+ }
+
+ /** Sets the status of this VCN */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public void setStatus(int status) {
+ mCurrentStatus = status;
}
/** Get current Gateways for testing purposes */
@@ -217,12 +222,6 @@ public class Vcn extends Handler {
return Collections.unmodifiableMap(new HashMap<>(mVcnGatewayConnections));
}
- /** Set whether this Vcn is active for testing purposes */
- @VisibleForTesting(visibility = Visibility.PRIVATE)
- public void setIsActive(boolean isActive) {
- mIsActive.set(isActive);
- }
-
private class VcnNetworkRequestListener implements VcnNetworkProvider.NetworkRequestListener {
@Override
public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
@@ -264,7 +263,8 @@ public class Vcn extends Handler {
mConfig = config;
- if (mIsActive.getAndSet(true)) {
+ // TODO(b/183174340): Remove this once opportunistic safe mode is supported.
+ if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
// VCN is already active - teardown any GatewayConnections whose configs have been
// removed and get all current requests
for (final Entry