Skip to content
Snippets Groups Projects
Commit 0d8a9800 authored by Danuta Brotikovskaya's avatar Danuta Brotikovskaya Committed by Gerrit Code Review
Browse files

Merge "Implement NetworkRequestsState atom" into main

parents 16936828 e3245081
No related branches found
No related tags found
No related merge requests found
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.metrics;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_RECEIVED;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_REMOVED;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_UNKNOWN;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.SystemClock;
import com.android.net.module.util.BitUtils;
class NetworkRequestStateInfo {
private final NetworkRequest mNetworkRequest;
private final long mNetworkRequestReceivedTime;
private enum NetworkRequestState {
RECEIVED,
REMOVED
}
private NetworkRequestState mNetworkRequestState;
private int mNetworkRequestDurationMillis;
private final Dependencies mDependencies;
NetworkRequestStateInfo(NetworkRequest networkRequest,
Dependencies deps) {
mDependencies = deps;
mNetworkRequest = networkRequest;
mNetworkRequestReceivedTime = mDependencies.getElapsedRealtime();
mNetworkRequestDurationMillis = 0;
mNetworkRequestState = NetworkRequestState.RECEIVED;
}
public void setNetworkRequestRemoved() {
mNetworkRequestState = NetworkRequestState.REMOVED;
mNetworkRequestDurationMillis = (int) (
mDependencies.getElapsedRealtime() - mNetworkRequestReceivedTime);
}
public int getNetworkRequestStateStatsType() {
if (mNetworkRequestState == NetworkRequestState.RECEIVED) {
return NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_RECEIVED;
} else if (mNetworkRequestState == NetworkRequestState.REMOVED) {
return NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_REMOVED;
} else {
return NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_UNKNOWN;
}
}
public int getRequestId() {
return mNetworkRequest.requestId;
}
public int getPackageUid() {
return mNetworkRequest.networkCapabilities.getRequestorUid();
}
public int getTransportTypes() {
return (int) BitUtils.packBits(mNetworkRequest.networkCapabilities.getTransportTypes());
}
public boolean getNetCapabilityNotMetered() {
return mNetworkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
}
public boolean getNetCapabilityInternet() {
return mNetworkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
public int getNetworkRequestDurationMillis() {
return mNetworkRequestDurationMillis;
}
/** Dependency class */
public static class Dependencies {
// Returns a timestamp with the time base of SystemClock.elapsedRealtime to keep durations
// relative to start time and avoid timezone change, including time spent in deep sleep.
public long getElapsedRealtime() {
return SystemClock.elapsedRealtime();
}
}
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.metrics;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED;
import android.annotation.NonNull;
import android.net.NetworkRequest;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.ConnectivityStatsLog;
/**
* A Connectivity Service helper class to push atoms capturing network requests have been received
* and removed and its metadata.
*
* Atom events are logged in the ConnectivityStatsLog. Network request id: network request metadata
* hashmap is stored to calculate network request duration when it is removed.
*
* Note that this class is not thread-safe. The instance of the class needs to be
* synchronized in the callers when being used in multiple threads.
*/
public class NetworkRequestStateStatsMetrics {
private static final String TAG = "NetworkRequestStateStatsMetrics";
private static final int MSG_NETWORK_REQUEST_STATE_CHANGED = 0;
// 1 second internal is suggested by experiment team
private static final int ATOM_INTERVAL_MS = 1000;
private final SparseArray<NetworkRequestStateInfo> mNetworkRequestsActive;
private final Handler mStatsLoggingHandler;
private final Dependencies mDependencies;
private final NetworkRequestStateInfo.Dependencies mNRStateInfoDeps;
public NetworkRequestStateStatsMetrics() {
this(new Dependencies(), new NetworkRequestStateInfo.Dependencies());
}
@VisibleForTesting
NetworkRequestStateStatsMetrics(Dependencies deps,
NetworkRequestStateInfo.Dependencies nrStateInfoDeps) {
mNetworkRequestsActive = new SparseArray<>();
mDependencies = deps;
mNRStateInfoDeps = nrStateInfoDeps;
HandlerThread handlerThread = mDependencies.makeHandlerThread(TAG);
handlerThread.start();
mStatsLoggingHandler = new StatsLoggingHandler(handlerThread.getLooper());
}
/**
* Register network request receive event, push RECEIVE atom
*
* @param networkRequest network request received
*/
public void onNetworkRequestReceived(NetworkRequest networkRequest) {
if (mNetworkRequestsActive.contains(networkRequest.requestId)) {
Log.w(TAG, "Received already registered network request, id = "
+ networkRequest.requestId);
} else {
Log.d(TAG, "Registered nr with ID = " + networkRequest.requestId
+ ", package_uid = " + networkRequest.networkCapabilities.getRequestorUid());
NetworkRequestStateInfo networkRequestStateInfo = new NetworkRequestStateInfo(
networkRequest, mNRStateInfoDeps);
mNetworkRequestsActive.put(networkRequest.requestId, networkRequestStateInfo);
mStatsLoggingHandler.sendMessage(
Message.obtain(
mStatsLoggingHandler,
MSG_NETWORK_REQUEST_STATE_CHANGED,
networkRequestStateInfo));
}
}
/**
* Register network request remove event, push REMOVE atom
*
* @param networkRequest network request removed
*/
public void onNetworkRequestRemoved(NetworkRequest networkRequest) {
NetworkRequestStateInfo networkRequestStateInfo = mNetworkRequestsActive.get(
networkRequest.requestId);
if (networkRequestStateInfo == null) {
Log.w(TAG, "This NR hasn't been registered. NR id = " + networkRequest.requestId);
} else {
Log.d(TAG, "Removed nr with ID = " + networkRequest.requestId);
mNetworkRequestsActive.remove(networkRequest.requestId);
networkRequestStateInfo.setNetworkRequestRemoved();
mStatsLoggingHandler.sendMessage(
Message.obtain(
mStatsLoggingHandler,
MSG_NETWORK_REQUEST_STATE_CHANGED,
networkRequestStateInfo));
}
}
/** Dependency class */
public static class Dependencies {
/**
* Creates a thread with provided tag.
*
* @param tag for the thread.
*/
public HandlerThread makeHandlerThread(@NonNull final String tag) {
return new HandlerThread(tag);
}
/**
* Sleeps the thread for provided intervalMs millis.
*
* @param intervalMs number of millis for the thread sleep.
*/
public void threadSleep(int intervalMs) {
try {
Thread.sleep(intervalMs);
} catch (InterruptedException e) {
Log.w(TAG, "Cool down interrupted!", e);
}
}
/**
* Writes a NETWORK_REQUEST_STATE_CHANGED event to ConnectivityStatsLog.
*
* @param networkRequestStateInfo NetworkRequestStateInfo containing network request info.
*/
public void writeStats(NetworkRequestStateInfo networkRequestStateInfo) {
ConnectivityStatsLog.write(
NETWORK_REQUEST_STATE_CHANGED,
networkRequestStateInfo.getPackageUid(),
networkRequestStateInfo.getTransportTypes(),
networkRequestStateInfo.getNetCapabilityNotMetered(),
networkRequestStateInfo.getNetCapabilityInternet(),
networkRequestStateInfo.getNetworkRequestStateStatsType(),
networkRequestStateInfo.getNetworkRequestDurationMillis());
}
}
private class StatsLoggingHandler extends Handler {
private static final String TAG = "NetworkRequestsStateStatsLoggingHandler";
private long mLastLogTime = 0;
StatsLoggingHandler(Looper looper) {
super(looper);
}
private void checkStatsLoggingTimeout() {
// Cool down before next execution. Required by atom logging frequency.
long now = SystemClock.elapsedRealtime();
if (now - mLastLogTime < ATOM_INTERVAL_MS) {
mDependencies.threadSleep(ATOM_INTERVAL_MS);
}
mLastLogTime = now;
}
@Override
public void handleMessage(Message msg) {
NetworkRequestStateInfo loggingInfo;
switch (msg.what) {
case MSG_NETWORK_REQUEST_STATE_CHANGED:
checkStatsLoggingTimeout();
loggingInfo = (NetworkRequestStateInfo) msg.obj;
mDependencies.writeStats(loggingInfo);
break;
default: // fall out
}
}
}
}
......@@ -281,6 +281,7 @@ import com.android.metrics.NetworkCountPerTransports;
import com.android.metrics.NetworkDescription;
import com.android.metrics.NetworkList;
import com.android.metrics.NetworkRequestCount;
import com.android.metrics.NetworkRequestStateStatsMetrics;
import com.android.metrics.RequestCountForType;
import com.android.modules.utils.BasicShellCommandHandler;
import com.android.modules.utils.build.SdkLevel;
......@@ -941,6 +942,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
 
private final IpConnectivityLog mMetricsLog;
 
private final NetworkRequestStateStatsMetrics mNetworkRequestStateStatsMetrics;
@GuardedBy("mBandwidthRequests")
private final SparseArray<Integer> mBandwidthRequests = new SparseArray<>(10);
 
......@@ -1421,6 +1424,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
return new AutomaticOnOffKeepaliveTracker(c, h);
}
 
/**
* @see NetworkRequestStateStatsMetrics
*/
public NetworkRequestStateStatsMetrics makeNetworkRequestStateStatsMetrics(
Context context) {
// We currently have network requests metric for Watch devices only
if (context.getPackageManager().hasSystemFeature(FEATURE_WATCH)) {
return new NetworkRequestStateStatsMetrics();
} else {
return null;
}
}
/**
* @see BatteryStatsManager
*/
......@@ -1654,6 +1670,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
new RequestInfoPerUidCounter(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1);
 
mMetricsLog = logger;
mNetworkRequestStateStatsMetrics = mDeps.makeNetworkRequestStateStatsMetrics(mContext);
final NetworkRequest defaultInternetRequest = createDefaultRequest();
mDefaultRequest = new NetworkRequestInfo(
Process.myUid(), defaultInternetRequest, null,
......@@ -5324,6 +5341,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateSignalStrengthThresholds(network, "REGISTER", req);
}
}
} else if (req.isRequest() && mNetworkRequestStateStatsMetrics != null) {
mNetworkRequestStateStatsMetrics.onNetworkRequestReceived(req);
}
}
 
......@@ -5541,6 +5560,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
if (req.isListen()) {
removeListenRequestFromNetworks(req);
} else if (req.isRequest() && mNetworkRequestStateStatsMetrics != null) {
mNetworkRequestStateStatsMetrics.onNetworkRequestRemoved(req);
}
}
nri.unlinkDeathRecipient();
......
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.metrics;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_RECEIVED;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_REMOVED;
import static org.junit.Assert.assertEquals;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkRequestStateInfoTest {
@Mock
private NetworkRequestStateInfo.Dependencies mDependencies;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testSetNetworkRequestRemoved() {
final long nrStartTime = 1L;
final long nrEndTime = 101L;
NetworkRequest notMeteredWifiNetworkRequest = new NetworkRequest(
new NetworkCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, true),
0, 1, NetworkRequest.Type.REQUEST
);
// This call will be used to calculate NR received time
Mockito.when(mDependencies.getElapsedRealtime()).thenReturn(nrStartTime);
NetworkRequestStateInfo mNetworkRequestStateInfo = new NetworkRequestStateInfo(
notMeteredWifiNetworkRequest, mDependencies);
// This call will be used to calculate NR removed time
Mockito.when(mDependencies.getElapsedRealtime()).thenReturn(nrEndTime);
mNetworkRequestStateInfo.setNetworkRequestRemoved();
assertEquals(
nrEndTime - nrStartTime,
mNetworkRequestStateInfo.getNetworkRequestDurationMillis());
assertEquals(mNetworkRequestStateInfo.getNetworkRequestStateStatsType(),
NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_REMOVED);
}
@Test
public void testCheckInitialState() {
NetworkRequestStateInfo mNetworkRequestStateInfo = new NetworkRequestStateInfo(
new NetworkRequest(new NetworkCapabilities(), 0, 1, NetworkRequest.Type.REQUEST),
mDependencies);
assertEquals(mNetworkRequestStateInfo.getNetworkRequestStateStatsType(),
NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_RECEIVED);
}
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.metrics;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_RECEIVED;
import static com.android.server.ConnectivityStatsLog.NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_REMOVED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.HandlerThread;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.testutils.HandlerUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class NetworkRequestStateStatsMetricsTest {
@Mock
private NetworkRequestStateStatsMetrics.Dependencies mNRStateStatsDeps;
@Mock
private NetworkRequestStateInfo.Dependencies mNRStateInfoDeps;
@Captor
private ArgumentCaptor<NetworkRequestStateInfo> mNetworkRequestStateInfoCaptor;
private NetworkRequestStateStatsMetrics mNetworkRequestStateStatsMetrics;
private HandlerThread mHandlerThread;
private static final int TEST_REQUEST_ID = 10;
private static final int TEST_PACKAGE_UID = 20;
private static final int TIMEOUT_MS = 30_000;
private static final NetworkRequest NOT_METERED_WIFI_NETWORK_REQUEST = new NetworkRequest(
new NetworkCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, true)
.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, false)
.setRequestorUid(TEST_PACKAGE_UID),
0, TEST_REQUEST_ID, NetworkRequest.Type.REQUEST
);
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mHandlerThread = new HandlerThread("NetworkRequestStateStatsMetrics");
Mockito.when(mNRStateStatsDeps.makeHandlerThread("NetworkRequestStateStatsMetrics"))
.thenReturn(mHandlerThread);
mNetworkRequestStateStatsMetrics = new NetworkRequestStateStatsMetrics(
mNRStateStatsDeps, mNRStateInfoDeps);
}
@Test
public void testNetworkRequestReceivedRemoved() {
final long nrStartTime = 1L;
final long nrEndTime = 101L;
// This call will be used to calculate NR received time
Mockito.when(mNRStateInfoDeps.getElapsedRealtime()).thenReturn(nrStartTime);
mNetworkRequestStateStatsMetrics.onNetworkRequestReceived(NOT_METERED_WIFI_NETWORK_REQUEST);
HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
verify(mNRStateStatsDeps, times(1))
.writeStats(mNetworkRequestStateInfoCaptor.capture());
NetworkRequestStateInfo nrStateInfoSent = mNetworkRequestStateInfoCaptor.getValue();
assertEquals(NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_RECEIVED,
nrStateInfoSent.getNetworkRequestStateStatsType());
assertEquals(NOT_METERED_WIFI_NETWORK_REQUEST.requestId, nrStateInfoSent.getRequestId());
assertEquals(TEST_PACKAGE_UID, nrStateInfoSent.getPackageUid());
assertEquals(1 << NetworkCapabilities.TRANSPORT_WIFI, nrStateInfoSent.getTransportTypes());
assertTrue(nrStateInfoSent.getNetCapabilityNotMetered());
assertFalse(nrStateInfoSent.getNetCapabilityInternet());
assertEquals(0, nrStateInfoSent.getNetworkRequestDurationMillis());
clearInvocations(mNRStateStatsDeps);
// This call will be used to calculate NR removed time
Mockito.when(mNRStateInfoDeps.getElapsedRealtime()).thenReturn(nrEndTime);
mNetworkRequestStateStatsMetrics.onNetworkRequestRemoved(NOT_METERED_WIFI_NETWORK_REQUEST);
HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
verify(mNRStateStatsDeps, times(1))
.writeStats(mNetworkRequestStateInfoCaptor.capture());
nrStateInfoSent = mNetworkRequestStateInfoCaptor.getValue();
assertEquals(NETWORK_REQUEST_STATE_CHANGED__STATE__NETWORK_REQUEST_STATE_REMOVED,
nrStateInfoSent.getNetworkRequestStateStatsType());
assertEquals(NOT_METERED_WIFI_NETWORK_REQUEST.requestId, nrStateInfoSent.getRequestId());
assertEquals(TEST_PACKAGE_UID, nrStateInfoSent.getPackageUid());
assertEquals(1 << NetworkCapabilities.TRANSPORT_WIFI, nrStateInfoSent.getTransportTypes());
assertTrue(nrStateInfoSent.getNetCapabilityNotMetered());
assertFalse(nrStateInfoSent.getNetCapabilityInternet());
assertEquals(nrEndTime - nrStartTime, nrStateInfoSent.getNetworkRequestDurationMillis());
}
@Test
public void testUnreceivedNetworkRequestRemoved() {
mNetworkRequestStateStatsMetrics.onNetworkRequestRemoved(NOT_METERED_WIFI_NETWORK_REQUEST);
HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
verify(mNRStateStatsDeps, never())
.writeStats(any(NetworkRequestStateInfo.class));
}
@Test
public void testExistingNetworkRequestReceived() {
mNetworkRequestStateStatsMetrics.onNetworkRequestReceived(NOT_METERED_WIFI_NETWORK_REQUEST);
HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
verify(mNRStateStatsDeps, times(1))
.writeStats(any(NetworkRequestStateInfo.class));
clearInvocations(mNRStateStatsDeps);
mNetworkRequestStateStatsMetrics.onNetworkRequestReceived(NOT_METERED_WIFI_NETWORK_REQUEST);
HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
verify(mNRStateStatsDeps, never())
.writeStats(any(NetworkRequestStateInfo.class));
}
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import android.os.Process
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkCallback
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.argThat
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class CSNetworkRequestStateStatsMetricsTests : CSTest() {
private val CELL_INTERNET_NOT_METERED_NC = NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
.build().setRequestorUidAndPackageName(Process.myUid(), context.getPackageName())
private val CELL_INTERNET_NOT_METERED_NR = NetworkRequest.Builder()
.setCapabilities(CELL_INTERNET_NOT_METERED_NC).build()
@Before
fun setup() {
waitForIdle()
clearInvocations(networkRequestStateStatsMetrics)
}
@Test
fun testRequestTypeNRProduceMetrics() {
cm.requestNetwork(CELL_INTERNET_NOT_METERED_NR, TestableNetworkCallback())
waitForIdle()
verify(networkRequestStateStatsMetrics).onNetworkRequestReceived(
argThat{req -> req.networkCapabilities.equals(
CELL_INTERNET_NOT_METERED_NR.networkCapabilities)})
}
@Test
fun testListenTypeNRProduceNoMetrics() {
cm.registerNetworkCallback(CELL_INTERNET_NOT_METERED_NR, TestableNetworkCallback())
waitForIdle()
verify(networkRequestStateStatsMetrics, never()).onNetworkRequestReceived(any())
}
@Test
fun testRemoveRequestTypeNRProduceMetrics() {
val cb = TestableNetworkCallback()
cm.requestNetwork(CELL_INTERNET_NOT_METERED_NR, cb)
waitForIdle()
clearInvocations(networkRequestStateStatsMetrics)
cm.unregisterNetworkCallback(cb)
waitForIdle()
verify(networkRequestStateStatsMetrics).onNetworkRequestRemoved(
argThat{req -> req.networkCapabilities.equals(
CELL_INTERNET_NOT_METERED_NR.networkCapabilities)})
}
}
......@@ -54,6 +54,7 @@ import android.util.ArraySet
import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.app.IBatteryStats
import com.android.internal.util.test.BroadcastInterceptingContext
import com.android.metrics.NetworkRequestStateStatsMetrics
import com.android.modules.utils.build.SdkLevel
import com.android.net.module.util.ArrayTrackRecord
import com.android.networkstack.apishim.common.UnsupportedApiLevelException
......@@ -157,6 +158,7 @@ open class CSTest {
val netd = mock<INetd>()
val bpfNetMaps = mock<BpfNetMaps>()
val clatCoordinator = mock<ClatCoordinator>()
val networkRequestStateStatsMetrics = mock<NetworkRequestStateStatsMetrics>()
val proxyTracker = ProxyTracker(context, mock<Handler>(), 16 /* EVENT_PROXY_HAS_CHANGED */)
val alarmManager = makeMockAlarmManager()
val systemConfigManager = makeMockSystemConfigManager()
......@@ -197,6 +199,9 @@ open class CSTest {
MultinetworkPolicyTracker(c, h, r,
MultinetworkPolicyTrackerTestDependencies(connResources.get()))
override fun makeNetworkRequestStateStatsMetrics(c: Context) =
this@CSTest.networkRequestStateStatsMetrics
// All queried features must be mocked, because the test cannot hold the
// READ_DEVICE_CONFIG permission and device config utils use static methods for
// checking permissions.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment