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