Injecting tethering stats into statsd
Fill in downstream type, upstream type, error code and user type to NetworkTetheringReported. Bug: 153942334 Test: m, flash and boot Test: atest TetheringMetricsTest Change-Id: I6ba7d9e512b1ada519f44f9f3a95667e4b0f03c0
This commit is contained in:
parent
a14bd2a032
commit
7ecded8248
3 changed files with 390 additions and 0 deletions
|
|
@ -33,6 +33,7 @@ java_defaults {
|
|||
":framework-connectivity-shared-srcs",
|
||||
":tethering-module-utils-srcs",
|
||||
":services-tethering-shared-srcs",
|
||||
":statslog-tethering-java-gen",
|
||||
],
|
||||
static_libs: [
|
||||
"androidx.annotation_annotation",
|
||||
|
|
@ -223,3 +224,11 @@ java_library_static {
|
|||
apex_available: ["com.android.tethering"],
|
||||
min_sdk_version: "30",
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "statslog-tethering-java-gen",
|
||||
tools: ["stats-log-api-gen"],
|
||||
cmd: "$(location stats-log-api-gen) --java $(out) --module network_tethering" +
|
||||
" --javaPackage com.android.networkstack.tethering.metrics --javaClass TetheringStatsLog",
|
||||
out: ["com/android/networkstack/tethering/metrics/TetheringStatsLog.java"],
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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.networkstack.tethering.metrics;
|
||||
|
||||
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.TetheringManager.TETHERING_ETHERNET;
|
||||
import static android.net.TetheringManager.TETHERING_NCM;
|
||||
import static android.net.TetheringManager.TETHERING_USB;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
|
||||
|
||||
import android.stats.connectivity.DownstreamType;
|
||||
import android.stats.connectivity.ErrorCode;
|
||||
import android.stats.connectivity.UpstreamType;
|
||||
import android.stats.connectivity.UserType;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Collection of utilities for tethering metrics.
|
||||
*
|
||||
* To see if the logs are properly sent to statsd, execute following commands
|
||||
*
|
||||
* $ adb shell cmd stats print-logs
|
||||
* $ adb logcat | grep statsd OR $ adb logcat -b stats
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class TetheringMetrics {
|
||||
private static final String TAG = TetheringMetrics.class.getSimpleName();
|
||||
private static final boolean DBG = false;
|
||||
private static final String SETTINGS_PKG_NAME = "com.android.settings";
|
||||
private static final String SYSTEMUI_PKG_NAME = "com.android.systemui";
|
||||
private static final String GMS_PKG_NAME = "com.google.android.gms";
|
||||
private final SparseArray<NetworkTetheringReported.Builder> mBuilderMap = new SparseArray<>();
|
||||
|
||||
/** Update Tethering stats about caller's package name and downstream type. */
|
||||
public void createBuilder(final int downstreamType, final String callerPkg) {
|
||||
mBuilderMap.clear();
|
||||
NetworkTetheringReported.Builder statsBuilder =
|
||||
NetworkTetheringReported.newBuilder();
|
||||
statsBuilder.setDownstreamType(downstreamTypeToEnum(downstreamType))
|
||||
.setUserType(userTypeToEnum(callerPkg))
|
||||
.setUpstreamType(UpstreamType.UT_UNKNOWN)
|
||||
.setErrorCode(ErrorCode.EC_NO_ERROR)
|
||||
.build();
|
||||
mBuilderMap.put(downstreamType, statsBuilder);
|
||||
}
|
||||
|
||||
/** Update error code of given downstreamType. */
|
||||
public void updateErrorCode(final int downstreamType, final int errCode) {
|
||||
NetworkTetheringReported.Builder statsBuilder = mBuilderMap.get(downstreamType);
|
||||
if (statsBuilder == null) {
|
||||
Log.e(TAG, "Given downstreamType does not exist, this is a bug!");
|
||||
return;
|
||||
}
|
||||
statsBuilder.setErrorCode(errorCodeToEnum(errCode));
|
||||
}
|
||||
|
||||
/** Remove Tethering stats.
|
||||
* If Tethering stats is ready to write then write it before removing.
|
||||
*/
|
||||
public void sendReport(final int downstreamType) {
|
||||
final NetworkTetheringReported.Builder statsBuilder =
|
||||
mBuilderMap.get(downstreamType);
|
||||
if (statsBuilder == null) {
|
||||
Log.e(TAG, "Given downstreamType does not exist, this is a bug!");
|
||||
return;
|
||||
}
|
||||
write(statsBuilder.build());
|
||||
mBuilderMap.remove(downstreamType);
|
||||
}
|
||||
|
||||
/** Collect Tethering stats and write metrics data to statsd pipeline. */
|
||||
@VisibleForTesting
|
||||
public void write(@NonNull final NetworkTetheringReported reported) {
|
||||
TetheringStatsLog.write(TetheringStatsLog.NETWORK_TETHERING_REPORTED,
|
||||
reported.getErrorCode().getNumber(),
|
||||
reported.getDownstreamType().getNumber(),
|
||||
reported.getUpstreamType().getNumber(),
|
||||
reported.getUserType().getNumber());
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Write errorCode: " + reported.getErrorCode().getNumber()
|
||||
+ ", downstreamType: " + reported.getDownstreamType().getNumber()
|
||||
+ ", upstreamType: " + reported.getUpstreamType().getNumber()
|
||||
+ ", userType: " + reported.getUserType().getNumber());
|
||||
}
|
||||
}
|
||||
|
||||
/** Map {@link TetheringType} to {@link DownstreamType} */
|
||||
private DownstreamType downstreamTypeToEnum(final int ifaceType) {
|
||||
switch(ifaceType) {
|
||||
case TETHERING_WIFI:
|
||||
return DownstreamType.DS_TETHERING_WIFI;
|
||||
case TETHERING_WIFI_P2P:
|
||||
return DownstreamType.DS_TETHERING_WIFI_P2P;
|
||||
case TETHERING_USB:
|
||||
return DownstreamType.DS_TETHERING_USB;
|
||||
case TETHERING_BLUETOOTH:
|
||||
return DownstreamType.DS_TETHERING_BLUETOOTH;
|
||||
case TETHERING_NCM:
|
||||
return DownstreamType.DS_TETHERING_NCM;
|
||||
case TETHERING_ETHERNET:
|
||||
return DownstreamType.DS_TETHERING_ETHERNET;
|
||||
default:
|
||||
return DownstreamType.DS_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/** Map {@link StartTetheringError} to {@link ErrorCode} */
|
||||
private ErrorCode errorCodeToEnum(final int lastError) {
|
||||
switch(lastError) {
|
||||
case TETHER_ERROR_NO_ERROR:
|
||||
return ErrorCode.EC_NO_ERROR;
|
||||
case TETHER_ERROR_UNKNOWN_IFACE:
|
||||
return ErrorCode.EC_UNKNOWN_IFACE;
|
||||
case TETHER_ERROR_SERVICE_UNAVAIL:
|
||||
return ErrorCode.EC_SERVICE_UNAVAIL;
|
||||
case TETHER_ERROR_UNSUPPORTED:
|
||||
return ErrorCode.EC_UNSUPPORTED;
|
||||
case TETHER_ERROR_UNAVAIL_IFACE:
|
||||
return ErrorCode.EC_UNAVAIL_IFACE;
|
||||
case TETHER_ERROR_INTERNAL_ERROR:
|
||||
return ErrorCode.EC_INTERNAL_ERROR;
|
||||
case TETHER_ERROR_TETHER_IFACE_ERROR:
|
||||
return ErrorCode.EC_TETHER_IFACE_ERROR;
|
||||
case TETHER_ERROR_UNTETHER_IFACE_ERROR:
|
||||
return ErrorCode.EC_UNTETHER_IFACE_ERROR;
|
||||
case TETHER_ERROR_ENABLE_FORWARDING_ERROR:
|
||||
return ErrorCode.EC_ENABLE_FORWARDING_ERROR;
|
||||
case TETHER_ERROR_DISABLE_FORWARDING_ERROR:
|
||||
return ErrorCode.EC_DISABLE_FORWARDING_ERROR;
|
||||
case TETHER_ERROR_IFACE_CFG_ERROR:
|
||||
return ErrorCode.EC_IFACE_CFG_ERROR;
|
||||
case TETHER_ERROR_PROVISIONING_FAILED:
|
||||
return ErrorCode.EC_PROVISIONING_FAILED;
|
||||
case TETHER_ERROR_DHCPSERVER_ERROR:
|
||||
return ErrorCode.EC_DHCPSERVER_ERROR;
|
||||
case TETHER_ERROR_ENTITLEMENT_UNKNOWN:
|
||||
return ErrorCode.EC_ENTITLEMENT_UNKNOWN;
|
||||
case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
|
||||
return ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION;
|
||||
case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
|
||||
return ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION;
|
||||
default:
|
||||
return ErrorCode.EC_UNKNOWN_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
/** Map callerPkg to {@link UserType} */
|
||||
private UserType userTypeToEnum(final String callerPkg) {
|
||||
if (callerPkg.equals(SETTINGS_PKG_NAME)) {
|
||||
return UserType.USER_SETTINGS;
|
||||
} else if (callerPkg.equals(SYSTEMUI_PKG_NAME)) {
|
||||
return UserType.USER_SYSTEMUI;
|
||||
} else if (callerPkg.equals(GMS_PKG_NAME)) {
|
||||
return UserType.USER_GMS;
|
||||
} else {
|
||||
return UserType.USER_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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.networkstack.tethering.metrics;
|
||||
|
||||
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.TetheringManager.TETHERING_ETHERNET;
|
||||
import static android.net.TetheringManager.TETHERING_NCM;
|
||||
import static android.net.TetheringManager.TETHERING_USB;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
|
||||
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.stats.connectivity.DownstreamType;
|
||||
import android.stats.connectivity.ErrorCode;
|
||||
import android.stats.connectivity.UpstreamType;
|
||||
import android.stats.connectivity.UserType;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public final class TetheringMetricsTest {
|
||||
private static final String TEST_CALLER_PKG = "com.test.caller.pkg";
|
||||
private static final String SETTINGS_PKG = "com.android.settings";
|
||||
private static final String SYSTEMUI_PKG = "com.android.systemui";
|
||||
private static final String GMS_PKG = "com.google.android.gms";
|
||||
private TetheringMetrics mTetheringMetrics;
|
||||
|
||||
private final NetworkTetheringReported.Builder mStatsBuilder =
|
||||
NetworkTetheringReported.newBuilder();
|
||||
|
||||
private class MockTetheringMetrics extends TetheringMetrics {
|
||||
@Override
|
||||
public void write(final NetworkTetheringReported reported) { }
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTetheringMetrics = spy(new MockTetheringMetrics());
|
||||
}
|
||||
|
||||
private void runDownstreamTypesTest(final Pair<Integer, DownstreamType>... testPairs)
|
||||
throws Exception {
|
||||
for (Pair<Integer, DownstreamType> testPair : testPairs) {
|
||||
final int type = testPair.first;
|
||||
final DownstreamType expectedResult = testPair.second;
|
||||
|
||||
mTetheringMetrics.createBuilder(type, TEST_CALLER_PKG);
|
||||
mTetheringMetrics.updateErrorCode(type, TETHER_ERROR_NO_ERROR);
|
||||
mTetheringMetrics.sendReport(type);
|
||||
NetworkTetheringReported expectedReport =
|
||||
mStatsBuilder.setDownstreamType(expectedResult)
|
||||
.setUserType(UserType.USER_UNKNOWN)
|
||||
.setUpstreamType(UpstreamType.UT_UNKNOWN)
|
||||
.setErrorCode(ErrorCode.EC_NO_ERROR)
|
||||
.build();
|
||||
verify(mTetheringMetrics).write(expectedReport);
|
||||
reset(mTetheringMetrics);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDownstreamTypes() throws Exception {
|
||||
runDownstreamTypesTest(new Pair<>(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI),
|
||||
new Pair<>(TETHERING_WIFI_P2P, DownstreamType.DS_TETHERING_WIFI_P2P),
|
||||
new Pair<>(TETHERING_BLUETOOTH, DownstreamType.DS_TETHERING_BLUETOOTH),
|
||||
new Pair<>(TETHERING_USB, DownstreamType.DS_TETHERING_USB),
|
||||
new Pair<>(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM),
|
||||
new Pair<>(TETHERING_ETHERNET, DownstreamType.DS_TETHERING_ETHERNET));
|
||||
}
|
||||
|
||||
private void runErrorCodesTest(final Pair<Integer, ErrorCode>... testPairs)
|
||||
throws Exception {
|
||||
for (Pair<Integer, ErrorCode> testPair : testPairs) {
|
||||
final int errorCode = testPair.first;
|
||||
final ErrorCode expectedResult = testPair.second;
|
||||
|
||||
mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG);
|
||||
mTetheringMetrics.updateErrorCode(TETHERING_WIFI, errorCode);
|
||||
mTetheringMetrics.sendReport(TETHERING_WIFI);
|
||||
NetworkTetheringReported expectedReport =
|
||||
mStatsBuilder.setDownstreamType(DownstreamType.DS_TETHERING_WIFI)
|
||||
.setUserType(UserType.USER_UNKNOWN)
|
||||
.setUpstreamType(UpstreamType.UT_UNKNOWN)
|
||||
.setErrorCode(expectedResult)
|
||||
.build();
|
||||
verify(mTetheringMetrics).write(expectedReport);
|
||||
reset(mTetheringMetrics);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorCodes() throws Exception {
|
||||
runErrorCodesTest(new Pair<>(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR),
|
||||
new Pair<>(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE),
|
||||
new Pair<>(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL),
|
||||
new Pair<>(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED),
|
||||
new Pair<>(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE),
|
||||
new Pair<>(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR),
|
||||
new Pair<>(TETHER_ERROR_TETHER_IFACE_ERROR, ErrorCode.EC_TETHER_IFACE_ERROR),
|
||||
new Pair<>(TETHER_ERROR_UNTETHER_IFACE_ERROR, ErrorCode.EC_UNTETHER_IFACE_ERROR),
|
||||
new Pair<>(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
|
||||
ErrorCode.EC_ENABLE_FORWARDING_ERROR),
|
||||
new Pair<>(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
|
||||
ErrorCode.EC_DISABLE_FORWARDING_ERROR),
|
||||
new Pair<>(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR),
|
||||
new Pair<>(TETHER_ERROR_PROVISIONING_FAILED, ErrorCode.EC_PROVISIONING_FAILED),
|
||||
new Pair<>(TETHER_ERROR_DHCPSERVER_ERROR, ErrorCode.EC_DHCPSERVER_ERROR),
|
||||
new Pair<>(TETHER_ERROR_ENTITLEMENT_UNKNOWN, ErrorCode.EC_ENTITLEMENT_UNKNOWN),
|
||||
new Pair<>(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
|
||||
ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION),
|
||||
new Pair<>(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
|
||||
ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION),
|
||||
new Pair<>(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE));
|
||||
}
|
||||
|
||||
private void runUserTypesTest(final Pair<String, UserType>... testPairs)
|
||||
throws Exception {
|
||||
for (Pair<String, UserType> testPair : testPairs) {
|
||||
final String callerPkg = testPair.first;
|
||||
final UserType expectedResult = testPair.second;
|
||||
|
||||
mTetheringMetrics.createBuilder(TETHERING_WIFI, callerPkg);
|
||||
mTetheringMetrics.updateErrorCode(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
|
||||
mTetheringMetrics.sendReport(TETHERING_WIFI);
|
||||
NetworkTetheringReported expectedReport =
|
||||
mStatsBuilder.setDownstreamType(DownstreamType.DS_TETHERING_WIFI)
|
||||
.setUserType(expectedResult)
|
||||
.setUpstreamType(UpstreamType.UT_UNKNOWN)
|
||||
.setErrorCode(ErrorCode.EC_NO_ERROR)
|
||||
.build();
|
||||
verify(mTetheringMetrics).write(expectedReport);
|
||||
reset(mTetheringMetrics);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserTypes() throws Exception {
|
||||
runUserTypesTest(new Pair<>(TEST_CALLER_PKG, UserType.USER_UNKNOWN),
|
||||
new Pair<>(SETTINGS_PKG, UserType.USER_SETTINGS),
|
||||
new Pair<>(SYSTEMUI_PKG, UserType.USER_SYSTEMUI),
|
||||
new Pair<>(GMS_PKG, UserType.USER_GMS));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue