• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.networkstack.tethering.metrics;
18 
19 import static android.app.usage.NetworkStats.Bucket.STATE_ALL;
20 import static android.app.usage.NetworkStats.Bucket.TAG_NONE;
21 import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
22 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
23 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
24 import static android.net.NetworkCapabilities.TRANSPORT_LOWPAN;
25 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
26 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
27 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
28 import static android.net.NetworkStats.METERED_NO;
29 import static android.net.NetworkStats.ROAMING_NO;
30 import static android.net.NetworkStats.SET_DEFAULT;
31 import static android.net.NetworkStats.UID_TETHERING;
32 import static android.net.NetworkTemplate.MATCH_BLUETOOTH;
33 import static android.net.NetworkTemplate.MATCH_ETHERNET;
34 import static android.net.NetworkTemplate.MATCH_MOBILE;
35 import static android.net.NetworkTemplate.MATCH_WIFI;
36 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
37 import static android.net.TetheringManager.TETHERING_ETHERNET;
38 import static android.net.TetheringManager.TETHERING_NCM;
39 import static android.net.TetheringManager.TETHERING_USB;
40 import static android.net.TetheringManager.TETHERING_WIFI;
41 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
42 import static android.net.TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
43 import static android.net.TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR;
44 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
45 import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
46 import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
47 import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
48 import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
49 import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
50 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
51 import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
52 import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
53 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
54 import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
55 import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
56 import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
57 import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
58 import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
59 import static android.stats.connectivity.UpstreamType.UT_BLUETOOTH;
60 import static android.stats.connectivity.UpstreamType.UT_CELLULAR;
61 import static android.stats.connectivity.UpstreamType.UT_ETHERNET;
62 import static android.stats.connectivity.UpstreamType.UT_WIFI;
63 
64 import static com.android.networkstack.tethering.metrics.TetheringMetrics.EMPTY;
65 import static com.android.testutils.NetworkStatsUtilsKt.makePublicStatsFromAndroidNetStats;
66 
67 import static org.junit.Assert.assertEquals;
68 import static org.junit.Assert.assertNull;
69 import static org.mockito.ArgumentMatchers.any;
70 import static org.mockito.ArgumentMatchers.eq;
71 import static org.mockito.Mockito.doReturn;
72 import static org.mockito.Mockito.doAnswer;
73 import static org.mockito.Mockito.verify;
74 
75 import android.app.usage.NetworkStatsManager;
76 import android.content.Context;
77 import android.net.NetworkCapabilities;
78 import android.net.NetworkStats;
79 import android.net.NetworkTemplate;
80 import android.os.Build;
81 import android.os.Handler;
82 import android.os.HandlerThread;
83 import android.stats.connectivity.DownstreamType;
84 import android.stats.connectivity.ErrorCode;
85 import android.stats.connectivity.UpstreamType;
86 import android.stats.connectivity.UserType;
87 import android.util.ArrayMap;
88 
89 import androidx.test.filters.SmallTest;
90 
91 import com.android.networkstack.tethering.UpstreamNetworkState;
92 import com.android.networkstack.tethering.metrics.TetheringMetrics.DataUsage;
93 import com.android.networkstack.tethering.metrics.TetheringMetrics.Dependencies;
94 import com.android.testutils.DevSdkIgnoreRule;
95 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
96 import com.android.testutils.DevSdkIgnoreRunner;
97 import com.android.testutils.HandlerUtils;
98 
99 import org.junit.After;
100 import org.junit.Before;
101 import org.junit.Rule;
102 import org.junit.Test;
103 import org.junit.runner.RunWith;
104 import org.mockito.Mock;
105 import org.mockito.MockitoAnnotations;
106 
107 @DevSdkIgnoreRunner.MonitorThreadLeak
108 @RunWith(DevSdkIgnoreRunner.class)
109 @SmallTest
110 public final class TetheringMetricsTest {
111     @Rule public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
112 
113     private static final String TEST_CALLER_PKG = "com.test.caller.pkg";
114     private static final String SETTINGS_PKG = "com.android.settings";
115     private static final String SYSTEMUI_PKG = "com.android.systemui";
116     private static final String GMS_PKG = "com.google.android.gms";
117     private static final long TEST_START_TIME = 1670395936033L;
118     private static final long SECOND_IN_MILLIS = 1_000L;
119     private static final long DEFAULT_TIMEOUT = 2000L;
120     private static final int MATCH_NONE = -1;
121 
122     @Mock private Context mContext;
123     @Mock private Dependencies mDeps;
124     @Mock private NetworkStatsManager mNetworkStatsManager;
125 
126     private TetheringMetrics mTetheringMetrics;
127     private final NetworkTetheringReported.Builder mStatsBuilder =
128             NetworkTetheringReported.newBuilder();
129     private final ArrayMap<UpstreamType, DataUsage> mMockUpstreamUsageBaseline = new ArrayMap<>();
130     private HandlerThread mThread;
131     private Handler mHandler;
132 
133     private long mElapsedRealtime;
134 
currentTimeMillis()135     private long currentTimeMillis() {
136         return TEST_START_TIME + mElapsedRealtime;
137     }
138 
incrementCurrentTime(final long duration)139     private void incrementCurrentTime(final long duration) {
140         mElapsedRealtime += duration;
141         final long currentTimeMillis = currentTimeMillis();
142         doReturn(currentTimeMillis).when(mDeps).timeNow();
143     }
144 
getElapsedRealtime()145     private long getElapsedRealtime() {
146         return mElapsedRealtime;
147     }
148 
clearElapsedRealtime()149     private void clearElapsedRealtime() {
150         mElapsedRealtime = 0;
151         doReturn(TEST_START_TIME).when(mDeps).timeNow();
152     }
153 
154     @Before
setUp()155     public void setUp() throws Exception {
156         MockitoAnnotations.initMocks(this);
157         doReturn(TEST_START_TIME).when(mDeps).timeNow();
158         doReturn(mNetworkStatsManager).when(mContext).getSystemService(NetworkStatsManager.class);
159         mThread = new HandlerThread("TetheringMetricsTest");
160         mThread.start();
161         mHandler = new Handler(mThread.getLooper());
162         doReturn(mHandler).when(mDeps).createHandler();
163         // Set up the usage for upstream types.
164         mMockUpstreamUsageBaseline.put(UT_CELLULAR, new DataUsage(100L, 200L));
165         mMockUpstreamUsageBaseline.put(UT_WIFI, new DataUsage(400L, 800L));
166         mMockUpstreamUsageBaseline.put(UT_BLUETOOTH, new DataUsage(50L, 80L));
167         mMockUpstreamUsageBaseline.put(UT_ETHERNET, new DataUsage(0L, 0L));
168         doAnswer(inv -> {
169             final NetworkTemplate template = (NetworkTemplate) inv.getArguments()[0];
170             final DataUsage dataUsage = mMockUpstreamUsageBaseline.getOrDefault(
171                     matchRuleToUpstreamType(template.getMatchRule()), new DataUsage(0L, 0L));
172             return makeNetworkStatsWithTxRxBytes(dataUsage);
173         }).when(mNetworkStatsManager).queryDetailsForUidTagState(any(), eq(Long.MIN_VALUE),
174                 eq(Long.MAX_VALUE), eq(UID_TETHERING), eq(TAG_NONE), eq(STATE_ALL));
175         mTetheringMetrics = new TetheringMetrics(mContext, mDeps);
176         mElapsedRealtime = 0L;
177     }
178 
179     @After
tearDown()180     public void tearDown() throws Exception {
181         if (mThread != null) {
182             mThread.quitSafely();
183             mThread.join();
184         }
185     }
186 
verifyReport(final DownstreamType downstream, final ErrorCode error, final UserType user, final UpstreamEvents.Builder upstreamEvents, final long duration)187     private void verifyReport(final DownstreamType downstream, final ErrorCode error,
188             final UserType user, final UpstreamEvents.Builder upstreamEvents, final long duration)
189             throws Exception {
190         final NetworkTetheringReported expectedReport =
191                 mStatsBuilder.setDownstreamType(downstream)
192                 .setUserType(user)
193                 .setUpstreamType(UpstreamType.UT_UNKNOWN)
194                 .setErrorCode(error)
195                 .setUpstreamEvents(upstreamEvents)
196                 .setDurationMillis(duration)
197                 .build();
198         verify(mDeps).write(expectedReport);
199     }
200 
runAndWaitForIdle(Runnable r)201     private void runAndWaitForIdle(Runnable r) {
202         r.run();
203         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
204     }
205 
updateErrorAndSendReport(final int downstream, final int error)206     private void updateErrorAndSendReport(final int downstream, final int error) {
207         mTetheringMetrics.updateErrorCode(downstream, error);
208         mTetheringMetrics.sendReport(downstream);
209         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
210     }
211 
buildUpstreamCapabilities(final int[] transports)212     private static NetworkCapabilities buildUpstreamCapabilities(final int[] transports) {
213         final NetworkCapabilities nc = new NetworkCapabilities();
214         for (int type: transports) {
215             nc.addTransportType(type);
216         }
217         return nc;
218     }
219 
buildUpstreamState(final int... transports)220     private static UpstreamNetworkState buildUpstreamState(final int... transports) {
221         return new UpstreamNetworkState(
222                 null,
223                 buildUpstreamCapabilities(transports),
224                 null);
225     }
226 
addUpstreamEvent(UpstreamEvents.Builder upstreamEvents, final UpstreamType expectedResult, final long duration, final long txBytes, final long rxBytes)227     private void addUpstreamEvent(UpstreamEvents.Builder upstreamEvents,
228             final UpstreamType expectedResult, final long duration, final long txBytes,
229                     final long rxBytes) {
230         UpstreamEvent.Builder upstreamEvent = UpstreamEvent.newBuilder()
231                 .setUpstreamType(expectedResult)
232                 .setDurationMillis(duration)
233                 .setTxBytes(txBytes)
234                 .setRxBytes(rxBytes);
235         upstreamEvents.addUpstreamEvent(upstreamEvent);
236     }
237 
runDownstreamTypesTest(final int type, final DownstreamType expectedResult)238     private void runDownstreamTypesTest(final int type, final DownstreamType expectedResult)
239             throws Exception {
240         mTetheringMetrics = new TetheringMetrics(mContext, mDeps);
241         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(type, TEST_CALLER_PKG));
242         final long duration = 2 * SECOND_IN_MILLIS;
243         incrementCurrentTime(duration);
244         UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
245         // Set UpstreamType as NO_NETWORK because the upstream type has not been changed.
246         addUpstreamEvent(upstreamEvents, UpstreamType.UT_NO_NETWORK, duration, 0L, 0L);
247         updateErrorAndSendReport(type, TETHER_ERROR_NO_ERROR);
248 
249         verifyReport(expectedResult, ErrorCode.EC_NO_ERROR, UserType.USER_UNKNOWN,
250                 upstreamEvents, getElapsedRealtime());
251         clearElapsedRealtime();
252     }
253 
254     @Test
testDownstreamTypes()255     public void testDownstreamTypes() throws Exception {
256         runDownstreamTypesTest(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI);
257         runDownstreamTypesTest(TETHERING_WIFI_P2P, DownstreamType.DS_TETHERING_WIFI_P2P);
258         runDownstreamTypesTest(TETHERING_BLUETOOTH, DownstreamType.DS_TETHERING_BLUETOOTH);
259         runDownstreamTypesTest(TETHERING_USB, DownstreamType.DS_TETHERING_USB);
260         runDownstreamTypesTest(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM);
261         runDownstreamTypesTest(TETHERING_ETHERNET, DownstreamType.DS_TETHERING_ETHERNET);
262     }
263 
runErrorCodesTest(final int errorCode, final ErrorCode expectedResult)264     private void runErrorCodesTest(final int errorCode, final ErrorCode expectedResult)
265             throws Exception {
266         mTetheringMetrics = new TetheringMetrics(mContext, mDeps);
267         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG));
268         runAndWaitForIdle(() ->
269                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI)));
270         final long duration = 2 * SECOND_IN_MILLIS;
271         incrementCurrentTime(duration);
272         updateErrorAndSendReport(TETHERING_WIFI, errorCode);
273 
274         UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
275         addUpstreamEvent(upstreamEvents, UT_WIFI, duration, 0L, 0L);
276         verifyReport(DownstreamType.DS_TETHERING_WIFI, expectedResult, UserType.USER_UNKNOWN,
277                     upstreamEvents, getElapsedRealtime());
278         clearElapsedRealtime();
279     }
280 
281     @Test
testErrorCodes()282     public void testErrorCodes() throws Exception {
283         runErrorCodesTest(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR);
284         runErrorCodesTest(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE);
285         runErrorCodesTest(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL);
286         runErrorCodesTest(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED);
287         runErrorCodesTest(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE);
288         runErrorCodesTest(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR);
289         runErrorCodesTest(TETHER_ERROR_TETHER_IFACE_ERROR, ErrorCode.EC_TETHER_IFACE_ERROR);
290         runErrorCodesTest(TETHER_ERROR_UNTETHER_IFACE_ERROR, ErrorCode.EC_UNTETHER_IFACE_ERROR);
291         runErrorCodesTest(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
292                 ErrorCode.EC_ENABLE_FORWARDING_ERROR);
293         runErrorCodesTest(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
294                 ErrorCode.EC_DISABLE_FORWARDING_ERROR);
295         runErrorCodesTest(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR);
296         runErrorCodesTest(TETHER_ERROR_PROVISIONING_FAILED, ErrorCode.EC_PROVISIONING_FAILED);
297         runErrorCodesTest(TETHER_ERROR_DHCPSERVER_ERROR, ErrorCode.EC_DHCPSERVER_ERROR);
298         runErrorCodesTest(TETHER_ERROR_ENTITLEMENT_UNKNOWN, ErrorCode.EC_ENTITLEMENT_UNKNOWN);
299         runErrorCodesTest(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
300                 ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION);
301         runErrorCodesTest(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
302                 ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION);
303         runErrorCodesTest(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE);
304     }
305 
runUserTypesTest(final String callerPkg, final UserType expectedResult)306     private void runUserTypesTest(final String callerPkg, final UserType expectedResult)
307             throws Exception {
308         mTetheringMetrics = new TetheringMetrics(mContext, mDeps);
309         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, callerPkg));
310         final long duration = 1 * SECOND_IN_MILLIS;
311         incrementCurrentTime(duration);
312         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
313 
314         UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
315         // Set UpstreamType as NO_NETWORK because the upstream type has not been changed.
316         addUpstreamEvent(upstreamEvents, UpstreamType.UT_NO_NETWORK, duration, 0L, 0L);
317         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR, expectedResult,
318                     upstreamEvents, getElapsedRealtime());
319         clearElapsedRealtime();
320     }
321 
322     @Test
testUserTypes()323     public void testUserTypes() throws Exception {
324         runUserTypesTest(TEST_CALLER_PKG, UserType.USER_UNKNOWN);
325         runUserTypesTest(SETTINGS_PKG, UserType.USER_SETTINGS);
326         runUserTypesTest(SYSTEMUI_PKG, UserType.USER_SYSTEMUI);
327         runUserTypesTest(GMS_PKG, UserType.USER_GMS);
328     }
329 
runUpstreamTypesTest(final UpstreamNetworkState ns, final UpstreamType expectedResult)330     private void runUpstreamTypesTest(final UpstreamNetworkState ns,
331             final UpstreamType expectedResult) throws Exception {
332         mTetheringMetrics = new TetheringMetrics(mContext, mDeps);
333         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG));
334         runAndWaitForIdle(() -> mTetheringMetrics.maybeUpdateUpstreamType(ns));
335         final long duration = 2 * SECOND_IN_MILLIS;
336         incrementCurrentTime(duration);
337         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
338 
339         UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
340         addUpstreamEvent(upstreamEvents, expectedResult, duration, 0L, 0L);
341         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
342                 UserType.USER_UNKNOWN, upstreamEvents, getElapsedRealtime());
343         clearElapsedRealtime();
344     }
345 
346     @Test
testUpstreamTypes()347     public void testUpstreamTypes() throws Exception {
348         runUpstreamTypesTest(null , UpstreamType.UT_NO_NETWORK);
349         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_CELLULAR), UT_CELLULAR);
350         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_WIFI), UT_WIFI);
351         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_BLUETOOTH), UT_BLUETOOTH);
352         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_ETHERNET), UT_ETHERNET);
353         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_WIFI_AWARE), UpstreamType.UT_WIFI_AWARE);
354         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_LOWPAN), UpstreamType.UT_LOWPAN);
355         runUpstreamTypesTest(buildUpstreamState(TRANSPORT_CELLULAR, TRANSPORT_WIFI,
356                 TRANSPORT_BLUETOOTH), UpstreamType.UT_UNKNOWN);
357     }
358 
359     @Test
testMultiBuildersCreatedBeforeSendReport()360     public void testMultiBuildersCreatedBeforeSendReport() throws Exception {
361         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG));
362         final long wifiTetheringStartTime = currentTimeMillis();
363         incrementCurrentTime(1 * SECOND_IN_MILLIS);
364         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_USB, SYSTEMUI_PKG));
365         final long usbTetheringStartTime = currentTimeMillis();
366         incrementCurrentTime(2 * SECOND_IN_MILLIS);
367         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_BLUETOOTH, GMS_PKG));
368         final long bluetoothTetheringStartTime = currentTimeMillis();
369         incrementCurrentTime(3 * SECOND_IN_MILLIS);
370         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_DHCPSERVER_ERROR);
371 
372         UpstreamEvents.Builder wifiTetheringUpstreamEvents = UpstreamEvents.newBuilder();
373         addUpstreamEvent(wifiTetheringUpstreamEvents, UpstreamType.UT_NO_NETWORK,
374                 currentTimeMillis() - wifiTetheringStartTime, 0L, 0L);
375         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_DHCPSERVER_ERROR,
376                 UserType.USER_SETTINGS, wifiTetheringUpstreamEvents,
377                 currentTimeMillis() - wifiTetheringStartTime);
378         incrementCurrentTime(1 * SECOND_IN_MILLIS);
379         updateErrorAndSendReport(TETHERING_USB, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
380 
381         UpstreamEvents.Builder usbTetheringUpstreamEvents = UpstreamEvents.newBuilder();
382         addUpstreamEvent(usbTetheringUpstreamEvents, UpstreamType.UT_NO_NETWORK,
383                 currentTimeMillis() - usbTetheringStartTime, 0L, 0L);
384 
385         verifyReport(DownstreamType.DS_TETHERING_USB, ErrorCode.EC_ENABLE_FORWARDING_ERROR,
386                 UserType.USER_SYSTEMUI, usbTetheringUpstreamEvents,
387                 currentTimeMillis() - usbTetheringStartTime);
388         incrementCurrentTime(1 * SECOND_IN_MILLIS);
389         updateErrorAndSendReport(TETHERING_BLUETOOTH, TETHER_ERROR_TETHER_IFACE_ERROR);
390 
391         UpstreamEvents.Builder bluetoothTetheringUpstreamEvents = UpstreamEvents.newBuilder();
392         addUpstreamEvent(bluetoothTetheringUpstreamEvents, UpstreamType.UT_NO_NETWORK,
393                 currentTimeMillis() - bluetoothTetheringStartTime, 0L, 0L);
394         verifyReport(DownstreamType.DS_TETHERING_BLUETOOTH, ErrorCode.EC_TETHER_IFACE_ERROR,
395                 UserType.USER_GMS, bluetoothTetheringUpstreamEvents,
396                 currentTimeMillis() - bluetoothTetheringStartTime);
397     }
398 
399     @Test
testUpstreamsWithMultipleDownstreams()400     public void testUpstreamsWithMultipleDownstreams() throws Exception {
401         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG));
402         final long wifiTetheringStartTime = currentTimeMillis();
403         incrementCurrentTime(1 * SECOND_IN_MILLIS);
404         runAndWaitForIdle(() ->
405                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI)));
406         final long wifiUpstreamStartTime = currentTimeMillis();
407         incrementCurrentTime(5 * SECOND_IN_MILLIS);
408         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_USB, SYSTEMUI_PKG));
409         final long usbTetheringStartTime = currentTimeMillis();
410         incrementCurrentTime(5 * SECOND_IN_MILLIS);
411         updateErrorAndSendReport(TETHERING_USB, TETHER_ERROR_NO_ERROR);
412 
413         UpstreamEvents.Builder usbTetheringUpstreamEvents = UpstreamEvents.newBuilder();
414         addUpstreamEvent(usbTetheringUpstreamEvents, UT_WIFI,
415                 currentTimeMillis() - usbTetheringStartTime, 0L, 0L);
416         verifyReport(DownstreamType.DS_TETHERING_USB, ErrorCode.EC_NO_ERROR,
417                 UserType.USER_SYSTEMUI, usbTetheringUpstreamEvents,
418                 currentTimeMillis() - usbTetheringStartTime);
419         incrementCurrentTime(7 * SECOND_IN_MILLIS);
420         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
421 
422         UpstreamEvents.Builder wifiTetheringUpstreamEvents = UpstreamEvents.newBuilder();
423         addUpstreamEvent(wifiTetheringUpstreamEvents, UT_WIFI,
424                 currentTimeMillis() - wifiUpstreamStartTime, 0L, 0L);
425         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
426                 UserType.USER_SETTINGS, wifiTetheringUpstreamEvents,
427                 currentTimeMillis() - wifiTetheringStartTime);
428     }
429 
430     @Test
testSwitchingMultiUpstreams()431     public void testSwitchingMultiUpstreams() throws Exception {
432         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG));
433         final long wifiTetheringStartTime = currentTimeMillis();
434         incrementCurrentTime(1 * SECOND_IN_MILLIS);
435         runAndWaitForIdle(() ->
436                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI)));
437         final long wifiDuration = 5 * SECOND_IN_MILLIS;
438         incrementCurrentTime(wifiDuration);
439         runAndWaitForIdle(() ->
440                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_BLUETOOTH)));
441         final long bluetoothDuration = 15 * SECOND_IN_MILLIS;
442         incrementCurrentTime(bluetoothDuration);
443         runAndWaitForIdle(() ->
444                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_CELLULAR)));
445         final long celltoothDuration = 20 * SECOND_IN_MILLIS;
446         incrementCurrentTime(celltoothDuration);
447         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
448 
449         UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
450         addUpstreamEvent(upstreamEvents, UT_WIFI, wifiDuration, 0L, 0L);
451         addUpstreamEvent(upstreamEvents, UT_BLUETOOTH, bluetoothDuration, 0L, 0L);
452         addUpstreamEvent(upstreamEvents, UT_CELLULAR, celltoothDuration, 0L, 0L);
453 
454         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
455                 UserType.USER_SETTINGS, upstreamEvents,
456                 currentTimeMillis() - wifiTetheringStartTime);
457     }
458 
runUsageSupportedForUpstreamTypeTest(final UpstreamType upstreamType, final boolean isSupported)459     private void runUsageSupportedForUpstreamTypeTest(final UpstreamType upstreamType,
460             final boolean isSupported) {
461         final boolean result = TetheringMetrics.isUsageSupportedForUpstreamType(upstreamType);
462         assertEquals(isSupported, result);
463     }
464 
465     @Test
testUsageSupportedForUpstreamTypeTest()466     public void testUsageSupportedForUpstreamTypeTest() {
467         runUsageSupportedForUpstreamTypeTest(UT_CELLULAR, true /* isSupported */);
468         runUsageSupportedForUpstreamTypeTest(UT_WIFI, true /* isSupported */);
469         runUsageSupportedForUpstreamTypeTest(UT_BLUETOOTH, true /* isSupported */);
470         runUsageSupportedForUpstreamTypeTest(UT_ETHERNET, true /* isSupported */);
471         runUsageSupportedForUpstreamTypeTest(UpstreamType.UT_WIFI_AWARE, false /* isSupported */);
472         runUsageSupportedForUpstreamTypeTest(UpstreamType.UT_LOWPAN, false /* isSupported */);
473         runUsageSupportedForUpstreamTypeTest(UpstreamType.UT_UNKNOWN, false /* isSupported */);
474     }
475 
runBuildNetworkTemplateForUpstreamType(final UpstreamType upstreamType, final int matchRule)476     private void runBuildNetworkTemplateForUpstreamType(final UpstreamType upstreamType,
477             final int matchRule)  {
478         final NetworkTemplate template =
479                 TetheringMetrics.buildNetworkTemplateForUpstreamType(upstreamType);
480         if (matchRule == MATCH_NONE) {
481             assertNull(template);
482         } else {
483             assertEquals(matchRule, template.getMatchRule());
484         }
485     }
486 
487     @Test
488     @IgnoreUpTo(Build.VERSION_CODES.S_V2)
testBuildNetworkTemplateForUpstreamType()489     public void testBuildNetworkTemplateForUpstreamType() {
490         runBuildNetworkTemplateForUpstreamType(UT_CELLULAR, MATCH_MOBILE);
491         runBuildNetworkTemplateForUpstreamType(UT_WIFI, MATCH_WIFI);
492         runBuildNetworkTemplateForUpstreamType(UT_BLUETOOTH, MATCH_BLUETOOTH);
493         runBuildNetworkTemplateForUpstreamType(UT_ETHERNET, MATCH_ETHERNET);
494         runBuildNetworkTemplateForUpstreamType(UpstreamType.UT_WIFI_AWARE, MATCH_NONE);
495         runBuildNetworkTemplateForUpstreamType(UpstreamType.UT_LOWPAN, MATCH_NONE);
496         runBuildNetworkTemplateForUpstreamType(UpstreamType.UT_UNKNOWN, MATCH_NONE);
497     }
498 
verifyEmptyUsageForAllUpstreamTypes()499     private void verifyEmptyUsageForAllUpstreamTypes() {
500         mHandler.post(() -> {
501             for (UpstreamType type : UpstreamType.values()) {
502                 assertEquals(EMPTY, mTetheringMetrics.getLastReportedUsageFromUpstreamType(type));
503             }
504         });
505         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
506     }
507 
508     @Test
testInitializeUpstreamDataUsageBeforeT()509     public void testInitializeUpstreamDataUsageBeforeT() {
510         // Verify the usage is empty for all upstream types before initialization.
511         verifyEmptyUsageForAllUpstreamTypes();
512 
513         // Verify the usage is still empty after initialization if sdk is lower than T.
514         doReturn(false).when(mDeps).isUpstreamDataUsageMetricsEnabled(any());
515         runAndWaitForIdle(() -> mTetheringMetrics.initUpstreamUsageBaseline());
516         verifyEmptyUsageForAllUpstreamTypes();
517     }
518 
makeNetworkStatsWithTxRxBytes(DataUsage dataUsage)519     private android.app.usage.NetworkStats makeNetworkStatsWithTxRxBytes(DataUsage dataUsage) {
520         final NetworkStats testAndroidNetStats =
521                 new NetworkStats(0L /* elapsedRealtime */, 1 /* initialSize */).addEntry(
522                         new NetworkStats.Entry("test", 10001, SET_DEFAULT, TAG_NONE,
523                                 METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, dataUsage.rxBytes,
524                                 10, dataUsage.txBytes, 10, 10));
525         return makePublicStatsFromAndroidNetStats(testAndroidNetStats);
526     }
527 
matchRuleToUpstreamType(int matchRule)528     private static UpstreamType matchRuleToUpstreamType(int matchRule) {
529         switch (matchRule) {
530             case MATCH_MOBILE:
531                 return UT_CELLULAR;
532             case MATCH_WIFI:
533                 return UT_WIFI;
534             case MATCH_BLUETOOTH:
535                 return UT_BLUETOOTH;
536             case MATCH_ETHERNET:
537                 return UT_ETHERNET;
538             default:
539                 return UpstreamType.UT_UNKNOWN;
540         }
541     }
542 
initializeUpstreamUsageBaseline()543     private void initializeUpstreamUsageBaseline() {
544         doReturn(true).when(mDeps).isUpstreamDataUsageMetricsEnabled(any());
545         runAndWaitForIdle(() -> mTetheringMetrics.initUpstreamUsageBaseline());
546     }
547 
548     @Test
549     @IgnoreUpTo(Build.VERSION_CODES.S_V2)
testInitUpstreamUsageBaselineAndCleanup()550     public void testInitUpstreamUsageBaselineAndCleanup() {
551         // Verify the usage is empty for all upstream types before initialization.
552         verifyEmptyUsageForAllUpstreamTypes();
553 
554         // Verify the usage has been initialized
555         initializeUpstreamUsageBaseline();
556 
557         mHandler.post(() -> {
558             for (UpstreamType type : UpstreamType.values()) {
559                 final DataUsage dataUsage =
560                         mTetheringMetrics.getLastReportedUsageFromUpstreamType(type);
561                 if (TetheringMetrics.isUsageSupportedForUpstreamType(type)) {
562                     assertEquals(mMockUpstreamUsageBaseline.get(type), dataUsage);
563                 } else {
564                     assertEquals(EMPTY, dataUsage);
565                 }
566             }
567         });
568         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
569 
570         // Verify the usage is empty after clean up
571         runAndWaitForIdle(() -> mTetheringMetrics.cleanup());
572         verifyEmptyUsageForAllUpstreamTypes();
573     }
574 
updateUpstreamDataUsage(UpstreamType type, long usageDiff)575     private void updateUpstreamDataUsage(UpstreamType type, long usageDiff) {
576         final DataUsage oldWifiUsage = mMockUpstreamUsageBaseline.get(type);
577         final DataUsage newWifiUsage = new DataUsage(
578                 oldWifiUsage.txBytes + usageDiff,
579                 oldWifiUsage.rxBytes + usageDiff);
580         mMockUpstreamUsageBaseline.put(type, newWifiUsage);
581     }
582 
583     @Test
584     @IgnoreUpTo(Build.VERSION_CODES.S_V2)
testDataUsageCalculation()585     public void testDataUsageCalculation() throws Exception {
586         initializeUpstreamUsageBaseline();
587         runAndWaitForIdle(() -> mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG));
588         final long wifiTetheringStartTime = currentTimeMillis();
589         incrementCurrentTime(1 * SECOND_IN_MILLIS);
590 
591         // Change the upstream to Wi-Fi and update the data usage
592         runAndWaitForIdle(() ->
593                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI)));
594         final long wifiDuration = 5 * SECOND_IN_MILLIS;
595         final long wifiUsageDiff = 100L;
596         incrementCurrentTime(wifiDuration);
597         updateUpstreamDataUsage(UT_WIFI, wifiUsageDiff);
598 
599         // Change the upstream to bluetooth and update the data usage
600         runAndWaitForIdle(() ->
601                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_BLUETOOTH)));
602         final long bluetoothDuration = 15 * SECOND_IN_MILLIS;
603         final long btUsageDiff = 50L;
604         incrementCurrentTime(bluetoothDuration);
605         updateUpstreamDataUsage(UT_BLUETOOTH, btUsageDiff);
606 
607         // Change the upstream to cellular and update the data usage
608         runAndWaitForIdle(() ->
609                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_CELLULAR)));
610         final long cellDuration = 20 * SECOND_IN_MILLIS;
611         final long cellUsageDiff = 500L;
612         incrementCurrentTime(cellDuration);
613         updateUpstreamDataUsage(UT_CELLULAR, cellUsageDiff);
614 
615         // Change the upstream back to Wi-FI and update the data usage
616         runAndWaitForIdle(() ->
617                 mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI)));
618         final long wifiDuration2 = 50 * SECOND_IN_MILLIS;
619         final long wifiUsageDiff2 = 1000L;
620         incrementCurrentTime(wifiDuration2);
621         updateUpstreamDataUsage(UT_WIFI, wifiUsageDiff2);
622 
623         // Stop tethering and verify that the data usage is uploaded.
624         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
625         UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
626         addUpstreamEvent(upstreamEvents, UT_WIFI, wifiDuration, wifiUsageDiff, wifiUsageDiff);
627         addUpstreamEvent(upstreamEvents, UT_BLUETOOTH, bluetoothDuration, btUsageDiff, btUsageDiff);
628         addUpstreamEvent(upstreamEvents, UT_CELLULAR, cellDuration, cellUsageDiff, cellUsageDiff);
629         addUpstreamEvent(upstreamEvents, UT_WIFI, wifiDuration2, wifiUsageDiff2, wifiUsageDiff2);
630         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
631                 UserType.USER_SETTINGS, upstreamEvents,
632                 currentTimeMillis() - wifiTetheringStartTime);
633     }
634 }
635