Log validated underlying network count that's available for VCN underlying network selection

Flag: EXEMPT METRICS
Test: atest FrameworksVcnTests, CtsVcnTestCases
Bug: 288600040
Change-Id: Ia1b51aa64388bc5c167f3a1081d8683d98fe0bef
This commit is contained in:
Hnin Naing 2025-09-11 23:46:54 +00:00
commit 4ab80490ae
5 changed files with 74 additions and 5 deletions

View file

@ -834,6 +834,7 @@ public class VcnGatewayConnection extends StateMachine {
mDeps.newUnderlyingNetworkController( mDeps.newUnderlyingNetworkController(
mVcnContext, mVcnContext,
mConnectionConfig, mConnectionConfig,
mId,
subscriptionGroup, subscriptionGroup,
mLastSnapshot, mLastSnapshot,
mUnderlyingNetworkControllerCallback); mUnderlyingNetworkControllerCallback);
@ -2815,11 +2816,17 @@ public class VcnGatewayConnection extends StateMachine {
public UnderlyingNetworkController newUnderlyingNetworkController( public UnderlyingNetworkController newUnderlyingNetworkController(
VcnContext vcnContext, VcnContext vcnContext,
VcnGatewayConnectionConfig connectionConfig, VcnGatewayConnectionConfig connectionConfig,
int gatewayConnectionId,
ParcelUuid subscriptionGroup, ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot, TelephonySubscriptionSnapshot snapshot,
UnderlyingNetworkControllerCallback callback) { UnderlyingNetworkControllerCallback callback) {
return new UnderlyingNetworkController( return new UnderlyingNetworkController(
vcnContext, connectionConfig, subscriptionGroup, snapshot, callback); vcnContext,
connectionConfig,
gatewayConnectionId,
subscriptionGroup,
snapshot,
callback);
} }
/** Builds a new IkeSession. */ /** Builds a new IkeSession. */

View file

@ -16,7 +16,6 @@
package com.android.server.vcn.metrics; package com.android.server.vcn.metrics;
import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED;
import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED__GW_TEARDOWN_REASON__GATEWAY_TEARDOWN_REASON_INTERNAL_ERROR; import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED__GW_TEARDOWN_REASON__GATEWAY_TEARDOWN_REASON_INTERNAL_ERROR;
import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED__GW_TEARDOWN_REASON__GATEWAY_TEARDOWN_REASON_NETWORK_AGENT_UNWANTED; import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED__GW_TEARDOWN_REASON__GATEWAY_TEARDOWN_REASON_NETWORK_AGENT_UNWANTED;
import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED__GW_TEARDOWN_REASON__GATEWAY_TEARDOWN_REASON_NONE; import static com.android.server.vcn.metrics.VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED__GW_TEARDOWN_REASON__GATEWAY_TEARDOWN_REASON_NONE;
@ -56,7 +55,7 @@ public class VcnMetrics {
/** Log an atom when a VcnGatewayConnection has entered safe mode. */ /** Log an atom when a VcnGatewayConnection has entered safe mode. */
public void logEnterSafeMode(int gatewayConnectionId) { public void logEnterSafeMode(int gatewayConnectionId) {
VcnStatsLog.write( VcnStatsLog.write(
VCN_GATEWAY_CONNECTION_STATE_CHANGED, VcnStatsLog.VCN_GATEWAY_CONNECTION_STATE_CHANGED,
gatewayConnectionId, gatewayConnectionId,
GATEWAY_TEARDOWN_REASON_NONE, GATEWAY_TEARDOWN_REASON_NONE,
true /* isInSafeMode */); true /* isInSafeMode */);
@ -125,4 +124,12 @@ public class VcnMetrics {
true /* isConnected */, true /* isConnected */,
false /* isValidated */); false /* isValidated */);
} }
/**
* Log an atom about number of validated underlying network available for VCN network selection.
*/
public void logValidatedUnderlyingNetworkCount(int gatewayConnectionId, int count) {
VcnStatsLog.write(
VcnStatsLog.VCN_UNDERLYING_NETWORKS_STATE_CHANGED, gatewayConnectionId, count);
}
} }

View file

@ -56,6 +56,7 @@ import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.HandlerExecutor;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext; import com.android.server.vcn.VcnContext;
import com.android.server.vcn.metrics.VcnMetrics;
import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback; import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
import java.util.ArrayList; import java.util.ArrayList;
@ -105,19 +106,31 @@ public class UnderlyingNetworkController {
@Nullable private UnderlyingNetworkRecord mCurrentRecord; @Nullable private UnderlyingNetworkRecord mCurrentRecord;
@Nullable private UnderlyingNetworkRecord.Builder mRecordInProgress; @Nullable private UnderlyingNetworkRecord.Builder mRecordInProgress;
private final int mGatewayConnectionId;
private final VcnMetrics mVcnMetrics;
public UnderlyingNetworkController( public UnderlyingNetworkController(
@NonNull VcnContext vcnContext, @NonNull VcnContext vcnContext,
@NonNull VcnGatewayConnectionConfig connectionConfig, @NonNull VcnGatewayConnectionConfig connectionConfig,
int gatewayConnectionId,
@NonNull ParcelUuid subscriptionGroup, @NonNull ParcelUuid subscriptionGroup,
@NonNull TelephonySubscriptionSnapshot snapshot, @NonNull TelephonySubscriptionSnapshot snapshot,
@NonNull UnderlyingNetworkControllerCallback cb) { @NonNull UnderlyingNetworkControllerCallback cb) {
this(vcnContext, connectionConfig, subscriptionGroup, snapshot, cb, new Dependencies()); this(
vcnContext,
connectionConfig,
gatewayConnectionId,
subscriptionGroup,
snapshot,
cb,
new Dependencies());
} }
@VisibleForTesting(visibility = Visibility.PRIVATE) @VisibleForTesting(visibility = Visibility.PRIVATE)
UnderlyingNetworkController( UnderlyingNetworkController(
@NonNull VcnContext vcnContext, @NonNull VcnContext vcnContext,
@NonNull VcnGatewayConnectionConfig connectionConfig, @NonNull VcnGatewayConnectionConfig connectionConfig,
int gatewayConnectionId,
@NonNull ParcelUuid subscriptionGroup, @NonNull ParcelUuid subscriptionGroup,
@NonNull TelephonySubscriptionSnapshot snapshot, @NonNull TelephonySubscriptionSnapshot snapshot,
@NonNull UnderlyingNetworkControllerCallback cb, @NonNull UnderlyingNetworkControllerCallback cb,
@ -128,6 +141,8 @@ public class UnderlyingNetworkController {
mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot"); mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
mCb = Objects.requireNonNull(cb, "Missing cb"); mCb = Objects.requireNonNull(cb, "Missing cb");
mDeps = Objects.requireNonNull(deps, "Missing deps"); mDeps = Objects.requireNonNull(deps, "Missing deps");
mGatewayConnectionId = gatewayConnectionId;
mVcnMetrics = mDeps.newVcnMetrics();
mHandler = new Handler(mVcnContext.getLooper()); mHandler = new Handler(mVcnContext.getLooper());
@ -468,6 +483,9 @@ public class UnderlyingNetworkController {
.getContext() .getContext()
.getSystemService(TelephonyManager.class) .getSystemService(TelephonyManager.class)
.unregisterTelephonyCallback(mActiveDataSubIdListener); .unregisterTelephonyCallback(mActiveDataSubIdListener);
// Log empty validated network count left, as a clean up state.
mVcnMetrics.logValidatedUnderlyingNetworkCount(mGatewayConnectionId, 0);
} }
private TreeSet<UnderlyingNetworkEvaluator> getSortedUnderlyingNetworks() { private TreeSet<UnderlyingNetworkEvaluator> getSortedUnderlyingNetworks() {
@ -489,6 +507,7 @@ public class UnderlyingNetworkController {
} }
TreeSet<UnderlyingNetworkEvaluator> sorted = getSortedUnderlyingNetworks(); TreeSet<UnderlyingNetworkEvaluator> sorted = getSortedUnderlyingNetworks();
mVcnMetrics.logValidatedUnderlyingNetworkCount(mGatewayConnectionId, sorted.size());
UnderlyingNetworkEvaluator candidateEvaluator = sorted.isEmpty() ? null : sorted.first(); UnderlyingNetworkEvaluator candidateEvaluator = sorted.isEmpty() ? null : sorted.first();
UnderlyingNetworkRecord candidate = UnderlyingNetworkRecord candidate =
@ -734,7 +753,9 @@ public class UnderlyingNetworkController {
} }
@VisibleForTesting(visibility = Visibility.PRIVATE) @VisibleForTesting(visibility = Visibility.PRIVATE)
/* External dependencies, for injection in tests */
public static class Dependencies { public static class Dependencies {
/** Builds a new UnderlyingNetworkEvaluator. */
public UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator( public UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator(
@NonNull VcnContext vcnContext, @NonNull VcnContext vcnContext,
@NonNull Network network, @NonNull Network network,
@ -752,5 +773,10 @@ public class UnderlyingNetworkController {
carrierConfig, carrierConfig,
evaluatorCallback); evaluatorCallback);
} }
/** Builds a new VcnMetrics. */
public VcnMetrics newVcnMetrics() {
return new VcnMetrics();
}
} }
} }

View file

@ -25,6 +25,7 @@ import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.atLeastOnce;
@ -228,7 +229,7 @@ public class VcnGatewayConnectionTestBase {
doReturn(mUnderlyingNetworkController) doReturn(mUnderlyingNetworkController)
.when(mDeps) .when(mDeps)
.newUnderlyingNetworkController(any(), any(), any(), any(), any()); .newUnderlyingNetworkController(any(), any(), anyInt(), any(), any(), any());
doReturn(mVcnMetrics).when(mDeps).newVcnMetrics(); doReturn(mVcnMetrics).when(mDeps).newVcnMetrics();
doReturn(mWakeLock) doReturn(mWakeLock)
.when(mDeps) .when(mDeps)

View file

@ -71,6 +71,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext; import com.android.server.vcn.VcnContext;
import com.android.server.vcn.VcnNetworkProvider; import com.android.server.vcn.VcnNetworkProvider;
import com.android.server.vcn.metrics.VcnMetrics;
import com.android.server.vcn.routeselection.UnderlyingNetworkController.Dependencies; import com.android.server.vcn.routeselection.UnderlyingNetworkController.Dependencies;
import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback; import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback;
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback; import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
@ -100,6 +101,7 @@ public class UnderlyingNetworkControllerTest {
private static final int INITIAL_SUB_ID_1 = 1; private static final int INITIAL_SUB_ID_1 = 1;
private static final int INITIAL_SUB_ID_2 = 2; private static final int INITIAL_SUB_ID_2 = 2;
private static final int UPDATED_SUB_ID = 3; private static final int UPDATED_SUB_ID = 3;
private static final int GATEWAY_CONNECTION_ID = 1234;
private static final Set<Integer> INITIAL_SUB_IDS = private static final Set<Integer> INITIAL_SUB_IDS =
new ArraySet<>(Arrays.asList(INITIAL_SUB_ID_1, INITIAL_SUB_ID_2)); new ArraySet<>(Arrays.asList(INITIAL_SUB_ID_1, INITIAL_SUB_ID_2));
@ -164,6 +166,7 @@ public class UnderlyingNetworkControllerTest {
@Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb; @Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb;
@Mock private NetworkEvaluatorCallback mEvaluatorCallback; @Mock private NetworkEvaluatorCallback mEvaluatorCallback;
@Mock private Network mNetwork; @Mock private Network mNetwork;
@Mock private VcnMetrics mVcnMetrics;
@Spy private Dependencies mDependencies = new Dependencies(); @Spy private Dependencies mDependencies = new Dependencies();
@ -218,11 +221,13 @@ public class UnderlyingNetworkControllerTest {
doReturn(mNetworkEvaluator) doReturn(mNetworkEvaluator)
.when(mDependencies) .when(mDependencies)
.newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any()); .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any());
doReturn(mVcnMetrics).when(mDependencies).newVcnMetrics();
mUnderlyingNetworkController = mUnderlyingNetworkController =
new UnderlyingNetworkController( new UnderlyingNetworkController(
mVcnContext, mVcnContext,
VcnGatewayConnectionConfigTest.buildTestConfig(), VcnGatewayConnectionConfigTest.buildTestConfig(),
GATEWAY_CONNECTION_ID,
SUB_GROUP, SUB_GROUP,
mSubscriptionSnapshot, mSubscriptionSnapshot,
mNetworkControllerCb, mNetworkControllerCb,
@ -268,6 +273,7 @@ public class UnderlyingNetworkControllerTest {
new UnderlyingNetworkController( new UnderlyingNetworkController(
vcnContext, vcnContext,
VcnGatewayConnectionConfigTest.buildTestConfig(), VcnGatewayConnectionConfigTest.buildTestConfig(),
GATEWAY_CONNECTION_ID,
SUB_GROUP, SUB_GROUP,
mSubscriptionSnapshot, mSubscriptionSnapshot,
mNetworkControllerCb); mNetworkControllerCb);
@ -320,6 +326,7 @@ public class UnderlyingNetworkControllerTest {
new UnderlyingNetworkController( new UnderlyingNetworkController(
mVcnContext, mVcnContext,
VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates), VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
GATEWAY_CONNECTION_ID,
SUB_GROUP, SUB_GROUP,
mSubscriptionSnapshot, mSubscriptionSnapshot,
mNetworkControllerCb); mNetworkControllerCb);
@ -361,6 +368,7 @@ public class UnderlyingNetworkControllerTest {
new UnderlyingNetworkController( new UnderlyingNetworkController(
mVcnContext, mVcnContext,
VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates), VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
GATEWAY_CONNECTION_ID,
SUB_GROUP, SUB_GROUP,
mSubscriptionSnapshot, mSubscriptionSnapshot,
mNetworkControllerCb); mNetworkControllerCb);
@ -515,6 +523,7 @@ public class UnderlyingNetworkControllerTest {
.unregisterNetworkCallback(any(NetworkBringupCallback.class)); .unregisterNetworkCallback(any(NetworkBringupCallback.class));
verify(mConnectivityManager) verify(mConnectivityManager)
.unregisterNetworkCallback(any(UnderlyingNetworkListener.class)); .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
verify(mVcnMetrics).logValidatedUnderlyingNetworkCount(eq(GATEWAY_CONNECTION_ID), eq(0));
} }
private static UnderlyingNetworkRecord getTestNetworkRecord( private static UnderlyingNetworkRecord getTestNetworkRecord(
@ -780,6 +789,7 @@ public class UnderlyingNetworkControllerTest {
new UnderlyingNetworkController( new UnderlyingNetworkController(
mVcnContext, mVcnContext,
VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates), VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
GATEWAY_CONNECTION_ID,
SUB_GROUP, SUB_GROUP,
mSubscriptionSnapshot, mSubscriptionSnapshot,
mNetworkControllerCb, mNetworkControllerCb,
@ -834,6 +844,24 @@ public class UnderlyingNetworkControllerTest {
verify(expectedEvaluator, never()).setIsSelected(eq(true), any(), any(), any(), any()); verify(expectedEvaluator, never()).setIsSelected(eq(true), any(), any(), any(), any());
} }
@Test
public void testValidatedUnderlyingNetworkCountsLogged() {
final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();
networkTemplates.add(CELL_TEMPLATE_DUN);
networkTemplates.add(CELL_TEMPLATE_CBS);
// Bring up CBS network
UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
bringupNetworkAndGetEvaluator(cb, CBS_NETWORK_CAPABILITIES, networkTemplates);
verify(mVcnMetrics).logValidatedUnderlyingNetworkCount(eq(GATEWAY_CONNECTION_ID), eq(1));
// Bring up DUN network
bringupNetworkAndGetEvaluator(cb, DUN_NETWORK_CAPABILITIES, networkTemplates);
verify(mVcnMetrics).logValidatedUnderlyingNetworkCount(eq(GATEWAY_CONNECTION_ID), eq(2));
}
@Test @Test
public void testSelectMorePreferredNetwork() { public void testSelectMorePreferredNetwork() {
final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList(); final List<VcnUnderlyingNetworkTemplate> networkTemplates = new ArrayList();