blob: b4cd7592c132be4dbf59c15df49c48e843b86e78 [file] [log] [blame]
/*
* Copyright (C) 2016 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.wifi;
import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT;
import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT;
import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY;
import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN;
import static com.android.server.wifi.WifiMetricsTestUtil.assertDeviceMobilityStatePnoScanStatsEqual;
import static com.android.server.wifi.WifiMetricsTestUtil.assertExperimentProbeCountsEqual;
import static com.android.server.wifi.WifiMetricsTestUtil.assertHistogramBucketsEqual;
import static com.android.server.wifi.WifiMetricsTestUtil.assertKeyCountsEqual;
import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeFailureReasonCountsEqual;
import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeStaEventsEqual;
import static com.android.server.wifi.WifiMetricsTestUtil.buildDeviceMobilityStatePnoScanStats;
import static com.android.server.wifi.WifiMetricsTestUtil.buildExperimentProbeCounts;
import static com.android.server.wifi.WifiMetricsTestUtil.buildHistogramBucketInt32;
import static com.android.server.wifi.WifiMetricsTestUtil.buildInt32Count;
import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureReasonCount;
import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureStaEvent;
import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeSuccessStaEvent;
import static com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.TYPE_LINK_PROBE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.wifi.EAPConstants;
import android.net.wifi.IOnWifiUsabilityStatsListener;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.ProvisioningCallback;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.telephony.TelephonyManager;
import android.util.Base64;
import android.util.Pair;
import android.util.SparseIntArray;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.wifi.aware.WifiAwareMetrics;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.hotspot2.PasspointMatch;
import com.android.server.wifi.hotspot2.PasspointProvider;
import com.android.server.wifi.p2p.WifiP2pMetrics;
import com.android.server.wifi.proto.WifiStatsLog;
import com.android.server.wifi.proto.nano.WifiMetricsProto;
import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorFailureStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics;
import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32;
import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics;
import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiRadioUsage;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
import com.android.server.wifi.rtt.RttMetrics;
import com.android.server.wifi.util.ExternalCallbackTracker;
import com.android.server.wifi.util.InformationElementUtil;
import com.android.wifi.resources.R;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Unit tests for {@link com.android.server.wifi.WifiMetrics}.
*/
@SmallTest
public class WifiMetricsTest extends WifiBaseTest {
WifiMetrics mWifiMetrics;
WifiMetricsProto.WifiLog mDecodedProto;
TestLooper mTestLooper;
Random mRandom = new Random();
private static final int TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER = 2;
private static final int TEST_NETWORK_ID = 42;
private MockitoSession mSession;
@Mock Context mContext;
MockResources mResources;
@Mock FrameworkFacade mFacade;
@Mock Clock mClock;
@Mock ScoringParams mScoringParams;
@Mock WifiConfigManager mWcm;
@Mock BssidBlocklistMonitor mBssidBlocklistMonitor;
@Mock PasspointManager mPpm;
@Mock WifiNetworkSelector mWns;
@Mock WifiPowerMetrics mWifiPowerMetrics;
@Mock WifiDataStall mWifiDataStall;
@Mock WifiHealthMonitor mWifiHealthMonitor;
@Mock IBinder mAppBinder;
@Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
@Mock ExternalCallbackTracker<IOnWifiUsabilityStatsListener> mListenerTracker;
@Mock WifiP2pMetrics mWifiP2pMetrics;
@Mock DppMetrics mDppMetrics;
@Mock WifiScoreCard mWifiScoreCard;
@Mock WifiScoreCard.PerNetwork mPerNetwork;
@Mock WifiScoreCard.NetworkConnectionStats mNetworkConnectionStats;
@Mock WifiConfiguration mWifiConfig;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDecodedProto = null;
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
mTestLooper = new TestLooper();
mResources = new MockResources();
when(mContext.getResources()).thenReturn(mResources);
mWifiMetrics = new WifiMetrics(mContext, mFacade, mClock, mTestLooper.getLooper(),
new WifiAwareMetrics(mClock), new RttMetrics(mClock), mWifiPowerMetrics,
mWifiP2pMetrics, mDppMetrics);
mWifiMetrics.setWifiConfigManager(mWcm);
mWifiMetrics.setBssidBlocklistMonitor(mBssidBlocklistMonitor);
mWifiMetrics.setPasspointManager(mPpm);
mWifiMetrics.setScoringParams(mScoringParams);
mWifiMetrics.setWifiNetworkSelector(mWns);
mWifiMetrics.setWifiDataStall(mWifiDataStall);
mWifiMetrics.setWifiHealthMonitor(mWifiHealthMonitor);
mWifiMetrics.setWifiScoreCard(mWifiScoreCard);
when(mWifiScoreCard.lookupNetwork(anyString())).thenReturn(mPerNetwork);
when(mPerNetwork.getRecentStats()).thenReturn(mNetworkConnectionStats);
}
/**
* Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of
* order. Only tests no exception occurs. Creates 3 ConnectionEvents.
*/
@Test
public void startAndEndConnectionEventSucceeds() throws Exception {
//Start and end Connection event
mWifiMetrics.startConnectionEvent(null, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
WifiMetricsProto.ConnectionEvent.HLF_DHCP,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//end Connection event without starting one
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
WifiMetricsProto.ConnectionEvent.HLF_DHCP,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//start two ConnectionEvents in a row
mWifiMetrics.startConnectionEvent(null, "BLUE",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.startConnectionEvent(null, "GREEN",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
}
private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60;
private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000;
/**
* Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and
* deserialize them into mDecodedProto
*/
public void dumpProtoAndDeserialize() throws Exception {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(stream);
when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
//Test proto dump, by passing in proto arg option
String[] args = {WifiMetrics.PROTO_DUMP_ARG};
mWifiMetrics.dump(null, writer, args);
writer.flush();
Pattern pattern = Pattern.compile(
"(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)");
Matcher matcher = pattern.matcher(stream.toString());
assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(),
matcher.find());
String protoByteString = matcher.group(1);
byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
}
/**
* Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into
* mDecodedProto
*/
public void cleanDumpProtoAndDeserialize() throws Exception {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(stream);
when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
//Test proto dump, by passing in proto arg option
String[] args = {WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG};
mWifiMetrics.dump(null, writer, args);
writer.flush();
String protoByteString = stream.toString();
byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
}
/** Verifies that dump() includes the expected header */
@Test
public void stateDumpIncludesHeader() throws Exception {
assertStringContains(getStateDump(), "WifiMetrics");
}
/** Verifies that dump() includes correct alert count when there are no alerts. */
@Test
public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception {
assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()");
}
/** Verifies that dump() includes correct alert count when there is one alert. */
@Test
public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception {
mWifiMetrics.logFirmwareAlert(1);
assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)");
}
/** Verifies that dump() includes correct alert count when there are multiple alerts. */
@Test
public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception {
mWifiMetrics.logFirmwareAlert(1);
mWifiMetrics.logFirmwareAlert(1);
mWifiMetrics.logFirmwareAlert(16);
assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)");
}
@Test
public void testDumpProtoAndDeserialize() throws Exception {
setAndIncrementMetrics();
dumpProtoAndDeserialize();
verify(mWifiP2pMetrics).consolidateProto();
assertDeserializedMetricsCorrect();
}
private static final int NUM_OPEN_NETWORKS = 2;
private static final int NUM_LEGACY_PERSONAL_NETWORKS = 3;
private static final int NUM_LEGACY_ENTERPRISE_NETWORKS = 5;
private static final int NUM_ENHANCED_OPEN_NETWORKS = 1;
private static final int NUM_WPA3_PERSONAL_NETWORKS = 4;
private static final int NUM_WPA3_ENTERPRISE_NETWORKS = 6;
private static final int NUM_WAPI_PERSONAL_NETWORKS = 4;
private static final int NUM_WAPI_ENTERPRISE_NETWORKS = 6;
private static final int NUM_SAVED_NETWORKS = NUM_OPEN_NETWORKS + NUM_LEGACY_PERSONAL_NETWORKS
+ NUM_LEGACY_ENTERPRISE_NETWORKS + NUM_ENHANCED_OPEN_NETWORKS
+ NUM_WPA3_PERSONAL_NETWORKS + NUM_WPA3_ENTERPRISE_NETWORKS
+ NUM_WAPI_PERSONAL_NETWORKS + NUM_WAPI_ENTERPRISE_NETWORKS;
private static final int NUM_HIDDEN_NETWORKS = NUM_OPEN_NETWORKS;
private static final int NUM_PASSPOINT_NETWORKS = NUM_LEGACY_ENTERPRISE_NETWORKS;
private static final int NUM_NETWORKS_ADDED_BY_USER = 0;
private static final int NUM_NETWORKS_ADDED_BY_APPS = NUM_SAVED_NETWORKS
- NUM_NETWORKS_ADDED_BY_USER;
private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true;
private static final boolean IS_SCANNING_ALWAYS_ENABLED = true;
private static final boolean IS_VERBOSE_LOGGING_ENABLED = true;
private static final boolean IS_ENHANCED_MAC_RANDOMIZATION_FORCE_ENABLED = true;
private static final boolean IS_WIFI_WAKE_ENABLED = true;
private static final int NUM_EMPTY_SCAN_RESULTS = 19;
private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23;
private static final int NUM_SCAN_UNKNOWN = 1;
private static final int NUM_SCAN_SUCCESS = 2;
private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3;
private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5;
private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3;
private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5;
private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7;
private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11;
private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11;
private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12;
private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13;
private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1;
private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2;
private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3;
private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4;
private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5;
private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10;
private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5;
private static final int WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER = 6;
private static final int RSSI_POLL_FREQUENCY = 5150;
private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20;
private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS = 4;
private static final int NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS = 2;
private static final int NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS = 2;
private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2;
private static final int NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS = 1;
private static final int NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS =
NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS + NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS
+ NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS;
private static final int NUM_SCANS = 5;
private static final int NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT = 4;
private static final int NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS = 15;
private static final int NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 10;
private static final int NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 16;
// Look at buildMockScanDetailList, this number needs to match the mocked results
private static final int NUM_TOTAL_SCAN_RESULTS = NUM_OPEN_NETWORK_SCAN_RESULTS
+ NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS + NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS
+ NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS + NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS
+ NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS + NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS
+ NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS;
private static final int MIN_RSSI_LEVEL = -127;
private static final int MAX_RSSI_LEVEL = 0;
private static final int WIFI_SCORE_RANGE_MIN = 0;
private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20;
private static final int WIFI_SCORE_RANGE_MAX = 60;
private static final int NUM_OUT_OF_BOUND_ENTRIES = 10;
private static final int MAX_NUM_SOFTAP_RETURN_CODES = 3;
private static final int NUM_SOFTAP_START_SUCCESS = 3;
private static final int NUM_SOFTAP_FAILED_GENERAL_ERROR = 2;
private static final int NUM_SOFTAP_FAILED_NO_CHANNEL = 1;
private static final int NUM_HAL_CRASHES = 11;
private static final int NUM_WIFICOND_CRASHES = 12;
private static final int NUM_SUPPLICANT_CRASHES = 23;
private static final int NUM_HOSTAPD_CRASHES = 7;
private static final int NUM_WIFI_ON_FAILURE_DUE_TO_HAL = 13;
private static final int NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND = 14;
private static final int NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT = 20;
private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL = 23;
private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND = 19;
private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD = 31;
private static final int NUM_SOFTAP_INTERFACE_DOWN = 65;
private static final int NUM_CLIENT_INTERFACE_DOWN = 12;
private static final int NUM_PASSPOINT_PROVIDERS = 7;
private static final int NUM_PASSPOINT_PROVIDER_INSTALLATION = 5;
private static final int NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS = 4;
private static final int NUM_PASSPOINT_PROVIDER_UNINSTALLATION = 3;
private static final int NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS = 2;
private static final int NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED = 1;
private static final int NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA = 2;
private static final int NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA = 3;
private static final int NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE = 4;
private static final int NUM_EAP_SIM_TYPE = 1;
private static final int NUM_EAP_TTLS_TYPE = 2;
private static final int NUM_EAP_TLS_TYPE = 3;
private static final int NUM_EAP_AKA_TYPE = 4;
private static final int NUM_EAP_AKA_PRIME_TYPE = 5;
private static final SparseIntArray SAVED_PASSPOINT_PROVIDERS_TYPE = new SparseIntArray();
static {
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_SIM, NUM_EAP_SIM_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TTLS, NUM_EAP_TTLS_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TLS, NUM_EAP_TLS_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA, NUM_EAP_AKA_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA_PRIME, NUM_EAP_AKA_PRIME_TYPE);
}
private static final int NUM_PARTIAL_SCAN_RESULTS = 73;
private static final int NUM_PNO_SCAN_ATTEMPTS = 20;
private static final int NUM_PNO_SCAN_FAILED = 5;
private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10;
private static final int NUM_RADIO_MODE_CHANGE_TO_MCC = 4;
private static final int NUM_RADIO_MODE_CHANGE_TO_SCC = 13;
private static final int NUM_RADIO_MODE_CHANGE_TO_SBS = 19;
private static final int NUM_RADIO_MODE_CHANGE_TO_DBS = 34;
private static final int NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED = 14;
private static final long NUM_WATCHDOG_SUCCESS_DURATION_MS = 65;
private static final long WIFI_POWER_METRICS_LOGGING_DURATION = 280;
private static final long WIFI_POWER_METRICS_SCAN_TIME = 33;
private static final boolean WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING = true;
private static final boolean LINK_SPEED_COUNTS_LOGGING_SETTING = true;
private static final int DATA_STALL_MIN_TX_BAD_SETTING = 5;
private static final int DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING = 75;
private static final int NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS = 4;
private static final int NUM_ADD_OR_UPDATE_NETWORK_CALLS = 5;
private static final int NUM_ENABLE_NETWORK_CALLS = 6;
private static final long NUM_IP_RENEWAL_FAILURE = 7;
private static final int NUM_NETWORK_ABNORMAL_ASSOC_REJECTION = 2;
private static final int NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY = 4;
private static final int NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS = 5;
private static final int NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE = 3;
private static final long WIFI_MAINLINE_MODULE_VERSION = 123456L;
/** Number of notifications per "Connect to Network" notification type. */
private static final int[] NUM_CONNECT_TO_NETWORK_NOTIFICATIONS = {0, 10, 20, 30, 40};
/** Number of notifications per "Connect to Network notification type and action type. */
private static final int[][] NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS = {
{0, 1, 2, 3, 4},
{10, 11, 12, 13, 14},
{20, 21, 22, 23, 24},
{30, 31, 32, 33, 34},
{40, 41, 42, 43, 44}};
private static final int SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST = 10;
private static final boolean IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = true;
private static final int NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND = 5;
private static final int NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES = 8;
private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG;
private static final int NUM_SOFT_AP_EVENT_ENTRIES = 3;
private static final int NUM_SOFT_AP_ASSOCIATED_STATIONS = 3;
private static final int SOFT_AP_CHANNEL_FREQUENCY = 2437;
private static final int SOFT_AP_CHANNEL_BANDWIDTH = SoftApConnectedClientsEvent.BANDWIDTH_20;
private static final int SOFT_AP_MAX_CLIENT_SETTING = 10;
private static final int SOFT_AP_MAX_CLIENT_CAPABILITY = 16;
private static final long SOFT_AP_SHUTDOWN_TIMEOUT_SETTING = 10_000;
private static final long SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING = 600_000;
private static final boolean SOFT_AP_CLIENT_CONTROL_ENABLE = true;
private static final boolean IS_MAC_RANDOMIZATION_ON = true;
private static final int NUM_LINK_SPEED_LEVELS_TO_INCREMENT = 30;
private static final int TEST_RSSI_LEVEL = -80;
private static final int MAX_SUPPORTED_TX_LINK_SPEED_MBPS = 144;
private static final int MAX_SUPPORTED_RX_LINK_SPEED_MBPS = 190;
private static final long NUM_MBO_SUPPORTED_NETWORKS_SCAN_RESULTS = 4;
private static final long NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS = 2;
private static final long NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS = 2;
private static final long NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS = 2;
private static final long NUM_11AX_NETWORKS_SCAN_RESULTS = 3;
private static final long NUM_6G_NETWORKS_SCAN_RESULTS = 2;
private static final long NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND = 3;
private static final long NUM_CONNECT_TO_MBO_SUPPORTED_NETWORKS = 4;
private static final long NUM_CONNECT_TO_OCE_SUPPORTED_NETWORKS = 3;
private static final long NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST = 2;
private static final long NUM_MBO_CELLULAR_SWITCH_REQUEST = 3;
private static final long NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY = 3;
private static final long NUM_CONNECT_REQUEST_WITH_FILS_AKM = 4;
private static final long NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION = 3;
public static final int FEATURE_MBO = 1 << 0;
public static final int FEATURE_MBO_CELL_DATA_AWARE = 1 << 1;
public static final int FEATURE_OCE = 1 << 2;
public static final int FEATURE_11AX = 1 << 3;
public static final int FEATURE_6G = 1 << 4;
private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
String capabilities, int supportedFeatures) {
ScanDetail mockScanDetail = mock(ScanDetail.class);
NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
ScanResult mockScanResult = mock(ScanResult.class);
when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
when(mockScanDetail.getScanResult()).thenReturn(mockScanResult);
when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden);
when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease);
mockScanResult.capabilities = capabilities;
if ((supportedFeatures & FEATURE_MBO) != 0) {
when(mockNetworkDetail.isMboSupported()).thenReturn(true);
}
if ((supportedFeatures & FEATURE_MBO_CELL_DATA_AWARE) != 0) {
when(mockNetworkDetail.isMboCellularDataAware()).thenReturn(true);
}
if ((supportedFeatures & FEATURE_OCE) != 0) {
when(mockNetworkDetail.isOceSupported()).thenReturn(true);
}
if ((supportedFeatures & FEATURE_11AX) != 0) {
when(mockNetworkDetail.getWifiMode())
.thenReturn(InformationElementUtil.WifiMode.MODE_11AX);
}
if ((supportedFeatures & FEATURE_6G) != 0) {
when(mockScanResult.is6GHz()).thenReturn(true);
}
return mockScanDetail;
}
private ScanDetail buildMockScanDetail(String ssid, String bssid, boolean isOpen,
boolean isSaved, boolean isProvider, boolean isWeakRssi) {
ScanDetail mockScanDetail = mock(ScanDetail.class);
NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
ScanResult scanResult = new ScanResult();
scanResult.SSID = ssid;
scanResult.BSSID = bssid;
when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
when(mockScanDetail.getScanResult()).thenReturn(scanResult);
when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(isWeakRssi);
scanResult.capabilities = isOpen ? "" : "PSK";
if (isSaved) {
when(mWcm.getConfiguredNetworkForScanDetail(eq(mockScanDetail)))
.thenReturn(mock(WifiConfiguration.class));
}
if (isProvider) {
PasspointProvider provider = mock(PasspointProvider.class);
List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>();
matchedProviders.add(Pair.create(provider, null));
when(mockNetworkDetail.isInterworking()).thenReturn(true);
when(mPpm.matchProvider(eq(scanResult), eq(false))).thenReturn(matchedProviders);
}
return mockScanDetail;
}
private ScanDetail buildMockScanDetailPasspoint(String ssid, String bssid, long hessid,
int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal) {
ScanDetail mockScanDetail = mock(ScanDetail.class);
NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
ScanResult scanResult = new ScanResult();
scanResult.SSID = ssid;
scanResult.BSSID = bssid;
scanResult.hessid = hessid;
scanResult.capabilities = "PSK";
when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
when(mockScanDetail.getScanResult()).thenReturn(scanResult);
when(mockNetworkDetail.getHSRelease()).thenReturn(hsRelease);
when(mockNetworkDetail.getAnqpDomainID()).thenReturn(anqpDomainId);
when(mockNetworkDetail.isInterworking()).thenReturn(true);
when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(weakSignal);
return mockScanDetail;
}
private List<ScanDetail> buildMockScanDetailList() {
List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>();
mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]", 0));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]", FEATURE_11AX));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]", 0));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]", FEATURE_MBO));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]",
FEATURE_11AX | FEATURE_6G));
mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]", 0));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]",
FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-OWE-CCMP]",
FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE | FEATURE_OCE));
mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-EAP-SUITE-B-192]",
FEATURE_11AX | FEATURE_6G));
mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-PSK-SMS4-SMS4]", 0));
mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
// Number of scans of R2 networks must be equal to NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS
mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
"[WPA-EAP-CCMP+EAP-FILS-SHA256-CCMP]", FEATURE_MBO | FEATURE_OCE));
mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
"[WPA2-EAP+FT/EAP-CCMP+EAP-FILS-SHA256-CCMP]", 0));
// Number of scans of R1 networks must be equal to NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS
mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1,
"[WPA-EAP-CCMP]", 0));
// Number of scans of R3 networks must be equal to NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS
mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R3,
"[WPA-EAP-CCMP]", 0));
return mockScanDetails;
}
private List<WifiConfiguration> buildSavedNetworkList() {
List<WifiConfiguration> testSavedNetworks = new ArrayList<WifiConfiguration>();
for (int i = 0; i < NUM_OPEN_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createOpenHiddenNetwork());
}
for (int i = 0; i < NUM_LEGACY_PERSONAL_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createPskNetwork());
}
for (int i = 0; i < NUM_LEGACY_ENTERPRISE_NETWORKS; i++) {
// Passpoint networks are counted in both Passpoint and Enterprise counters
testSavedNetworks.add(WifiConfigurationTestUtil.createPasspointNetwork());
}
for (int i = 0; i < NUM_ENHANCED_OPEN_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createOweNetwork());
}
for (int i = 0; i < NUM_WPA3_PERSONAL_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createSaeNetwork());
}
for (int i = 0; i < NUM_WPA3_ENTERPRISE_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createEapSuiteBNetwork());
}
for (int i = 0; i < NUM_WAPI_PERSONAL_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createWapiPskNetwork());
}
for (int i = 0; i < NUM_WAPI_ENTERPRISE_NETWORKS; i++) {
testSavedNetworks.add(WifiConfigurationTestUtil.createWapiCertNetwork());
}
testSavedNetworks.get(0).macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
return testSavedNetworks;
}
private PasspointProvider createMockProvider(int eapType, boolean validateForR2) {
PasspointProvider provider = mock(PasspointProvider.class);
PasspointConfiguration config = mock(PasspointConfiguration.class);
Credential credential = new Credential();
switch (eapType) {
case EAPConstants.EAP_TLS:
credential.setCertCredential(new Credential.CertificateCredential());
break;
case EAPConstants.EAP_TTLS:
credential.setUserCredential(new Credential.UserCredential());
break;
case EAPConstants.EAP_AKA:
case EAPConstants.EAP_AKA_PRIME:
case EAPConstants.EAP_SIM:
Credential.SimCredential simCredential = new Credential.SimCredential();
simCredential.setEapType(eapType);
credential.setSimCredential(simCredential);
break;
}
when(provider.getConfig()).thenReturn(config);
when(config.getCredential()).thenReturn(credential);
when(config.validateForR2()).thenReturn(validateForR2);
return provider;
}
/**
* Set simple metrics, increment others
*/
public void setAndIncrementMetrics() throws Exception {
Map<String, PasspointProvider> providers = new HashMap<>();
mWifiMetrics.updateSavedNetworks(buildSavedNetworkList());
mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS,
NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED);
for (int i = 0; i < SAVED_PASSPOINT_PROVIDERS_TYPE.size(); i++) {
int eapType = SAVED_PASSPOINT_PROVIDERS_TYPE.keyAt(i);
int count = SAVED_PASSPOINT_PROVIDERS_TYPE.valueAt(i);
for (int j = 0; j < count; j++) {
providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, false));
}
for (int j = count; j < count * 2; j++) {
providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, true));
}
}
mWifiMetrics.updateSavedPasspointProfilesInfo(providers);
mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED);
mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED);
mWifiMetrics.setVerboseLoggingEnabled(IS_VERBOSE_LOGGING_ENABLED);
mWifiMetrics.setEnhancedMacRandomizationForceEnabled(
IS_ENHANCED_MAC_RANDOMIZATION_FORCE_ENABLED);
mWifiMetrics.setWifiWakeEnabled(IS_WIFI_WAKE_ENABLED);
for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) {
mWifiMetrics.incrementEmptyScanResultCount();
}
for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) {
mWifiMetrics.incrementNonEmptyScanResultCount();
}
mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN,
NUM_SCAN_UNKNOWN);
mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS,
NUM_SCAN_SUCCESS);
mWifiMetrics.incrementScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
NUM_SCAN_FAILURE_INTERRUPTED);
mWifiMetrics.incrementScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) {
mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
false);
}
for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) {
mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
true);
}
for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) {
mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
false);
}
for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) {
mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
true);
}
for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) {
mWifiMetrics.incrementNumConnectivityWatchdogPnoGood();
}
for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) {
mWifiMetrics.incrementNumConnectivityWatchdogPnoBad();
}
for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) {
mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood();
}
for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) {
mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad();
}
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) {
mWifiMetrics.incrementNumLastResortWatchdogTriggers();
}
mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal(
NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL);
mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(
NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL);
mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal(
NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL);
mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal(
NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL);
mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal(
NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL);
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) {
mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation();
}
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) {
mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication();
}
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) {
mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp();
}
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) {
mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther();
}
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) {
mWifiMetrics.incrementNumLastResortWatchdogSuccesses();
}
for (int i = 0; i < WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER; i++) {
mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger();
}
for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
for (int j = 0; j <= i; j++) {
mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL + i);
}
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL - i);
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MAX_RSSI_LEVEL + i);
}
// Test alert-reason clamping.
mWifiMetrics.logFirmwareAlert(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1);
mWifiMetrics.logFirmwareAlert(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1);
// Simple cases for alert reason.
mWifiMetrics.logFirmwareAlert(1);
mWifiMetrics.logFirmwareAlert(1);
mWifiMetrics.logFirmwareAlert(1);
mWifiMetrics.logFirmwareAlert(2);
List<ScanDetail> mockScanDetails = buildMockScanDetailList();
for (int i = 0; i < NUM_SCANS; i++) {
mWifiMetrics.countScanResults(mockScanDetails);
}
// increment connectivity scan metrics
for (int i = 0; i < NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT; i++) {
mWifiMetrics.incrementConnectivityOneshotScanCount();
}
for (int i = 0; i < NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS; i++) {
mWifiMetrics.incrementExternalAppOneshotScanRequestsCount();
}
for (int i = 0; i < NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) {
mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount();
}
for (int i = 0; i < NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) {
mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount();
}
for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
for (int offset = 0; offset <= score; offset++) {
mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score);
}
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i);
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i);
}
for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
for (int offset = 0; offset <= score; offset++) {
mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MIN + score, 15);
}
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MIN - i, 15);
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MAX + i, 15);
}
// increment soft ap start return codes
for (int i = 0; i < NUM_SOFTAP_START_SUCCESS; i++) {
mWifiMetrics.incrementSoftApStartResult(true, 0);
}
for (int i = 0; i < NUM_SOFTAP_FAILED_GENERAL_ERROR; i++) {
mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL);
}
for (int i = 0; i < NUM_SOFTAP_FAILED_NO_CHANNEL; i++) {
mWifiMetrics.incrementSoftApStartResult(false,
WifiManager.SAP_START_FAILURE_NO_CHANNEL);
}
for (int i = 0; i < NUM_HAL_CRASHES; i++) {
mWifiMetrics.incrementNumHalCrashes();
}
for (int i = 0; i < NUM_WIFICOND_CRASHES; i++) {
mWifiMetrics.incrementNumWificondCrashes();
}
for (int i = 0; i < NUM_SUPPLICANT_CRASHES; i++) {
mWifiMetrics.incrementNumSupplicantCrashes();
}
for (int i = 0; i < NUM_HOSTAPD_CRASHES; i++) {
mWifiMetrics.incrementNumHostapdCrashes();
}
for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_HAL; i++) {
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
}
for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND; i++) {
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
}
for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT; i++) {
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
}
for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL; i++) {
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
}
for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND; i++) {
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond();
}
for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD; i++) {
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
}
for (int i = 0; i < NUM_SOFTAP_INTERFACE_DOWN; i++) {
mWifiMetrics.incrementNumSoftApInterfaceDown();
}
for (int i = 0; i < NUM_CLIENT_INTERFACE_DOWN; i++) {
mWifiMetrics.incrementNumClientInterfaceDown();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALLATION; i++) {
mWifiMetrics.incrementNumPasspointProviderInstallation();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS; i++) {
mWifiMetrics.incrementNumPasspointProviderInstallSuccess();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALLATION; i++) {
mWifiMetrics.incrementNumPasspointProviderUninstallation();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS; i++) {
mWifiMetrics.incrementNumPasspointProviderUninstallSuccess();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA; i++) {
mWifiMetrics.incrementNumPasspointProviderWithNoRootCa();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA; i++) {
mWifiMetrics.incrementNumPasspointProviderWithSelfSignedRootCa();
}
for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE; i++) {
mWifiMetrics.incrementNumPasspointProviderWithSubscriptionExpiration();
}
for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_MCC; i++) {
mWifiMetrics.incrementNumRadioModeChangeToMcc();
}
for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SCC; i++) {
mWifiMetrics.incrementNumRadioModeChangeToScc();
}
for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SBS; i++) {
mWifiMetrics.incrementNumRadioModeChangeToSbs();
}
for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_DBS; i++) {
mWifiMetrics.incrementNumRadioModeChangeToDbs();
}
for (int i = 0; i < NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED; i++) {
mWifiMetrics.incrementNumSoftApUserBandPreferenceUnsatisfied();
}
// increment pno scan metrics
for (int i = 0; i < NUM_PNO_SCAN_ATTEMPTS; i++) {
mWifiMetrics.incrementPnoScanStartAttemptCount();
}
for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) {
mWifiMetrics.incrementPnoScanFailedCount();
}
for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) {
mWifiMetrics.incrementPnoFoundNetworkEventCount();
}
for (int i = 0; i < NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE; i++) {
mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
}
// set and increment "connect to network" notification metrics
for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATIONS.length; i++) {
int count = NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[i];
for (int j = 0; j < count; j++) {
mWifiMetrics.incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, i);
}
}
for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS.length; i++) {
int[] actions = NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS[i];
for (int j = 0; j < actions.length; j++) {
int count = actions[j];
for (int k = 0; k < count; k++) {
mWifiMetrics.incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG,
i, j);
}
}
}
mWifiMetrics.setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG,
SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST);
mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG,
IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) {
mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG);
}
for (int i = 0; i < NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND; i++) {
mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG);
}
addSoftApEventsToMetrics();
for (int i = 0; i < NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS; i++) {
mWifiMetrics.incrementOneshotScanWithDfsCount();
}
for (int i = 0; i < NUM_ADD_OR_UPDATE_NETWORK_CALLS; i++) {
mWifiMetrics.incrementNumAddOrUpdateNetworkCalls();
}
for (int i = 0; i < NUM_ENABLE_NETWORK_CALLS; i++) {
mWifiMetrics.incrementNumEnableNetworkCalls();
}
for (int i = 0; i < NUM_IP_RENEWAL_FAILURE; i++) {
mWifiMetrics.incrementIpRenewalFailure();
}
mWifiMetrics.setWatchdogSuccessTimeDurationMs(NUM_WATCHDOG_SUCCESS_DURATION_MS);
mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported,
IS_MAC_RANDOMIZATION_ON);
addWifiPowerMetrics();
addWifiHealthMetrics();
mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled,
WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING);
mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled,
LINK_SPEED_COUNTS_LOGGING_SETTING);
mResources.setInteger(R.integer.config_wifiDataStallMinTxBad,
DATA_STALL_MIN_TX_BAD_SETTING);
mResources.setInteger(R.integer.config_wifiDataStallMinTxSuccessWithoutRx,
DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING);
for (int i = 0; i < NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND; i++) {
mWifiMetrics.incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd();
}
for (int i = 0; i < NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST; i++) {
mWifiMetrics.incrementForceScanCountDueToSteeringRequest();
}
for (int i = 0; i < NUM_MBO_CELLULAR_SWITCH_REQUEST; i++) {
mWifiMetrics.incrementMboCellularSwitchRequestCount();
}
for (int i = 0; i < NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY; i++) {
mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay();
}
for (int i = 0; i < NUM_CONNECT_REQUEST_WITH_FILS_AKM; i++) {
mWifiMetrics.incrementConnectRequestWithFilsAkmCount();
}
for (int i = 0; i < NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION; i++) {
mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount();
}
}
private void addWifiPowerMetrics() {
WifiRadioUsage wifiRadioUsage = new WifiRadioUsage();
wifiRadioUsage.loggingDurationMs = WIFI_POWER_METRICS_LOGGING_DURATION;
wifiRadioUsage.scanTimeMs = WIFI_POWER_METRICS_SCAN_TIME;
when(mWifiPowerMetrics.buildWifiRadioUsageProto()).thenReturn(wifiRadioUsage);
}
private void addWifiHealthMetrics() {
HealthMonitorMetrics metrics = new HealthMonitorMetrics();
metrics.failureStatsIncrease = new HealthMonitorFailureStats();
metrics.failureStatsDecrease = new HealthMonitorFailureStats();
metrics.failureStatsHigh = new HealthMonitorFailureStats();
metrics.failureStatsIncrease.cntAssocRejection = NUM_NETWORK_ABNORMAL_ASSOC_REJECTION;
metrics.numNetworkSufficientRecentStatsOnly = NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY;
metrics.numNetworkSufficientRecentPrevStats = NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS;
when(mWifiHealthMonitor.buildProto()).thenReturn(metrics);
when(mWifiHealthMonitor.getWifiStackVersion()).thenReturn(WIFI_MAINLINE_MODULE_VERSION);
}
private void addSoftApEventsToMetrics() {
// Total number of events recorded is NUM_SOFT_AP_EVENT_ENTRIES in both modes
mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED,
SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING);
mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
WifiManager.IFACE_IP_MODE_TETHERED);
mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
WifiManager.IFACE_IP_MODE_UNSPECIFIED); // Should be dropped.
mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_TETHERED,
SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING);
// Channel switch info should be added to the last Soft AP UP event in the list
mWifiMetrics.addSoftApChannelSwitchedEvent(SOFT_AP_CHANNEL_FREQUENCY,
SOFT_AP_CHANNEL_BANDWIDTH, WifiManager.IFACE_IP_MODE_TETHERED);
SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder()
.setSsid("Test_Metric_SSID")
.setMaxNumberOfClients(SOFT_AP_MAX_CLIENT_SETTING)
.setShutdownTimeoutMillis(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING)
.setClientControlByUserEnabled(SOFT_AP_CLIENT_CONTROL_ENABLE)
.build();
mWifiMetrics.updateSoftApConfiguration(testSoftApConfig,
WifiManager.IFACE_IP_MODE_TETHERED);
SoftApCapability testSoftApCapability = new SoftApCapability(0);
testSoftApCapability.setMaxSupportedClients(SOFT_AP_MAX_CLIENT_CAPABILITY);
mWifiMetrics.updateSoftApCapability(testSoftApCapability,
WifiManager.IFACE_IP_MODE_TETHERED);
mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_LOCAL_ONLY,
SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING);
mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
// Should be dropped.
mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR,
SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING);
mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_LOCAL_ONLY,
SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING);
}
private void verifySoftApEventsStoredInProto() {
assertEquals(NUM_SOFT_AP_EVENT_ENTRIES,
mDecodedProto.softApConnectedClientsEventsTethered.length);
assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP,
mDecodedProto.softApConnectedClientsEventsTethered[0].eventType);
assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[0].numConnectedClients);
assertEquals(SOFT_AP_CHANNEL_FREQUENCY,
mDecodedProto.softApConnectedClientsEventsTethered[0].channelFrequency);
assertEquals(SOFT_AP_CHANNEL_BANDWIDTH,
mDecodedProto.softApConnectedClientsEventsTethered[0].channelBandwidth);
assertEquals(SOFT_AP_MAX_CLIENT_SETTING,
mDecodedProto.softApConnectedClientsEventsTethered[0]
.maxNumClientsSettingInSoftapConfiguration);
assertEquals(SOFT_AP_MAX_CLIENT_CAPABILITY,
mDecodedProto.softApConnectedClientsEventsTethered[0]
.maxNumClientsSettingInSoftapCapability);
assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING,
mDecodedProto.softApConnectedClientsEventsTethered[0]
.shutdownTimeoutSettingInSoftapConfiguration);
assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING,
mDecodedProto.softApConnectedClientsEventsTethered[0]
.defaultShutdownTimeoutSetting);
assertEquals(SOFT_AP_CLIENT_CONTROL_ENABLE,
mDecodedProto.softApConnectedClientsEventsTethered[0].clientControlIsEnabled);
assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED,
mDecodedProto.softApConnectedClientsEventsTethered[1].eventType);
assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS,
mDecodedProto.softApConnectedClientsEventsTethered[1].numConnectedClients);
assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
mDecodedProto.softApConnectedClientsEventsTethered[2].eventType);
assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[2].numConnectedClients);
assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP,
mDecodedProto.softApConnectedClientsEventsLocalOnly[0].eventType);
assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[0].numConnectedClients);
assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED,
mDecodedProto.softApConnectedClientsEventsLocalOnly[1].eventType);
assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS,
mDecodedProto.softApConnectedClientsEventsLocalOnly[1].numConnectedClients);
assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
mDecodedProto.softApConnectedClientsEventsLocalOnly[2].eventType);
assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[2].numConnectedClients);
}
/**
* Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics'
*/
public void assertDeserializedMetricsCorrect() throws Exception {
assertEquals("mDecodedProto.numSavedNetworks == NUM_SAVED_NETWORKS",
NUM_SAVED_NETWORKS, mDecodedProto.numSavedNetworks);
assertEquals("mDecodedProto.numSavedNetworksWithMacRandomization == NUM_SAVED_NETWORKS-1",
NUM_SAVED_NETWORKS - 1, mDecodedProto.numSavedNetworksWithMacRandomization);
assertEquals("mDecodedProto.numOpenNetworks == NUM_OPEN_NETWORKS",
NUM_OPEN_NETWORKS, mDecodedProto.numOpenNetworks);
assertEquals("mDecodedProto.numLegacyPersonalNetworks == NUM_LEGACY_PERSONAL_NETWORKS",
NUM_LEGACY_PERSONAL_NETWORKS, mDecodedProto.numLegacyPersonalNetworks);
assertEquals(
"mDecodedProto.numLegacyEnterpriseNetworks == NUM_LEGACY_ENTERPRISE_NETWORKS",
NUM_LEGACY_ENTERPRISE_NETWORKS, mDecodedProto.numLegacyEnterpriseNetworks);
assertEquals("mDecodedProto.numEnhancedOpenNetworks == NUM_ENHANCED_OPEN_NETWORKS",
NUM_ENHANCED_OPEN_NETWORKS, mDecodedProto.numEnhancedOpenNetworks);
assertEquals("mDecodedProto.numWpa3PersonalNetworks == NUM_WPA3_PERSONAL_NETWORKS",
NUM_WPA3_PERSONAL_NETWORKS, mDecodedProto.numWpa3PersonalNetworks);
assertEquals("mDecodedProto.numWpa3EnterpriseNetworks == NUM_WPA3_ENTERPRISE_NETWORKS",
NUM_WPA3_ENTERPRISE_NETWORKS, mDecodedProto.numWpa3EnterpriseNetworks);
assertEquals("mDecodedProto.numWapiPersonalNetworks == NUM_WAPI_PERSONAL_NETWORKS",
NUM_WAPI_PERSONAL_NETWORKS, mDecodedProto.numWapiPersonalNetworks);
assertEquals("mDecodedProto.numWapiEnterpriseNetworks == NUM_WAPI_ENTERPRISE_NETWORKS",
NUM_WAPI_ENTERPRISE_NETWORKS, mDecodedProto.numWapiEnterpriseNetworks);
assertEquals("mDecodedProto.numNetworksAddedByUser == NUM_NETWORKS_ADDED_BY_USER",
NUM_NETWORKS_ADDED_BY_USER, mDecodedProto.numNetworksAddedByUser);
assertEquals(NUM_HIDDEN_NETWORKS, mDecodedProto.numHiddenNetworks);
assertEquals(NUM_PASSPOINT_NETWORKS, mDecodedProto.numPasspointNetworks);
assertEquals("mDecodedProto.numNetworksAddedByApps == NUM_NETWORKS_ADDED_BY_APPS",
NUM_NETWORKS_ADDED_BY_APPS, mDecodedProto.numNetworksAddedByApps);
assertEquals("mDecodedProto.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED",
TEST_VAL_IS_LOCATION_ENABLED, mDecodedProto.isLocationEnabled);
assertEquals("mDecodedProto.isScanningAlwaysEnabled == IS_SCANNING_ALWAYS_ENABLED",
IS_SCANNING_ALWAYS_ENABLED, mDecodedProto.isScanningAlwaysEnabled);
assertEquals(IS_VERBOSE_LOGGING_ENABLED, mDecodedProto.isVerboseLoggingEnabled);
assertEquals(IS_ENHANCED_MAC_RANDOMIZATION_FORCE_ENABLED,
mDecodedProto.isEnhancedMacRandomizationForceEnabled);
assertEquals(IS_WIFI_WAKE_ENABLED, mDecodedProto.isWifiWakeEnabled);
assertEquals("mDecodedProto.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS",
NUM_EMPTY_SCAN_RESULTS, mDecodedProto.numEmptyScanResults);
assertEquals("mDecodedProto.numNonEmptyScanResults == NUM_NON_EMPTY_SCAN_RESULTS",
NUM_NON_EMPTY_SCAN_RESULTS, mDecodedProto.numNonEmptyScanResults);
assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, NUM_SCAN_UNKNOWN);
assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS, NUM_SCAN_SUCCESS);
assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
NUM_SCAN_FAILURE_INTERRUPTED);
assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false,
NUM_WIFI_UNKNOWN_SCREEN_OFF);
assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true,
NUM_WIFI_UNKNOWN_SCREEN_ON);
assertSystemStateEntryEquals(
WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF);
assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true,
NUM_WIFI_ASSOCIATED_SCREEN_ON);
assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD,
mDecodedProto.numConnectivityWatchdogPnoGood);
assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_BAD,
mDecodedProto.numConnectivityWatchdogPnoBad);
assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD,
mDecodedProto.numConnectivityWatchdogBackgroundGood);
assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD,
mDecodedProto.numConnectivityWatchdogBackgroundBad);
assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS,
mDecodedProto.numLastResortWatchdogTriggers);
assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL,
mDecodedProto.numLastResortWatchdogBadAssociationNetworksTotal);
assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL,
mDecodedProto.numLastResortWatchdogBadAuthenticationNetworksTotal);
assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL,
mDecodedProto.numLastResortWatchdogBadDhcpNetworksTotal);
assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL,
mDecodedProto.numLastResortWatchdogBadOtherNetworksTotal);
assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL,
mDecodedProto.numLastResortWatchdogAvailableNetworksTotal);
assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION,
mDecodedProto.numLastResortWatchdogTriggersWithBadAssociation);
assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION,
mDecodedProto.numLastResortWatchdogTriggersWithBadAuthentication);
assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP,
mDecodedProto.numLastResortWatchdogTriggersWithBadDhcp);
assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER,
mDecodedProto.numLastResortWatchdogTriggersWithBadOther);
assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES,
mDecodedProto.numLastResortWatchdogSuccesses);
assertEquals(WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER,
mDecodedProto.watchdogTotalConnectionFailureCountAfterTrigger);
assertEquals(TEST_RECORD_DURATION_SEC,
mDecodedProto.recordDurationSec);
for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
assertEquals(RSSI_POLL_FREQUENCY,
mDecodedProto.rssiPollRssiCount[i].frequency);
assertEquals(MIN_RSSI_LEVEL + i, mDecodedProto.rssiPollRssiCount[i].rssi);
assertEquals(i + 1, mDecodedProto.rssiPollRssiCount[i].count);
}
StringBuilder sb_rssi = new StringBuilder();
sb_rssi.append("Number of RSSIs = " + mDecodedProto.rssiPollRssiCount.length);
assertTrue(sb_rssi.toString(), (mDecodedProto.rssiPollRssiCount.length
<= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1)));
assertEquals(2, mDecodedProto.alertReasonCount[0].count); // Clamped reasons.
assertEquals(3, mDecodedProto.alertReasonCount[1].count);
assertEquals(1, mDecodedProto.alertReasonCount[2].count);
assertEquals(3, mDecodedProto.alertReasonCount.length);
assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numTotalScanResults);
assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numOpenNetworkScanResults);
assertEquals(NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numLegacyPersonalNetworkScanResults);
assertEquals(NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numLegacyEnterpriseNetworkScanResults);
assertEquals(NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numEnhancedOpenNetworkScanResults);
assertEquals(NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numWpa3PersonalNetworkScanResults);
assertEquals(NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numWpa3EnterpriseNetworkScanResults);
assertEquals(NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numWapiPersonalNetworkScanResults);
assertEquals(NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numWapiEnterpriseNetworkScanResults);
assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numHiddenNetworkScanResults);
assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numHotspot2R1NetworkScanResults);
assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numHotspot2R2NetworkScanResults);
assertEquals(NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numHotspot2R3NetworkScanResults);
assertEquals(NUM_MBO_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numMboSupportedNetworkScanResults);
assertEquals(NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numMboCellularDataAwareNetworkScanResults);
assertEquals(NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numOceSupportedNetworkScanResults);
assertEquals(NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.numFilsSupportedNetworkScanResults);
assertEquals(NUM_11AX_NETWORKS_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.num11AxNetworkScanResults);
assertEquals(NUM_6G_NETWORKS_SCAN_RESULTS * NUM_SCANS,
mDecodedProto.num6GNetworkScanResults);
assertEquals(NUM_SCANS,
mDecodedProto.numScans);
assertEquals(NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT,
mDecodedProto.numConnectivityOneshotScans);
assertEquals(NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS,
mDecodedProto.numExternalAppOneshotScanRequests);
assertEquals(NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED,
mDecodedProto.numExternalForegroundAppOneshotScanRequestsThrottled);
assertEquals(NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED,
mDecodedProto.numExternalBackgroundAppOneshotScanRequestsThrottled);
for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) {
assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
mDecodedProto.wifiScoreCount[score_index].score);
assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1,
mDecodedProto.wifiScoreCount[score_index].count);
assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
mDecodedProto.wifiUsabilityScoreCount[score_index].score);
assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1,
mDecodedProto.wifiUsabilityScoreCount[score_index].count);
}
StringBuilder sb_wifi_score = new StringBuilder();
sb_wifi_score.append("Number of wifi_scores = " + mDecodedProto.wifiScoreCount.length);
assertTrue(sb_wifi_score.toString(), (mDecodedProto.wifiScoreCount.length
<= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
StringBuilder sb_wifi_limits = new StringBuilder();
sb_wifi_limits.append("Wifi Score limit is " + ConnectedScore.WIFI_MAX_SCORE
+ ">= " + WIFI_SCORE_RANGE_MAX);
assertTrue(sb_wifi_limits.toString(),
ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX);
StringBuilder sb_wifi_usability_score = new StringBuilder();
sb_wifi_usability_score.append("Number of wifi_usability_scores = "
+ mDecodedProto.wifiUsabilityScoreCount.length);
assertTrue(sb_wifi_usability_score.toString(), (mDecodedProto.wifiUsabilityScoreCount.length
<= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
StringBuilder sb_wifi_usablity_limits = new StringBuilder();
sb_wifi_limits.append("Wifi Usability Score limit is " + ConnectedScore.WIFI_MAX_SCORE
+ ">= " + WIFI_SCORE_RANGE_MAX);
assertTrue(sb_wifi_limits.toString(),
ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX);
assertEquals(MAX_NUM_SOFTAP_RETURN_CODES, mDecodedProto.softApReturnCode.length);
assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY,
mDecodedProto.softApReturnCode[0].startResult);
assertEquals(NUM_SOFTAP_START_SUCCESS, mDecodedProto.softApReturnCode[0].count);
assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR,
mDecodedProto.softApReturnCode[1].startResult);
assertEquals(NUM_SOFTAP_FAILED_GENERAL_ERROR,
mDecodedProto.softApReturnCode[1].count);
assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL,
mDecodedProto.softApReturnCode[2].startResult);
assertEquals(NUM_SOFTAP_FAILED_NO_CHANNEL,
mDecodedProto.softApReturnCode[2].count);
assertEquals(NUM_HAL_CRASHES, mDecodedProto.numHalCrashes);
assertEquals(NUM_WIFICOND_CRASHES, mDecodedProto.numWificondCrashes);
assertEquals(NUM_SUPPLICANT_CRASHES, mDecodedProto.numSupplicantCrashes);
assertEquals(NUM_HOSTAPD_CRASHES, mDecodedProto.numHostapdCrashes);
assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_HAL,
mDecodedProto.numSetupClientInterfaceFailureDueToHal);
assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND,
mDecodedProto.numSetupClientInterfaceFailureDueToWificond);
assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT,
mDecodedProto.numSetupClientInterfaceFailureDueToSupplicant);
assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL,
mDecodedProto.numSetupSoftApInterfaceFailureDueToHal);
assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND,
mDecodedProto.numSetupSoftApInterfaceFailureDueToWificond);
assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD,
mDecodedProto.numSetupSoftApInterfaceFailureDueToHostapd);
assertEquals(NUM_CLIENT_INTERFACE_DOWN, mDecodedProto.numClientInterfaceDown);
assertEquals(NUM_SOFTAP_INTERFACE_DOWN, mDecodedProto.numSoftApInterfaceDown);
assertEquals(NUM_PASSPOINT_PROVIDERS, mDecodedProto.numPasspointProviders);
assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR1);
assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR2);
assertEquals(NUM_PASSPOINT_PROVIDER_INSTALLATION,
mDecodedProto.numPasspointProviderInstallation);
assertEquals(NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS,
mDecodedProto.numPasspointProviderInstallSuccess);
assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALLATION,
mDecodedProto.numPasspointProviderUninstallation);
assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS,
mDecodedProto.numPasspointProviderUninstallSuccess);
assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED,
mDecodedProto.numPasspointProvidersSuccessfullyConnected);
assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA,
mDecodedProto.numPasspointProviderWithNoRootCa);
assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA,
mDecodedProto.numPasspointProviderWithSelfSignedRootCa);
assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE,
mDecodedProto.numPasspointProviderWithSubscriptionExpiration);
assertEquals(NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE,
mDecodedProto.numBssidDifferentSelectionBetweenFrameworkAndFirmware);
assertEquals(NUM_RADIO_MODE_CHANGE_TO_MCC, mDecodedProto.numRadioModeChangeToMcc);
assertEquals(NUM_RADIO_MODE_CHANGE_TO_SCC, mDecodedProto.numRadioModeChangeToScc);
assertEquals(NUM_RADIO_MODE_CHANGE_TO_SBS, mDecodedProto.numRadioModeChangeToSbs);
assertEquals(NUM_RADIO_MODE_CHANGE_TO_DBS, mDecodedProto.numRadioModeChangeToDbs);
assertEquals(NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED,
mDecodedProto.numSoftApUserBandPreferenceUnsatisfied);
PnoScanMetrics pno_metrics = mDecodedProto.pnoScanMetrics;
assertNotNull(pno_metrics);
assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts);
assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed);
assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents);
for (ConnectToNetworkNotificationAndActionCount notificationCount
: mDecodedProto.connectToNetworkNotificationCount) {
assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[notificationCount.notification],
notificationCount.count);
assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN,
notificationCount.recommender);
}
for (ConnectToNetworkNotificationAndActionCount notificationActionCount
: mDecodedProto.connectToNetworkNotificationActionCount) {
assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS
[notificationActionCount.notification]
[notificationActionCount.action],
notificationActionCount.count);
assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN,
notificationActionCount.recommender);
}
assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST,
mDecodedProto.openNetworkRecommenderBlacklistSize);
assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
mDecodedProto.isWifiNetworksAvailableNotificationOn);
assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES,
mDecodedProto.numOpenNetworkRecommendationUpdates);
assertEquals(NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND,
mDecodedProto.numOpenNetworkConnectMessageFailedToSend);
verifySoftApEventsStoredInProto();
assertEquals(NUM_WATCHDOG_SUCCESS_DURATION_MS,
mDecodedProto.watchdogTriggerToConnectionSuccessDurationMs);
assertEquals(IS_MAC_RANDOMIZATION_ON, mDecodedProto.isMacRandomizationOn);
assertEquals(WIFI_POWER_METRICS_LOGGING_DURATION,
mDecodedProto.wifiRadioUsage.loggingDurationMs);
assertEquals(WIFI_POWER_METRICS_SCAN_TIME,
mDecodedProto.wifiRadioUsage.scanTimeMs);
assertEquals(WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING,
mDecodedProto.experimentValues.wifiIsUnusableLoggingEnabled);
assertEquals(LINK_SPEED_COUNTS_LOGGING_SETTING,
mDecodedProto.experimentValues.linkSpeedCountsLoggingEnabled);
assertEquals(DATA_STALL_MIN_TX_BAD_SETTING,
mDecodedProto.experimentValues.wifiDataStallMinTxBad);
assertEquals(DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING,
mDecodedProto.experimentValues.wifiDataStallMinTxSuccessWithoutRx);
assertEquals(NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS,
mDecodedProto.numOneshotHasDfsChannelScans);
assertEquals(NUM_ADD_OR_UPDATE_NETWORK_CALLS, mDecodedProto.numAddOrUpdateNetworkCalls);
assertEquals(NUM_ENABLE_NETWORK_CALLS, mDecodedProto.numEnableNetworkCalls);
assertEquals(NUM_IP_RENEWAL_FAILURE, mDecodedProto.numIpRenewalFailure);
assertEquals(NUM_NETWORK_ABNORMAL_ASSOC_REJECTION,
mDecodedProto.healthMonitorMetrics.failureStatsIncrease.cntAssocRejection);
assertEquals(0,
mDecodedProto.healthMonitorMetrics.failureStatsIncrease.cntAssocTimeout);
assertEquals(NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY,
mDecodedProto.healthMonitorMetrics.numNetworkSufficientRecentStatsOnly);
assertEquals(NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS,
mDecodedProto.healthMonitorMetrics.numNetworkSufficientRecentPrevStats);
assertEquals(NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND,
mDecodedProto.numBssidFilteredDueToMboAssocDisallowInd);
assertEquals(NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST,
mDecodedProto.numForceScanDueToSteeringRequest);
assertEquals(NUM_MBO_CELLULAR_SWITCH_REQUEST,
mDecodedProto.numMboCellularSwitchRequest);
assertEquals(NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY,
mDecodedProto.numSteeringRequestIncludingMboAssocRetryDelay);
assertEquals(NUM_CONNECT_REQUEST_WITH_FILS_AKM,
mDecodedProto.numConnectRequestWithFilsAkm);
assertEquals(NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION,
mDecodedProto.numL2ConnectionThroughFilsAuthentication);
assertEquals(WIFI_MAINLINE_MODULE_VERSION, mDecodedProto.mainlineModuleVersion);
}
/**
* Assert deserialized metrics Scan Return Entry equals count
*/
public void assertScanReturnEntryEquals(int returnCode, int count) {
for (int i = 0; i < mDecodedProto.scanReturnEntries.length; i++) {
if (mDecodedProto.scanReturnEntries[i].scanReturnCode == returnCode) {
assertEquals(count, mDecodedProto.scanReturnEntries[i].scanResultsCount);
return;
}
}
assertEquals(null, count);
}
/**
* Assert deserialized metrics SystemState entry equals count
*/
public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) {
for (int i = 0; i < mDecodedProto.wifiSystemStateEntries.length; i++) {
if (mDecodedProto.wifiSystemStateEntries[i].wifiState == state
&& mDecodedProto.wifiSystemStateEntries[i].isScreenOn == screenOn) {
assertEquals(count, mDecodedProto.wifiSystemStateEntries[i].wifiStateCount);
return;
}
}
assertEquals(null, count);
}
/**
* Test the number of Passpoint provision with the failure code are collected correctly
*
* @throws Exception
*/
@Test
public void testPasspointProvisionMetrics() throws Exception {
//Increment count for provisioning success.
mWifiMetrics.incrementPasspointProvisionSuccess();
// Increment count for provisioning unavailable
mWifiMetrics.incrementPasspointProvisionFailure(
ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
mWifiMetrics.incrementPasspointProvisionFailure(
ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
// Increment count for server connection failure
mWifiMetrics.incrementPasspointProvisionFailure(
ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
// Dump proto and deserialize
dumpProtoAndDeserialize();
assertEquals(mDecodedProto.passpointProvisionStats.numProvisionSuccess, 1);
assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount.length, 2);
assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].failureCode,
PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION);
assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].count, 1);
assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].failureCode,
PasspointProvisionStats.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].count, 2);
}
/**
* Combination of all other WifiMetrics unit tests, an internal-integration test, or functional
* test
*/
@Test
public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception {
setAndIncrementMetrics();
startAndEndConnectionEventSucceeds();
dumpProtoAndDeserialize();
assertDeserializedMetricsCorrect();
assertEquals("mDecodedProto.connectionEvent.length",
2, mDecodedProto.connectionEvent.length);
//<TODO> test individual connectionEvents for correctness,
// check scanReturnEntries & wifiSystemStateEntries counts and individual elements
// pending their implementation</TODO>
}
/**
* Test that score breach events are properly generated
*/
@Test
public void testScoreBeachEvents() throws Exception {
int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
int mid = WifiMetrics.LOW_WIFI_SCORE;
int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
for (int score = upper; score >= mid; score--) mWifiMetrics.incrementWifiScoreCount(score);
mWifiMetrics.incrementWifiScoreCount(mid + 1);
mWifiMetrics.incrementWifiScoreCount(lower); // First breach
for (int score = lower; score <= mid; score++) mWifiMetrics.incrementWifiScoreCount(score);
mWifiMetrics.incrementWifiScoreCount(mid - 1);
mWifiMetrics.incrementWifiScoreCount(upper); // Second breach
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.staEventList.length);
assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[0].type);
assertEquals(lower, mDecodedProto.staEventList[0].lastScore);
assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[1].type);
assertEquals(upper, mDecodedProto.staEventList[1].lastScore);
}
/**
* Test that Wifi usability score breach events are properly generated
*/
@Test
public void testWifiUsabilityScoreBreachEvents() throws Exception {
int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
int mid = WifiMetrics.LOW_WIFI_USABILITY_SCORE;
int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
for (int score = upper; score >= mid; score--) {
mWifiMetrics.incrementWifiUsabilityScoreCount(1, score, 15);
}
mWifiMetrics.incrementWifiUsabilityScoreCount(1, mid + 1, 15);
mWifiMetrics.incrementWifiUsabilityScoreCount(1, lower, 15); // First breach
for (int score = lower; score <= mid; score++) {
mWifiMetrics.incrementWifiUsabilityScoreCount(1, score, 15);
}
mWifiMetrics.incrementWifiUsabilityScoreCount(1, mid - 1, 15);
mWifiMetrics.incrementWifiUsabilityScoreCount(1, upper, 15); // Second breach
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.staEventList.length);
assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[0].type);
assertEquals(lower, mDecodedProto.staEventList[0].lastWifiUsabilityScore);
assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[1].type);
assertEquals(upper, mDecodedProto.staEventList[1].lastWifiUsabilityScore);
}
private static final String SSID = "red";
private static final int CONFIG_DTIM = 3;
private static final int NETWORK_DETAIL_WIFIMODE = 5;
private static final int NETWORK_DETAIL_DTIM = 7;
private static final int SCAN_RESULT_LEVEL = -30;
/**
* Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration
*/
@Test
public void testScanDetailAndWifiConfigurationUsage() throws Exception {
//Setup mock configs and scan details
NetworkDetail networkDetail = mock(NetworkDetail.class);
when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
when(networkDetail.getSSID()).thenReturn(SSID);
when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
ScanResult scanResult = mock(ScanResult.class);
scanResult.level = SCAN_RESULT_LEVEL;
scanResult.capabilities = "EAP";
WifiConfiguration config = mock(WifiConfiguration.class);
config.SSID = "\"" + SSID + "\"";
config.dtimInterval = CONFIG_DTIM;
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
config.allowedKeyManagement = new BitSet();
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
config.enterpriseConfig = new WifiEnterpriseConfig();
config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
config.enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS);
WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
mock(WifiConfiguration.NetworkSelectionStatus.class);
when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
ScanDetail scanDetail = mock(ScanDetail.class);
when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
when(scanDetail.getScanResult()).thenReturn(scanResult);
when(networkDetail.isMboSupported()).thenReturn(true);
when(networkDetail.isOceSupported()).thenReturn(true);
config.networkId = TEST_NETWORK_ID;
mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID,
WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
//Create a connection event using only the config
mWifiMetrics.startConnectionEvent(config, "Red",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//Change configuration to open without randomization
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
scanResult.capabilities = "";
//Create a connection event using the config and a scan detail
mWifiMetrics.startConnectionEvent(config, "Green",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.setConnectionScanDetail(scanDetail);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//Dump proto from mWifiMetrics and deserialize it to mDecodedProto
dumpProtoAndDeserialize();
//Check that the correct values are being flowed through
assertEquals(2, mDecodedProto.connectionEvent.length);
assertEquals(CONFIG_DTIM, mDecodedProto.connectionEvent[0].routerFingerprint.dtim);
assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE,
mDecodedProto.connectionEvent[0].routerFingerprint.authentication);
assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS,
mDecodedProto.connectionEvent[0].routerFingerprint.eapMethod);
assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2,
mDecodedProto.connectionEvent[0].routerFingerprint.authPhase2Method);
assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS,
mDecodedProto.connectionEvent[0].routerFingerprint.ocspType);
assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[0].signalStrength);
assertEquals(NETWORK_DETAIL_DTIM, mDecodedProto.connectionEvent[1].routerFingerprint.dtim);
assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_OPEN,
mDecodedProto.connectionEvent[1].routerFingerprint.authentication);
assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN,
mDecodedProto.connectionEvent[1].routerFingerprint.eapMethod);
assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE,
mDecodedProto.connectionEvent[1].routerFingerprint.authPhase2Method);
assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE,
mDecodedProto.connectionEvent[1].routerFingerprint.ocspType);
assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[1].signalStrength);
assertEquals(NETWORK_DETAIL_WIFIMODE,
mDecodedProto.connectionEvent[1].routerFingerprint.routerTechnology);
assertTrue(mDecodedProto.connectionEvent[0].useRandomizedMac);
assertFalse(mDecodedProto.connectionEvent[1].useRandomizedMac);
assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL,
mDecodedProto.connectionEvent[0].connectionNominator);
assertEquals(1, mDecodedProto.numConnectToNetworkSupportingMbo);
assertEquals(1, mDecodedProto.numConnectToNetworkSupportingOce);
}
/**
* Tests that the mapping from networkId to nominatorId is not cleared.
*/
@Test
public void testNetworkToNominatorNotCleared() throws Exception {
//Setup mock configs and scan details
NetworkDetail networkDetail = mock(NetworkDetail.class);
when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
when(networkDetail.getSSID()).thenReturn(SSID);
when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
ScanResult scanResult = mock(ScanResult.class);
scanResult.level = SCAN_RESULT_LEVEL;
WifiConfiguration config = mock(WifiConfiguration.class);
config.SSID = "\"" + SSID + "\"";
config.dtimInterval = CONFIG_DTIM;
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
config.allowedKeyManagement = new BitSet();
WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
mock(WifiConfiguration.NetworkSelectionStatus.class);
when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
ScanDetail scanDetail = mock(ScanDetail.class);
when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
when(scanDetail.getScanResult()).thenReturn(scanResult);
config.networkId = TEST_NETWORK_ID;
mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID,
WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER);
// dump() calls clear() internally
mWifiMetrics.dump(null, new PrintWriter(new StringWriter()),
new String[]{WifiMetrics.PROTO_DUMP_ARG});
// Create a connection event using only the config
mWifiMetrics.startConnectionEvent(config, "Red",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER,
mDecodedProto.connectionEvent[0].connectionNominator);
}
/**
* Test that WifiMetrics is serializing/deserializing association time out events.
*/
@Test
public void testMetricsAssociationTimedOut() throws Exception {
mWifiMetrics.startConnectionEvent(null, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//Dump proto and deserialize
//This should clear all the metrics in mWifiMetrics,
dumpProtoAndDeserialize();
//Check there is only 1 connection events
assertEquals(1, mDecodedProto.connectionEvent.length);
assertEquals(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
mDecodedProto.connectionEvent[0].level2FailureCode);
assertEquals(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN,
mDecodedProto.connectionEvent[0].level2FailureReason);
}
/**
* Verify the logging of number of blocked BSSIDs in ConnectionEvent.
*/
@Test
public void testMetricNumBssidInBlocklist() throws Exception {
WifiConfiguration config = mock(WifiConfiguration.class);
config.SSID = "\"" + SSID + "\"";
config.allowedKeyManagement = new BitSet();
when(config.getNetworkSelectionStatus()).thenReturn(
mock(WifiConfiguration.NetworkSelectionStatus.class));
when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(eq(config.SSID)))
.thenReturn(3);
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.connectionEvent.length);
assertEquals(3, mDecodedProto.connectionEvent[0].numBssidInBlocklist);
}
/**
* Verify the ConnectionEvent is labeled with networkType open network correctly.
*/
@Test
public void testConnectionNetworkTypeOpen() throws Exception {
WifiConfiguration config = mock(WifiConfiguration.class);
config.SSID = "\"" + SSID + "\"";
config.allowedKeyManagement = new BitSet();
when(config.getNetworkSelectionStatus()).thenReturn(
mock(WifiConfiguration.NetworkSelectionStatus.class));
when(config.isOpenNetwork()).thenReturn(true);
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.connectionEvent.length);
assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_OPEN,
mDecodedProto.connectionEvent[0].networkType);
assertFalse(mDecodedProto.connectionEvent[0].isOsuProvisioned);
}
/**
* Verify the ConnectionEvent is labeled with networkType Passpoint correctly.
*/
@Test
public void testConnectionNetworkTypePasspoint() throws Exception {
WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.connectionEvent.length);
assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT,
mDecodedProto.connectionEvent[0].networkType);
assertFalse(mDecodedProto.connectionEvent[0].isOsuProvisioned);
}
/**
* Verify the ConnectionEvent is created with correct creatorUid.
*/
@Test
public void testConnectionCreatorUid() throws Exception {
WifiConfiguration config = mock(WifiConfiguration.class);
config.SSID = "\"" + SSID + "\"";
config.allowedKeyManagement = new BitSet();
when(config.getNetworkSelectionStatus()).thenReturn(
mock(WifiConfiguration.NetworkSelectionStatus.class));
// First network is created by the user
config.fromWifiNetworkSuggestion = false;
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
// Second network is created by a carrier app
config.fromWifiNetworkSuggestion = true;
config.carrierId = 123;
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
// Third network is created by an unknown app
config.fromWifiNetworkSuggestion = true;
config.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(3, mDecodedProto.connectionEvent.length);
assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_USER,
mDecodedProto.connectionEvent[0].networkCreator);
assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER,
mDecodedProto.connectionEvent[1].networkCreator);
assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN,
mDecodedProto.connectionEvent[2].networkCreator);
}
/**
* Test that WifiMetrics is serializing/deserializing authentication failure events.
*/
@Test
public void testMetricsAuthenticationFailureReason() throws Exception {
mWifiMetrics.startConnectionEvent(null, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD);
//Dump proto and deserialize
//This should clear all the metrics in mWifiMetrics,
dumpProtoAndDeserialize();
//Check there is only 1 connection events
assertEquals(1, mDecodedProto.connectionEvent.length);
assertEquals(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
mDecodedProto.connectionEvent[0].level2FailureCode);
//Check the authentication failure reason
assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD,
mDecodedProto.connectionEvent[0].level2FailureReason);
}
/**
* Test the logging of BssidBlocklistStats.
*/
@Test
public void testBssidBlocklistMetrics() throws Exception {
for (int i = 0; i < 3; i++) {
mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(i);
}
mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(2);
mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled,
true);
mWifiMetrics.incrementNumHighMovementConnectionStarted();
mWifiMetrics.incrementNumHighMovementConnectionSkipped();
mWifiMetrics.incrementNumHighMovementConnectionSkipped();
dumpProtoAndDeserialize();
Int32Count[] expectedHistogram = {
buildInt32Count(0, 1),
buildInt32Count(1, 1),
buildInt32Count(2, 2),
};
assertKeyCountsEqual(expectedHistogram,
mDecodedProto.bssidBlocklistStats.networkSelectionFilteredBssidCount);
assertEquals(true, mDecodedProto.bssidBlocklistStats
.highMovementMultipleScansFeatureEnabled);
assertEquals(1, mDecodedProto.bssidBlocklistStats.numHighMovementConnectionStarted);
assertEquals(2, mDecodedProto.bssidBlocklistStats.numHighMovementConnectionSkipped);
}
/**
* Test that WifiMetrics is being cleared after dumping via proto
*/
@Test
public void testMetricsClearedAfterProtoRequested() throws Exception {
// Create 3 ConnectionEvents
mWifiMetrics.startConnectionEvent(null, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
mWifiMetrics.startConnectionEvent(null, "YELLOW",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
mWifiMetrics.startConnectionEvent(null, "GREEN",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
mWifiMetrics.startConnectionEvent(null, "ORANGE",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//Dump proto and deserialize
//This should clear all the metrics in mWifiMetrics,
dumpProtoAndDeserialize();
//Check there are 4 connection events
assertEquals(4, mDecodedProto.connectionEvent.length);
assertEquals(0, mDecodedProto.rssiPollRssiCount.length);
assertEquals(0, mDecodedProto.alertReasonCount.length);
// Create 2 ConnectionEvents
mWifiMetrics.startConnectionEvent(null, "BLUE",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
mWifiMetrics.startConnectionEvent(null, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
//Dump proto and deserialize
dumpProtoAndDeserialize();
//Check there are only 2 connection events
assertEquals(2, mDecodedProto.connectionEvent.length);
}
/**
* Test logging to statsd when a connection event finishes.
*/
@Test
public void testLogWifiConnectionResultStatsd() throws Exception {
// static mocking for WifiStatsLog
mSession = ExtendedMockito.mockitoSession()
.strictness(Strictness.LENIENT)
.mockStatic(WifiStatsLog.class)
.startMocking();
WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork();
WifiConfiguration.NetworkSelectionStatus networkSelectionStatus =
mock(WifiConfiguration.NetworkSelectionStatus.class);
ScanResult scanResult = mock(ScanResult.class);
scanResult.level = -55;
when(networkSelectionStatus.getCandidate()).thenReturn(scanResult);
network.setNetworkSelectionStatus(networkSelectionStatus);
// Start and end Connection event
mWifiMetrics.startConnectionEvent(network, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
WifiMetricsProto.ConnectionEvent.HLF_DHCP,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
ExtendedMockito.verify(() -> WifiStatsLog.write(
WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, false,
WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL,
-55));
mSession.finishMocking();
}
/**
* Test that current ongoing ConnectionEvent is not cleared and logged
* when proto is dumped
*/
@Test
public void testCurrentConnectionEventNotClearedAfterProtoRequested() throws Exception {
// Create 2 complete ConnectionEvents and 1 ongoing un-ended ConnectionEvent
mWifiMetrics.startConnectionEvent(null, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
mWifiMetrics.startConnectionEvent(null, "YELLOW",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
mWifiMetrics.startConnectionEvent(null, "GREEN",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
// Dump proto and deserialize
// This should clear the metrics in mWifiMetrics,
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.connectionEvent.length);
// End the ongoing ConnectionEvent
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.connectionEvent.length);
}
/**
* Tests that after setting metrics values they can be serialized and deserialized with the
* $ adb shell dumpsys wifi wifiMetricsProto clean
*/
@Test
public void testClearMetricsDump() throws Exception {
setAndIncrementMetrics();
startAndEndConnectionEventSucceeds();
cleanDumpProtoAndDeserialize();
assertDeserializedMetricsCorrect();
assertEquals("mDecodedProto.connectionEvent.length",
2, mDecodedProto.connectionEvent.length);
}
private static final int NUM_REPEATED_DELTAS = 7;
private static final int REPEATED_DELTA = 0;
private static final int SINGLE_GOOD_DELTA = 1;
private static final int SINGLE_TIMEOUT_DELTA = 2;
private static final int NUM_REPEATED_BOUND_DELTAS = 2;
private static final int MAX_DELTA_LEVEL = 127;
private static final int MIN_DELTA_LEVEL = -127;
private static final int ARBITRARY_DELTA_LEVEL = 20;
/**
* Sunny day RSSI delta logging scenario.
* Logs one rssi delta value multiple times
* Logs a different delta value a single time
*/
@Test
public void testRssiDeltasSuccessfulLogging() throws Exception {
// Generate some repeated deltas
for (int i = 0; i < NUM_REPEATED_DELTAS; i++) {
generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
}
// Generate a single delta
generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.rssiPollDeltaCount.length);
// Check the repeated deltas
assertEquals(NUM_REPEATED_DELTAS, mDecodedProto.rssiPollDeltaCount[0].count);
assertEquals(REPEATED_DELTA, mDecodedProto.rssiPollDeltaCount[0].rssi);
// Check the single delta
assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count);
assertEquals(SINGLE_GOOD_DELTA, mDecodedProto.rssiPollDeltaCount[1].rssi);
}
/**
* Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout,
* and are not logged.
*/
@Test
public void testRssiDeltasTimeout() throws Exception {
// Create timed out rssi deltas
generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
}
/**
* Tests the exact inclusive boundaries of RSSI delta logging.
*/
@Test
public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception {
generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.rssiPollDeltaCount.length);
assertEquals(MIN_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi);
assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count);
assertEquals(MAX_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[1].rssi);
assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count);
}
/**
* Tests the exact exclusive boundaries of RSSI delta logging.
* This test ensures that too much data is not generated.
*/
@Test
public void testRssiDeltaOutOfBounds() throws Exception {
generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
}
/**
* This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent
*/
@Test
public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception {
generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
false, // successfulConnectionEvent
true, // completeConnectionEvent
true, // useValidScanResult
true // dontDeserializeBeforePoll
);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
}
/**
* This test ensures rssi Deltas can be logged during a ConnectionEvent
*/
@Test
public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception {
generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
true, // successfulConnectionEvent
false, // completeConnectionEvent
true, // useValidScanResult
true // dontDeserializeBeforePoll
);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.rssiPollDeltaCount.length);
assertEquals(ARBITRARY_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi);
assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count);
}
/**
* This test ensures that no delta is logged for a null ScanResult Candidate
*/
@Test
public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception {
generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
true, // successfulConnectionEvent
true, // completeConnectionEvent
false, // useValidScanResult
true // dontDeserializeBeforePoll
);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
}
/**
* This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized)
*/
@Test
public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception {
generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
true, // successfulConnectionEvent
true, // completeConnectionEvent
true, // useValidScanResult
false // dontDeserializeBeforePoll
);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
}
private static final int DEAUTH_REASON = 7;
private static final int ASSOC_STATUS = 11;
private static final int ASSOC_TIMEOUT = 1;
private static final int LOCAL_GEN = 1;
private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD;
private static final int NUM_TEST_STA_EVENTS = 19;
private static final String sSSID = "\"SomeTestSsid\"";
private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
private static final String sBSSID = "01:02:03:04:05:06";
private final StateChangeResult mStateDisconnected =
new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED);
private final StateChangeResult mStateCompleted =
new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED);
// Test bitmasks of supplicant state changes
private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state);
private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state)
| WifiMetrics.supplicantStateToBit(mStateCompleted.state);
// An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding
private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig();
// <msg.what> <msg.arg1> <msg.arg2>
private int[][] mTestStaMessageInts = {
{WifiMonitor.ASSOCIATION_REJECTION_EVENT, ASSOC_TIMEOUT, ASSOC_STATUS},
{WifiMonitor.AUTHENTICATION_FAILURE_EVENT, AUTH_FAILURE_REASON, -1},
{WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0},
{WifiMonitor.NETWORK_DISCONNECTION_EVENT, LOCAL_GEN, DEAUTH_REASON},
{WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0},
{WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0},
{WifiMonitor.TARGET_BSSID_EVENT, 0, 0},
{WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0},
{WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}
};
private Object[] mTestStaMessageObjs = {
null,
null,
null,
null,
mStateDisconnected,
null,
null,
mStateDisconnected,
mStateCompleted
};
// Values used to generate the StaEvent log calls from ClientModeImpl
// <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <1|0>(testWifiConfiguration, null)
private int[][] mTestStaLogInts = {
{StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0, 0},
{StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, 0, 0},
{StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, 0, 0},
{StaEvent.TYPE_CMD_START_CONNECT, 0, 1},
{StaEvent.TYPE_CMD_START_ROAM, 0, 1},
{StaEvent.TYPE_CONNECT_NETWORK, 0, 1},
{StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, 0, 0},
{StaEvent.TYPE_FRAMEWORK_DISCONNECT, StaEvent.DISCONNECT_API, 0},
{StaEvent.TYPE_SCORE_BREACH, 0, 0},
{StaEvent.TYPE_MAC_CHANGE, 0, 1},
{StaEvent.TYPE_WIFI_ENABLED, 0, 0},
{StaEvent.TYPE_WIFI_DISABLED, 0, 0},
{StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, 0, 0}
};
// Values used to generate the StaEvent log calls from WifiMonitor
// <type>, <reason>, <status>, <local_gen>,
// <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <1|0>(has ConfigInfo)
private int[][] mExpectedValues = {
{StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT, -1, ASSOC_STATUS, 0,
/**/ 0, ASSOC_TIMEOUT, 0, 0}, /**/
{StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT, -1, -1, 0,
/**/StaEvent.AUTH_FAILURE_WRONG_PSWD, 0, 0, 0}, /**/
{StaEvent.TYPE_NETWORK_CONNECTION_EVENT, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON, -1, LOCAL_GEN,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_CMD_ASSOCIATED_BSSID, -1, -1, 0,
/**/ 0, 0, mSupBm1, 0}, /**/
{StaEvent.TYPE_CMD_TARGET_BSSID, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1, -1, 0,
/**/ 0, 0, mSupBm2, 0}, /**/
{StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_CMD_START_CONNECT, -1, -1, 0,
/**/ 0, 0, 0, 1}, /**/
{StaEvent.TYPE_CMD_START_ROAM, -1, -1, 0,
/**/ 0, 0, 0, 1}, /**/
{StaEvent.TYPE_CONNECT_NETWORK, -1, -1, 0,
/**/ 0, 0, 0, 1}, /**/
{StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_FRAMEWORK_DISCONNECT, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_SCORE_BREACH, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_MAC_CHANGE, -1, -1, 0,
/**/ 0, 0, 0, 1}, /**/
{StaEvent.TYPE_WIFI_ENABLED, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_WIFI_DISABLED, -1, -1, 0,
/**/ 0, 0, 0, 0}, /**/
{StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, -1, -1, 0,
/**/ 0, 0, 0, 0} /**/
};
/**
* Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts
*/
private void generateStaEvents(WifiMetrics wifiMetrics) {
Handler handler = wifiMetrics.getHandler();
for (int i = 0; i < mTestStaMessageInts.length; i++) {
int[] mia = mTestStaMessageInts[i];
handler.sendMessage(
handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i]));
}
mTestLooper.dispatchAll();
wifiMetrics.setScreenState(true);
when(mWifiDataStall.isCellularDataAvailable()).thenReturn(true);
for (int i = 0; i < mTestStaLogInts.length; i++) {
int[] lia = mTestStaLogInts[i];
wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null);
}
}
private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) {
assertNotNull(mTestWifiConfig);
assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length);
int j = 0; // De-serialized event index
for (int i = 0; i < mTestStaMessageInts.length; i++) {
StaEvent event = wifiLog.staEventList[j];
int[] mia = mTestStaMessageInts[i];
int[] evs = mExpectedValues[j];
if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) {
assertEquals(evs[0], event.type);
assertEquals(evs[1], event.reason);
assertEquals(evs[2], event.status);
assertEquals(evs[3] == 1 ? true : false, event.localGen);
assertEquals(evs[4], event.authFailureReason);
assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
assertEquals(evs[6], event.supplicantStateChangesBitmask);
assertConfigInfoEqualsWifiConfig(
evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
j++;
}
}
for (int i = 0; i < mTestStaLogInts.length; i++) {
StaEvent event = wifiLog.staEventList[j];
int[] evs = mExpectedValues[j];
assertEquals(evs[0], event.type);
assertEquals(evs[1], event.reason);
assertEquals(evs[2], event.status);
assertEquals(evs[3] == 1 ? true : false, event.localGen);
assertEquals(evs[4], event.authFailureReason);
assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
assertEquals(evs[6], event.supplicantStateChangesBitmask);
assertConfigInfoEqualsWifiConfig(
evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
assertEquals(true, event.screenOn);
assertEquals(true, event.isCellularDataAvailable);
j++;
}
assertEquals(mExpectedValues.length, j);
}
/**
* Generate StaEvents of each type, ensure all the different values are logged correctly,
* and that they survive serialization & de-serialization
*/
@Test
public void testStaEventsLogSerializeDeserialize() throws Exception {
generateStaEvents(mWifiMetrics);
dumpProtoAndDeserialize();
verifyDeserializedStaEvents(mDecodedProto);
}
/**
* Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events
* and checking how many are deserialized
*/
@Test
public void testStaEventBounding() throws Exception {
for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) {
mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT);
}
dumpProtoAndDeserialize();
assertEquals(WifiMetrics.MAX_STA_EVENTS, mDecodedProto.staEventList.length);
}
/**
* Tests that link probe StaEvents do not exceed
* {@link WifiMetrics#MAX_LINK_PROBE_STA_EVENTS}.
*/
@Test
public void testLinkProbeStaEventBounding() throws Exception {
for (int i = 0; i < WifiMetrics.MAX_LINK_PROBE_STA_EVENTS; i++) {
mWifiMetrics.logLinkProbeSuccess(0, 0, 0, 0);
mWifiMetrics.logLinkProbeFailure(0, 0, 0, 0);
}
for (int i = 0; i < 10; i++) {
mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT);
}
dumpProtoAndDeserialize();
long numLinkProbeStaEvents = Arrays.stream(mDecodedProto.staEventList)
.filter(event -> event.type == TYPE_LINK_PROBE)
.count();
assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS, numLinkProbeStaEvents);
assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS + 10, mDecodedProto.staEventList.length);
}
/**
* Test the logging of UserActionEvent with a valid network ID
*/
@Test
public void testLogUserActionEventValidNetworkId() throws Exception {
int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
int testNetworkId = 0;
long testStartTimeMillis = 123123L;
when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
config.ephemeral = true;
when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(config);
mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
dumpProtoAndDeserialize();
WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
assertEquals(1, userActionEvents.length);
assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
userActionEvents[0].eventType);
assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
assertEquals(true, userActionEvents[0].targetNetworkInfo.isEphemeral);
assertEquals(true, userActionEvents[0].targetNetworkInfo.isPasspoint);
// Verify that there are no disabled WifiConfiguration and BSSIDs
NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
assertEquals(NetworkDisableReason.REASON_UNKNOWN, networkDisableReason.disableReason);
assertEquals(false, networkDisableReason.configTemporarilyDisabled);
assertEquals(false, networkDisableReason.configPermanentlyDisabled);
assertEquals(0, networkDisableReason.bssidDisableReasons.length);
}
/**
* Verify the WifiStatus field in a UserActionEvent is populated correctly.
* @throws Exception
*/
@Test
public void testLogWifiStatusInUserActionEvent() throws Exception {
// setups WifiStatus for information
int expectedRssi = -55;
int testNetworkId = 1;
int expectedTx = 1234;
int expectedRx = 2345;
WifiInfo wifiInfo = mock(WifiInfo.class);
when(wifiInfo.getRssi()).thenReturn(expectedRssi);
when(wifiInfo.getNetworkId()).thenReturn(testNetworkId);
mWifiMetrics.handlePollResult(wifiInfo);
mWifiMetrics.incrementThroughputKbpsCount(expectedTx, expectedRx, RSSI_POLL_FREQUENCY);
mWifiMetrics.setNominatorForNetwork(testNetworkId,
WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE);
// generate a user action event and then verify fields
int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
dumpProtoAndDeserialize();
WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
assertEquals(1, userActionEvents.length);
assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
userActionEvents[0].eventType);
assertEquals(expectedRssi, userActionEvents[0].wifiStatus.lastRssi);
assertEquals(expectedTx, userActionEvents[0].wifiStatus.estimatedTxKbps);
assertEquals(expectedRx, userActionEvents[0].wifiStatus.estimatedRxKbps);
assertTrue(userActionEvents[0].wifiStatus.isStuckDueToUserConnectChoice);
}
/**
* verify NetworkDisableReason is populated properly when there exists a disabled
* WifiConfiguration and BSSID.
*/
@Test
public void testNetworkDisableReasonInUserActionEvent() throws Exception {
// Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
status.setNetworkSelectionStatus(
NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
status.setNetworkSelectionDisableReason(
NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
// Also setup the same BSSID level failure
Set<Integer> testBssidBlocklistReasons = new HashSet<>();
testBssidBlocklistReasons.add(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION);
when(mBssidBlocklistMonitor.getFailureReasonsForSsid(anyString()))
.thenReturn(testBssidBlocklistReasons);
// Logging the user action event
mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
TEST_NETWORK_ID);
dumpProtoAndDeserialize();
WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
assertEquals(1, userActionEvents.length);
assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
userActionEvents[0].eventType);
NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
networkDisableReason.disableReason);
assertEquals(true, networkDisableReason.configTemporarilyDisabled);
assertEquals(false, networkDisableReason.configPermanentlyDisabled);
assertEquals(1, networkDisableReason.bssidDisableReasons.length);
assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
networkDisableReason.bssidDisableReasons[0]);
}
/**
* verify that auto-join disable overrides any other disable reasons in NetworkDisableReason.
*/
@Test
public void testNetworkDisableReasonDisableAutojoinInUserActionEvent() throws Exception {
// Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
status.setNetworkSelectionStatus(
NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
status.setNetworkSelectionDisableReason(
NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
// Disable autojoin
testConfig.allowAutojoin = false;
// Logging the user action event
mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
TEST_NETWORK_ID);
dumpProtoAndDeserialize();
WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
assertEquals(NetworkDisableReason.REASON_AUTO_JOIN_DISABLED,
networkDisableReason.disableReason);
assertEquals(false, networkDisableReason.configTemporarilyDisabled);
assertEquals(true, networkDisableReason.configPermanentlyDisabled);
}
/**
* Test the logging of UserActionEvent with invalid network ID
*/
@Test
public void testLogUserActionEventInvalidNetworkId() throws Exception {
int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
int testNetworkId = 0;
long testStartTimeMillis = 123123L;
when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(null);
mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
dumpProtoAndDeserialize();
WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
assertEquals(1, userActionEvents.length);
assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
userActionEvents[0].eventType);
assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
assertNull(userActionEvents[0].targetNetworkInfo);
}
/**
* Verify that the max length of the UserActionEvent list is limited to MAX_USER_ACTION_EVENTS.
*/
@Test
public void testLogUserActionEventCapped() throws Exception {
for (int i = 0; i < WifiMetrics.MAX_USER_ACTION_EVENTS + 1; i++) {
mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, 0);
}
dumpProtoAndDeserialize();
assertEquals(WifiMetrics.MAX_USER_ACTION_EVENTS, mDecodedProto.userActionEvents.length);
}
/**
* Ensure WifiMetrics doesn't cause a null pointer exception when called with null args
*/
@Test
public void testDumpNullArg() {
mWifiMetrics.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
}
/**
* Test the generation of 'NumConnectableNetwork' histograms from two scans of different
* ScanDetails produces the correct histogram values, and relevant bounds are observed
*/
@MediumTest
@Test
public void testNumConnectableNetworksGeneration() throws Exception {
List<ScanDetail> scan = new ArrayList<ScanDetail>();
// ssid, bssid, isOpen, isSaved, isProvider, isWeakRssi)
scan.add(buildMockScanDetail("PASSPOINT_1", "bssid0", false, false, true, false));
scan.add(buildMockScanDetail("PASSPOINT_2", "bssid1", false, false, true, false));
scan.add(buildMockScanDetail("SSID_B", "bssid2", true, true, false, false));
scan.add(buildMockScanDetail("SSID_B", "bssid3", true, true, false, false));
scan.add(buildMockScanDetail("SSID_C", "bssid4", true, false, false, false));
scan.add(buildMockScanDetail("SSID_D", "bssid5", false, true, false, false));
scan.add(buildMockScanDetail("SSID_E", "bssid6", false, true, false, false));
scan.add(buildMockScanDetail("SSID_F", "bssid7", false, false, false, false));
scan.add(buildMockScanDetail("SSID_G_WEAK", "bssid9", false, false, false, true));
scan.add(buildMockScanDetail("SSID_H_WEAK", "bssid10", false, false, false, true));
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
scan.add(buildMockScanDetail("SSID_B", "bssid8", true, true, false, false));
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
for (int i = 0; i < NUM_PARTIAL_SCAN_RESULTS; i++) {
mWifiMetrics.incrementAvailableNetworksHistograms(scan, false);
}
dumpProtoAndDeserialize();
verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1, a(7), a(2));
verifyHist(mDecodedProto.totalBssidsInScanHistogram, 2, a(8, 9), a(1, 1));
verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1, a(2), a(2));
verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 2, a(3, 4), a(1, 1));
verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1, a(3), a(2));
verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 2, a(4, 5), a(1, 1));
verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1, a(4), a(2));
verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 2, a(5, 6), a(1, 1));
verifyHist(mDecodedProto.availableSavedPasspointProviderProfilesInScanHistogram, 1,
a(2), a(2));
verifyHist(mDecodedProto.availableSavedPasspointProviderBssidsInScanHistogram, 1,
a(2), a(2));
assertEquals(2, mDecodedProto.fullBandAllSingleScanListenerResults);
assertEquals(NUM_PARTIAL_SCAN_RESULTS, mDecodedProto.partialAllSingleScanListenerResults);
// Check Bounds
scan.clear();
int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET,
WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET) + 5;
for (int i = 0; i < lotsOfSSids; i++) {
scan.add(buildMockScanDetail("SSID_" + i, "bssid_" + i, true, true, false, false));
}
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
dumpProtoAndDeserialize();
verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET), a(1));
verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1,
a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1,
a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1,
a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
scan.clear();
int lotsOfBssids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET,
WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET) + 5;
for (int i = 0; i < lotsOfBssids; i++) {
scan.add(buildMockScanDetail("SSID", "bssid_" + i, true, true, false, false));
}
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
dumpProtoAndDeserialize();
verifyHist(mDecodedProto.totalBssidsInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET), a(1));
verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 1,
a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 1,
a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 1,
a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
}
/**
* Test that Hotspot 2.0 (Passpoint) scan results are collected correctly and that relevant
* bounds are observed.
*/
@Test
public void testObservedHotspotAps() throws Exception {
List<ScanDetail> scan = new ArrayList<ScanDetail>();
// 2 R1 (Unknown AP isn't counted) passpoint APs belonging to a single provider: hessid1
long hessid1 = 10;
int anqpDomainId1 = 5;
scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX", "00:02:03:04:05:06", hessid1,
anqpDomainId1, NetworkDetail.HSRelease.R1, true));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY", "01:02:03:04:05:06", hessid1,
anqpDomainId1, NetworkDetail.HSRelease.R1, true));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_XYZ", "02:02:03:04:05:06", hessid1,
anqpDomainId1, NetworkDetail.HSRelease.Unknown, true));
// 2 R2 passpoint APs belonging to a single provider: hessid2
long hessid2 = 12;
int anqpDomainId2 = 6;
scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid2,
anqpDomainId2, NetworkDetail.HSRelease.R2, true));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid2,
anqpDomainId2, NetworkDetail.HSRelease.R2, true));
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
scan = new ArrayList<ScanDetail>();
// 3 R2 passpoint APs belonging to a single provider: hessid3 (in next scan)
long hessid3 = 15;
int anqpDomainId3 = 8;
scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3,
anqpDomainId3, NetworkDetail.HSRelease.R2, true));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3,
anqpDomainId3, NetworkDetail.HSRelease.R2, false));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid3,
anqpDomainId3, NetworkDetail.HSRelease.R2, true));
// 2 R3 Passpoint APs belonging to a single provider: hessid4
long hessid4 = 17;
int anqpDomainId4 = 2;
scan.add(buildMockScanDetailPasspoint("PASSPOINT_R3", "0C:02:03:04:05:01", hessid4,
anqpDomainId4, NetworkDetail.HSRelease.R3, true));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_R3_2", "0C:02:03:04:05:02", hessid4,
anqpDomainId4, NetworkDetail.HSRelease.R3, true));
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
dumpProtoAndDeserialize();
verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 2, a(0, 2), a(1, 1));
verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 2, a(2, 3), a(1, 1));
verifyHist(mDecodedProto.observedHotspotR3ApsInScanHistogram, 2, a(0, 2), a(1, 1));
verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 2, a(0, 1), a(1, 1));
verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, a(1), a(2));
verifyHist(mDecodedProto.observedHotspotR3EssInScanHistogram, 2, a(0, 1), a(1, 1));
verifyHist(mDecodedProto.observedHotspotR1ApsPerEssInScanHistogram, 1, a(2), a(1));
verifyHist(mDecodedProto.observedHotspotR2ApsPerEssInScanHistogram, 2, a(2, 3), a(1, 1));
verifyHist(mDecodedProto.observedHotspotR3ApsPerEssInScanHistogram, 1, a(2), a(1));
// check bounds
scan.clear();
int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET,
WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET) + 5;
for (int i = 0; i < lotsOfSSids; i++) {
scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX" + i, "00:02:03:04:05:06", i,
i + 10, NetworkDetail.HSRelease.R1, true));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY" + i, "AA:02:03:04:05:06", 1000 * i,
i + 10, NetworkDetail.HSRelease.R2, false));
scan.add(buildMockScanDetailPasspoint("PASSPOINT_XZ" + i, "0B:02:03:04:05:06", 101 * i,
i + 10, NetworkDetail.HSRelease.R3, false));
}
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
dumpProtoAndDeserialize();
verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
verifyHist(mDecodedProto.observedHotspotR3ApsInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
verifyHist(mDecodedProto.observedHotspotR3EssInScanHistogram, 1,
a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
}
/**
* Test that IEEE 802.11mc scan results are collected correctly and that relevant
* bounds are observed.
*/
@Test
public void testObserved80211mcAps() throws Exception {
ScanDetail mockScanDetailNon80211mc = mock(ScanDetail.class);
ScanDetail mockScanDetail80211mc = mock(ScanDetail.class);
NetworkDetail mockNetworkDetailNon80211mc = mock(NetworkDetail.class);
NetworkDetail mockNetworkDetail80211mc = mock(NetworkDetail.class);
when(mockNetworkDetail80211mc.is80211McResponderSupport()).thenReturn(true);
ScanResult mockScanResult = mock(ScanResult.class);
mockScanResult.capabilities = "";
when(mockScanDetailNon80211mc.getNetworkDetail()).thenReturn(mockNetworkDetailNon80211mc);
when(mockScanDetail80211mc.getNetworkDetail()).thenReturn(mockNetworkDetail80211mc);
when(mockScanDetailNon80211mc.getScanResult()).thenReturn(mockScanResult);
when(mockScanDetail80211mc.getScanResult()).thenReturn(mockScanResult);
when(mWns.isSignalTooWeak(eq(mockScanDetail80211mc.getScanResult()))).thenReturn(true);
List<ScanDetail> scan = new ArrayList<ScanDetail>();
// 4 scans (a few non-802.11mc supporting APs on each)
// scan1: no 802.11mc supporting APs
scan.add(mockScanDetailNon80211mc);
scan.add(mockScanDetailNon80211mc);
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
// scan2: 2 802.11mc supporting APs
scan.clear();
scan.add(mockScanDetailNon80211mc);
scan.add(mockScanDetail80211mc);
scan.add(mockScanDetail80211mc);
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
// scan3: 100 802.11mc supporting APs (> limit)
scan.clear();
scan.add(mockScanDetailNon80211mc);
scan.add(mockScanDetailNon80211mc);
scan.add(mockScanDetailNon80211mc);
for (int i = 0; i < 100; ++i) {
scan.add(mockScanDetail80211mc);
}
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
// scan4: 2 802.11mc supporting APs
scan.clear();
scan.add(mockScanDetailNon80211mc);
scan.add(mockScanDetail80211mc);
scan.add(mockScanDetail80211mc);
scan.add(mockScanDetailNon80211mc);
mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
dumpProtoAndDeserialize();
verifyHist(mDecodedProto.observed80211McSupportingApsInScanHistogram, 3,
a(0, 2, WifiMetrics.MAX_TOTAL_80211MC_APS_BUCKET), a(1, 2, 1));
}
/**
* Test Open Network Notification blacklist size and feature state are not cleared when proto
* is dumped.
*/
@Test
public void testOpenNetworkNotificationBlacklistSizeAndFeatureStateNotCleared()
throws Exception {
mWifiMetrics.setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG,
SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST);
mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG,
IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) {
mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG);
}
// This should clear most metrics in mWifiMetrics
dumpProtoAndDeserialize();
assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST,
mDecodedProto.openNetworkRecommenderBlacklistSize);
assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
mDecodedProto.isWifiNetworksAvailableNotificationOn);
assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES,
mDecodedProto.numOpenNetworkRecommendationUpdates);
// Check that blacklist size and feature state persist on next dump but
// others do not.
dumpProtoAndDeserialize();
assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST,
mDecodedProto.openNetworkRecommenderBlacklistSize);
assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
mDecodedProto.isWifiNetworksAvailableNotificationOn);
assertEquals(0, mDecodedProto.numOpenNetworkRecommendationUpdates);
}
/**
* Check network selector id
*/
@Test
public void testNetworkSelectorExperimentId() throws Exception {
final int id = 42888888;
mWifiMetrics.setNetworkSelectorExperimentId(id);
mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(id, mDecodedProto.connectionEvent[0].networkSelectorExperimentId);
}
/**
* Check pmk cache
*/
@Test
public void testConnectionWithPmkCache() throws Exception {
mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.setConnectionPmkCache(true);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(true, mDecodedProto.connectionEvent[0].routerFingerprint.pmkCacheEnabled);
}
/**
* Check max supported link speed and consecutive connection failure count
*/
@Test
public void testConnectionMaxSupportedLinkSpeedConsecutiveFailureCnt() throws Exception {
mWifiMetrics.setScreenState(true);
when(mNetworkConnectionStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE))
.thenReturn(2);
mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(MAX_SUPPORTED_TX_LINK_SPEED_MBPS,
MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(MAX_SUPPORTED_TX_LINK_SPEED_MBPS, mDecodedProto.connectionEvent[0]
.routerFingerprint.maxSupportedTxLinkSpeedMbps);
assertEquals(MAX_SUPPORTED_RX_LINK_SPEED_MBPS, mDecodedProto.connectionEvent[0]
.routerFingerprint.maxSupportedRxLinkSpeedMbps);
assertEquals(2, mDecodedProto.connectionEvent[0].numConsecutiveConnectionFailure);
assertEquals(true, mDecodedProto.connectionEvent[0].screenOn);
}
/**
* Check ScoringParams
*/
@Test
public void testExperimentId() throws Exception {
final int id = 42;
final String expectId = "x" + id;
when(mScoringParams.getExperimentIdentifier()).thenReturn(id);
dumpProtoAndDeserialize();
assertEquals(expectId, mDecodedProto.scoreExperimentId);
}
/**
* Check ScoringParams default case
*/
@Test
public void testDefaultExperimentId() throws Exception {
final int id = 0;
final String expectId = "";
when(mScoringParams.getExperimentIdentifier()).thenReturn(id);
dumpProtoAndDeserialize();
assertEquals(expectId, mDecodedProto.scoreExperimentId);
}
/** short hand for instantiating an anonymous int array, instead of 'new int[]{a1, a2, ...}' */
private int[] a(int... element) {
return element;
}
private void verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size,
int[] keys, int[] counts) throws Exception {
assertEquals(size, hist.length);
for (int i = 0; i < keys.length; i++) {
assertEquals(keys[i], hist[i].numConnectableNetworks);
assertEquals(counts[i], hist[i].count);
}
}
/**
* Generate an RSSI delta event by creating a connection event and an RSSI poll within
* 'interArrivalTime' milliseconds of each other.
* Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS
* successfulConnectionEvent, completeConnectionEvent, useValidScanResult and
* dontDeserializeBeforePoll
* each create an anomalous condition when set to false.
*/
private void generateRssiDelta(int scanRssi, int rssiDelta,
long interArrivalTime, boolean successfulConnectionEvent,
boolean completeConnectionEvent, boolean useValidScanResult,
boolean dontDeserializeBeforePoll) throws Exception {
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
ScanResult scanResult = null;
if (useValidScanResult) {
scanResult = mock(ScanResult.class);
scanResult.level = scanRssi;
}
WifiConfiguration config = mock(WifiConfiguration.class);
WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
mock(WifiConfiguration.NetworkSelectionStatus.class);
config.allowedKeyManagement = new BitSet();
when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
mWifiMetrics.startConnectionEvent(config, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
if (completeConnectionEvent) {
if (successfulConnectionEvent) {
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
} else {
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
}
}
when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime);
if (!dontDeserializeBeforePoll) {
dumpProtoAndDeserialize();
}
mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, scanRssi + rssiDelta);
}
/**
* Generate an RSSI delta event, with all extra conditions set to true.
*/
private void generateRssiDelta(int scanRssi, int rssiDelta,
long interArrivalTime) throws Exception {
generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true);
}
private void assertStringContains(
String actualString, String expectedSubstring) {
assertTrue("Expected text not found in: " + actualString,
actualString.contains(expectedSubstring));
}
private String getStateDump() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(stream);
String[] args = new String[0];
mWifiMetrics.dump(null, writer, args);
writer.flush();
return stream.toString();
}
private static final int TEST_ALLOWED_KEY_MANAGEMENT = 83;
private static final int TEST_ALLOWED_PROTOCOLS = 22;
private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11;
private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67;
private static final int TEST_ALLOWED_GROUP_CIPHERS = 231;
private static final int TEST_CANDIDATE_LEVEL = -80;
private static final int TEST_CANDIDATE_FREQ = 2345;
private WifiConfiguration createComplexWifiConfig() {
WifiConfiguration config = new WifiConfiguration();
config.SSID = SSID;
config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT);
config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS);
config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS);
config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS);
config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS);
config.hiddenSSID = true;
config.ephemeral = true;
config.getNetworkSelectionStatus().setHasEverConnected(true);
ScanResult candidate = new ScanResult();
candidate.level = TEST_CANDIDATE_LEVEL;
candidate.frequency = TEST_CANDIDATE_FREQ;
config.getNetworkSelectionStatus().setCandidate(candidate);
return config;
}
private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config,
StaEvent.ConfigInfo info) {
if (config == null && info == null) return;
assertEquals(config.allowedKeyManagement, intToBitSet(info.allowedKeyManagement));
assertEquals(config.allowedProtocols, intToBitSet(info.allowedProtocols));
assertEquals(config.allowedAuthAlgorithms, intToBitSet(info.allowedAuthAlgorithms));
assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers));
assertEquals(config.allowedGroupCiphers, intToBitSet(info.allowedGroupCiphers));
assertEquals(config.hiddenSSID, info.hiddenSsid);
assertEquals(config.ephemeral, info.isEphemeral);
assertEquals(config.getNetworkSelectionStatus().hasEverConnected(),
info.hasEverConnected);
assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi);
assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq);
}
/**
* Sets the values of bitSet to match an int mask
*/
private static BitSet intToBitSet(int mask) {
BitSet bitSet = new BitSet();
for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) {
if ((mask & 1) != 0) bitSet.set(bitIndex);
}
return bitSet;
}
private static final int NUM_UNUSABLE_EVENT = 5;
private static final int NUM_UNUSABLE_EVENT_TIME_THROTTLE = 3;
/**
* Values used to generate WifiIsUnusableEvent
* <WifiIsUnusableEvent.TriggerType>, <last_score>, <tx_success_delta>, <tx_retries_delta>,
* <tx_bad_delta>, <rx_success_delta>, <packet_update_time_delta>, <firmware_alert_code>,
* <last_wifi_usability_score>, <mobile_tx_bytes>, <mobile_rx_bytes>, <total_tx_bytes>,
* <total_rx_bytes>,
*/
private int[][] mTestUnusableEvents = {
{WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, 60, 60, 50, 40, 30, 1000, -1, 51,
11, 12, 13, 14},
{WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, 55, 40, 30, 0, 0, 500, -1, 52,
15, 16, 17, 18},
{WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH, 60, 90, 30, 30, 0, 1000, -1, 53,
19, 20, 21, 22},
{WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, 55, 55, 30, 15, 10, 1000, 4, 54,
23, 24, 25, 26},
{WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST, 50, 56, 28, 17, 12, 1000, -1, 45,
27, 28, 29, 30}
};
/**
* Generate all WifiIsUnusableEvents from mTestUnusableEvents
*/
private void generateAllUnusableEvents(WifiMetrics wifiMetrics) {
for (int i = 0; i < mTestUnusableEvents.length; i++) {
generateUnusableEventAtGivenTime(i, i * (WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000));
}
}
/**
* Generate a WifiIsUnusableEvent at the given timestamp with data from
* mTestUnusableEvents[index]
*/
private void generateUnusableEventAtGivenTime(int index, long eventTime) {
when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime);
int[] trigger = mTestUnusableEvents[index];
when(mFacade.getMobileTxBytes()).thenReturn((long) trigger[9]);
when(mFacade.getMobileRxBytes()).thenReturn((long) trigger[10]);
when(mFacade.getTotalTxBytes()).thenReturn((long) trigger[11]);
when(mFacade.getTotalRxBytes()).thenReturn((long) trigger[12]);
mWifiMetrics.incrementWifiScoreCount(trigger[1]);
mWifiMetrics.incrementWifiUsabilityScoreCount(1, trigger[8], 15);
mWifiMetrics.updateWifiIsUnusableLinkLayerStats(trigger[2], trigger[3], trigger[4],
trigger[5], trigger[6]);
mWifiMetrics.setScreenState(true);
switch(trigger[0]) {
case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
mWifiMetrics.logWifiIsUnusableEvent(trigger[0]);
break;
case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
mWifiMetrics.logWifiIsUnusableEvent(trigger[0], trigger[7]);
break;
case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
mWifiMetrics.logWifiIsUnusableEvent(trigger[0]);
break;
default:
break;
}
}
/**
* Verify that WifiIsUnusableEvent in wifiLog matches mTestUnusableEvents
*/
private void verifyDeserializedUnusableEvents(WifiMetricsProto.WifiLog wifiLog) {
assertEquals(NUM_UNUSABLE_EVENT, wifiLog.wifiIsUnusableEventList.length);
for (int i = 0; i < mTestUnusableEvents.length; i++) {
WifiIsUnusableEvent event = wifiLog.wifiIsUnusableEventList[i];
verifyUnusableEvent(event, i);
}
}
/**
* Verify that the given WifiIsUnusableEvent matches mTestUnusableEvents
* at given index
*/
private void verifyUnusableEvent(WifiIsUnusableEvent event, int index) {
int[] expectedValues = mTestUnusableEvents[index];
assertEquals(expectedValues[0], event.type);
assertEquals(expectedValues[1], event.lastScore);
assertEquals(expectedValues[2], event.txSuccessDelta);
assertEquals(expectedValues[3], event.txRetriesDelta);
assertEquals(expectedValues[4], event.txBadDelta);
assertEquals(expectedValues[5], event.rxSuccessDelta);
assertEquals(expectedValues[6], event.packetUpdateTimeDelta);
assertEquals(expectedValues[7], event.firmwareAlertCode);
assertEquals(expectedValues[8], event.lastWifiUsabilityScore);
assertEquals(true, event.screenOn);
assertEquals(expectedValues[9], event.mobileTxBytes);
assertEquals(expectedValues[10], event.mobileRxBytes);
assertEquals(expectedValues[11], event.totalTxBytes);
assertEquals(expectedValues[12], event.totalRxBytes);
}
/**
* Verify that no WifiIsUnusableEvent is generated when it is disabled in the settings
*/
@Test
public void testNoUnusableEventLogWhenDisabled() throws Exception {
mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, false);
generateAllUnusableEvents(mWifiMetrics);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiIsUnusableEventList.length);
}
/**
* Generate WifiIsUnusableEvent and verify that they are logged correctly
*/
@Test
public void testUnusableEventLogSerializeDeserialize() throws Exception {
mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true);
generateAllUnusableEvents(mWifiMetrics);
dumpProtoAndDeserialize();
verifyDeserializedUnusableEvents(mDecodedProto);
}
/**
* Verify that the number of WifiIsUnusableEvents does not exceed MAX_UNUSABLE_EVENTS
*/
@Test
public void testUnusableEventBounding() throws Exception {
mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true);
for (int i = 0; i < (WifiMetrics.MAX_UNUSABLE_EVENTS + 2); i++) {
generateAllUnusableEvents(mWifiMetrics);
}
dumpProtoAndDeserialize();
assertEquals(WifiMetrics.MAX_UNUSABLE_EVENTS, mDecodedProto.wifiIsUnusableEventList.length);
}
/**
* Verify that we don't generate new WifiIsUnusableEvent from data stalls
* until MIN_DATA_STALL_WAIT_MS has passed since the last data stall WifiIsUnusableEvent
*/
@Test
public void testUnusableEventTimeThrottleForDataStall() throws Exception {
mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true);
generateUnusableEventAtGivenTime(0, 0);
// should be time throttled
generateUnusableEventAtGivenTime(1, 1);
generateUnusableEventAtGivenTime(2, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000);
// no time throttle for firmware alert
generateUnusableEventAtGivenTime(3, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1001);
dumpProtoAndDeserialize();
assertEquals(NUM_UNUSABLE_EVENT_TIME_THROTTLE,
mDecodedProto.wifiIsUnusableEventList.length);
verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[0], 0);
verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[1], 2);
verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[2], 3);
}
/**
* Verify that LinkSpeedCounts is correctly logged in metrics
*/
@Test
public void testLinkSpeedCounts() throws Exception {
mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true);
for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
for (int j = 0; j <= i; j++) {
mWifiMetrics.incrementLinkSpeedCount(
WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL);
}
}
dumpProtoAndDeserialize();
assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT, mDecodedProto.linkSpeedCounts.length);
for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
assertEquals("Incorrect link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i,
mDecodedProto.linkSpeedCounts[i].linkSpeedMbps);
assertEquals("Incorrect count of link speed",
i + 1, mDecodedProto.linkSpeedCounts[i].count);
assertEquals("Incorrect sum of absolute values of rssi values",
Math.abs(TEST_RSSI_LEVEL) * (i + 1),
mDecodedProto.linkSpeedCounts[i].rssiSumDbm);
assertEquals("Incorrect sum of squares of rssi values",
TEST_RSSI_LEVEL * TEST_RSSI_LEVEL * (i + 1),
mDecodedProto.linkSpeedCounts[i].rssiSumOfSquaresDbmSq);
}
}
/**
* Verify that Tx and Rx per-band LinkSpeedCounts are correctly logged in metrics
*/
@Test
public void testTxRxLinkSpeedBandCounts() throws Exception {
mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true);
for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
for (int j = 0; j <= i; j++) {
mWifiMetrics.incrementTxLinkSpeedBandCount(
WifiMetrics.MIN_LINK_SPEED_MBPS + i, RSSI_POLL_FREQUENCY);
mWifiMetrics.incrementRxLinkSpeedBandCount(
WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1, RSSI_POLL_FREQUENCY);
}
}
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.txLinkSpeedCount2G.length);
assertEquals(0, mDecodedProto.rxLinkSpeedCount2G.length);
assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT,
mDecodedProto.txLinkSpeedCount5GLow.length);
assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT,
mDecodedProto.rxLinkSpeedCount5GLow.length);
assertEquals(0, mDecodedProto.txLinkSpeedCount5GMid.length);
assertEquals(0, mDecodedProto.rxLinkSpeedCount5GMid.length);
assertEquals(0, mDecodedProto.txLinkSpeedCount5GHigh.length);
assertEquals(0, mDecodedProto.rxLinkSpeedCount5GHigh.length);
for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
assertEquals("Incorrect Tx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i,
mDecodedProto.txLinkSpeedCount5GLow[i].key);
assertEquals("Incorrect Rx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1,
mDecodedProto.rxLinkSpeedCount5GLow[i].key);
assertEquals("Incorrect count of Tx link speed",
i + 1, mDecodedProto.txLinkSpeedCount5GLow[i].count);
assertEquals("Incorrect count of Rx link speed",
i + 1, mDecodedProto.rxLinkSpeedCount5GLow[i].count);
}
}
/**
* Verify that LinkSpeedCounts is not logged when disabled in settings
*/
@Test
public void testNoLinkSpeedCountsWhenDisabled() throws Exception {
mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, false);
for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
for (int j = 0; j <= i; j++) {
mWifiMetrics.incrementLinkSpeedCount(
WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL);
mWifiMetrics.incrementTxLinkSpeedBandCount(
WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
mWifiMetrics.incrementRxLinkSpeedBandCount(
WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
}
}
dumpProtoAndDeserialize();
assertEquals("LinkSpeedCounts should not be logged when disabled in settings",
0, mDecodedProto.linkSpeedCounts.length);
assertEquals("Tx LinkSpeedCounts should not be logged when disabled in settings",
0, mDecodedProto.txLinkSpeedCount5GLow.length);
assertEquals("Rx LinkSpeedCounts should not be logged when disabled in settings",
0, mDecodedProto.rxLinkSpeedCount5GLow.length);
}
/**
* Verify that LinkSpeedCounts is not logged when the link speed value is lower than
* MIN_LINK_SPEED_MBPS or when the rssi value is outside of
* [MIN_RSSI_LEVEL, MAX_RSSI_LEVEL]
*/
@Test
public void testNoLinkSpeedCountsForOutOfBoundValues() throws Exception {
mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true);
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementLinkSpeedCount(
WifiMetrics.MIN_LINK_SPEED_MBPS - i, MIN_RSSI_LEVEL);
mWifiMetrics.incrementTxLinkSpeedBandCount(
WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
mWifiMetrics.incrementRxLinkSpeedBandCount(
WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementLinkSpeedCount(
WifiMetrics.MIN_LINK_SPEED_MBPS, MIN_RSSI_LEVEL - i);
}
for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
mWifiMetrics.incrementLinkSpeedCount(
WifiMetrics.MIN_LINK_SPEED_MBPS, MAX_RSSI_LEVEL + i);
}
dumpProtoAndDeserialize();
assertEquals("LinkSpeedCounts should not be logged for out of bound values",
0, mDecodedProto.linkSpeedCounts.length);
assertEquals("Tx LinkSpeedCounts should not be logged for out of bound values",
0, mDecodedProto.txLinkSpeedCount5GLow.length);
assertEquals("Rx LinkSpeedCounts should not be logged for out of bound values",
0, mDecodedProto.rxLinkSpeedCount5GLow.length);
}
private int nextRandInt() {
return mRandom.nextInt(1000);
}
private WifiLinkLayerStats nextRandomStats(WifiLinkLayerStats current) {
WifiLinkLayerStats out = new WifiLinkLayerStats();
out.timeStampInMs = current.timeStampInMs + nextRandInt();
out.rxmpdu_be = current.rxmpdu_be + nextRandInt();
out.txmpdu_be = current.txmpdu_be + nextRandInt();
out.lostmpdu_be = current.lostmpdu_be + nextRandInt();
out.retries_be = current.retries_be + nextRandInt();
out.rxmpdu_bk = current.rxmpdu_bk + nextRandInt();
out.txmpdu_bk = current.txmpdu_bk + nextRandInt();
out.lostmpdu_bk = current.lostmpdu_bk + nextRandInt();
out.retries_bk = current.retries_bk + nextRandInt();
out.rxmpdu_vi = current.rxmpdu_vi + nextRandInt();
out.txmpdu_vi = current.txmpdu_vi + nextRandInt();
out.lostmpdu_vi = current.lostmpdu_vi + nextRandInt();
out.retries_vi = current.retries_vi + nextRandInt();
out.rxmpdu_vo = current.rxmpdu_vo + nextRandInt();
out.txmpdu_vo = current.txmpdu_vo + nextRandInt();
out.lostmpdu_vo = current.lostmpdu_vo + nextRandInt();
out.retries_vo = current.retries_vo + nextRandInt();
out.on_time = current.on_time + nextRandInt();
out.tx_time = current.tx_time + nextRandInt();
out.rx_time = current.rx_time + nextRandInt();
out.on_time_scan = current.on_time_scan + nextRandInt();
out.on_time_nan_scan = current.on_time_nan_scan + nextRandInt();
out.on_time_background_scan = current.on_time_background_scan + nextRandInt();
out.on_time_roam_scan = current.on_time_roam_scan + nextRandInt();
out.on_time_pno_scan = current.on_time_pno_scan + nextRandInt();
out.on_time_hs20_scan = current.on_time_hs20_scan + nextRandInt();
return out;
}
private void assertWifiLinkLayerUsageHasDiff(WifiLinkLayerStats oldStats,
WifiLinkLayerStats newStats) {
assertEquals(newStats.timeStampInMs - oldStats.timeStampInMs,
mDecodedProto.wifiLinkLayerUsageStats.loggingDurationMs);
assertEquals(newStats.on_time - oldStats.on_time,
mDecodedProto.wifiLinkLayerUsageStats.radioOnTimeMs);
assertEquals(newStats.tx_time - oldStats.tx_time,
mDecodedProto.wifiLinkLayerUsageStats.radioTxTimeMs);
assertEquals(newStats.rx_time - oldStats.rx_time,
mDecodedProto.wifiLinkLayerUsageStats.radioRxTimeMs);
assertEquals(newStats.on_time_scan - oldStats.on_time_scan,
mDecodedProto.wifiLinkLayerUsageStats.radioScanTimeMs);
assertEquals(newStats.on_time_nan_scan - oldStats.on_time_nan_scan,
mDecodedProto.wifiLinkLayerUsageStats.radioNanScanTimeMs);
assertEquals(newStats.on_time_background_scan - oldStats.on_time_background_scan,
mDecodedProto.wifiLinkLayerUsageStats.radioBackgroundScanTimeMs);
assertEquals(newStats.on_time_roam_scan - oldStats.on_time_roam_scan,
mDecodedProto.wifiLinkLayerUsageStats.radioRoamScanTimeMs);
assertEquals(newStats.on_time_pno_scan - oldStats.on_time_pno_scan,
mDecodedProto.wifiLinkLayerUsageStats.radioPnoScanTimeMs);
assertEquals(newStats.on_time_hs20_scan - oldStats.on_time_hs20_scan,
mDecodedProto.wifiLinkLayerUsageStats.radioHs20ScanTimeMs);
}
/**
* Verify that WifiMetrics is counting link layer usage correctly when given a series of
* valid input.
* @throws Exception
*/
@Test
public void testWifiLinkLayerUsageStats() throws Exception {
WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats());
WifiLinkLayerStats stat2 = nextRandomStats(stat1);
WifiLinkLayerStats stat3 = nextRandomStats(stat2);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat3);
dumpProtoAndDeserialize();
// After 2 increments, the counters should have difference between |stat1| and |stat3|
assertWifiLinkLayerUsageHasDiff(stat1, stat3);
}
/**
* Verify that null input is handled and wifi link layer usage stats are not incremented.
* @throws Exception
*/
@Test
public void testWifiLinkLayerUsageStatsNullInput() throws Exception {
WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats());
WifiLinkLayerStats stat2 = null;
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2);
dumpProtoAndDeserialize();
// Counter should be zero
assertWifiLinkLayerUsageHasDiff(stat1, stat1);
}
/**
* Verify that when the new data appears to be bad link layer usage stats are not being
* incremented and the buffered WifiLinkLayerStats get cleared.
* @throws Exception
*/
@Test
public void testWifiLinkLayerUsageStatsChipReset() throws Exception {
WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats());
WifiLinkLayerStats stat2 = nextRandomStats(stat1);
stat2.on_time = stat1.on_time - 1;
WifiLinkLayerStats stat3 = nextRandomStats(stat2);
WifiLinkLayerStats stat4 = nextRandomStats(stat3);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat3);
mWifiMetrics.incrementWifiLinkLayerUsageStats(stat4);
dumpProtoAndDeserialize();
// Should only count the difference between |stat3| and |stat4|
assertWifiLinkLayerUsageHasDiff(stat3, stat4);
}
private void assertUsabilityStatsAssignment(WifiInfo info, WifiLinkLayerStats stats,
WifiUsabilityStatsEntry usabilityStats) {
assertEquals(info.getRssi(), usabilityStats.rssi);
assertEquals(info.getLinkSpeed(), usabilityStats.linkSpeedMbps);
assertEquals(info.getRxLinkSpeedMbps(), usabilityStats.rxLinkSpeedMbps);
assertEquals(stats.timeStampInMs, usabilityStats.timeStampMs);
assertEquals(stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo,
usabilityStats.totalTxSuccess);
assertEquals(stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo,
usabilityStats.totalTxRetries);
assertEquals(stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo,
usabilityStats.totalTxBad);
assertEquals(stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo,
usabilityStats.totalRxSuccess);
assertEquals(stats.on_time, usabilityStats.totalRadioOnTimeMs);
assertEquals(stats.tx_time, usabilityStats.totalRadioTxTimeMs);
assertEquals(stats.rx_time, usabilityStats.totalRadioRxTimeMs);
assertEquals(stats.on_time_scan, usabilityStats.totalScanTimeMs);
assertEquals(stats.on_time_nan_scan, usabilityStats.totalNanScanTimeMs);
assertEquals(stats.on_time_background_scan, usabilityStats.totalBackgroundScanTimeMs);
assertEquals(stats.on_time_roam_scan, usabilityStats.totalRoamScanTimeMs);
assertEquals(stats.on_time_pno_scan, usabilityStats.totalPnoScanTimeMs);
assertEquals(stats.on_time_hs20_scan, usabilityStats.totalHotspot2ScanTimeMs);
assertEquals(stats.beacon_rx, usabilityStats.totalBeaconRx);
}
// Simulate adding a LABEL_GOOD WifiUsabilityStats
private WifiLinkLayerStats addGoodWifiUsabilityStats(WifiLinkLayerStats start) {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats = start;
for (int i = 0; i < WifiMetrics.NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats);
stats = nextRandomStats(stats);
}
return stats;
}
// Simulate adding a LABEL_BAD WifiUsabilityStats
private WifiLinkLayerStats addBadWifiUsabilityStats(WifiLinkLayerStats start) {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats1 = start;
WifiLinkLayerStats stats2 = nextRandomStats(stats1);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
return nextRandomStats(stats2);
}
/**
* Verify that updateWifiUsabilityStatsEntries correctly converts the inputs into
* a WifiUsabilityStatsEntry Object and then stores it.
*
* Verify that the converted metrics proto contains pairs of WifiUsabilityStats with
* LABEL_GOOD and LABEL_BAD
* @throws Exception
*/
@Test
public void testUpdateWifiUsabilityStatsEntries() throws Exception {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
when(info.getRxLinkSpeedMbps()).thenReturn(nextRandInt());
when(info.getBSSID()).thenReturn("Wifi");
when(info.getFrequency()).thenReturn(5745);
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
WifiLinkLayerStats stats2 = nextRandomStats(stats1);
mWifiMetrics.incrementWifiScoreCount(60);
mWifiMetrics.incrementWifiUsabilityScoreCount(2, 55, 15);
mWifiMetrics.logLinkProbeSuccess(nextRandInt(), nextRandInt(), nextRandInt(), 12);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
mWifiMetrics.incrementWifiScoreCount(58);
mWifiMetrics.incrementWifiUsabilityScoreCount(3, 56, 15);
mWifiMetrics.logLinkProbeFailure(nextRandInt(), nextRandInt(),
nextRandInt(), nextRandInt());
mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
// Add 2 LABEL_GOOD but only 1 should remain in the converted proto
WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats2));
statsGood.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
addGoodWifiUsabilityStats(statsGood);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
assertEquals(WifiUsabilityStats.LABEL_GOOD, mDecodedProto.wifiUsabilityStatsList[0].label);
assertEquals(WifiUsabilityStats.LABEL_BAD, mDecodedProto.wifiUsabilityStatsList[1].label);
assertUsabilityStatsAssignment(info, stats1,
mDecodedProto.wifiUsabilityStatsList[1].stats[0]);
assertUsabilityStatsAssignment(info, stats2,
mDecodedProto.wifiUsabilityStatsList[1].stats[1]);
assertEquals(2, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumToFramework);
assertEquals(3, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumToFramework);
assertEquals(0, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumInsideFramework);
assertEquals(1, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumInsideFramework);
assertEquals(60, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiScore);
assertEquals(58, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiScore);
assertEquals(55, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiUsabilityScore);
assertEquals(56, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiUsabilityScore);
assertEquals(15, mDecodedProto.wifiUsabilityStatsList[1].stats[0].predictionHorizonSec);
assertEquals(true, mDecodedProto.wifiUsabilityStatsList[1].stats[0].isSameBssidAndFreq);
assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS,
mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeStatusSinceLastUpdate);
assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE,
mDecodedProto.wifiUsabilityStatsList[1].stats[1].probeStatusSinceLastUpdate);
assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE,
mDecodedProto.wifiUsabilityStatsList[0].stats[0].probeStatusSinceLastUpdate);
assertEquals(12,
mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeElapsedTimeSinceLastUpdateMs);
assertEquals(Integer.MAX_VALUE, mDecodedProto.wifiUsabilityStatsList[1]
.stats[1].probeElapsedTimeSinceLastUpdateMs);
assertEquals(-1, mDecodedProto.wifiUsabilityStatsList[0]
.stats[0].probeElapsedTimeSinceLastUpdateMs);
assertEquals(DEVICE_MOBILITY_STATE_HIGH_MVMT, mDecodedProto.wifiUsabilityStatsList[1]
.stats[mDecodedProto.wifiUsabilityStatsList[1].stats.length - 1]
.deviceMobilityState);
}
/**
* Verify that when there are no WifiUsability events the generated proto also contains no
* such information.
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsZeroEvents() throws Exception {
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that we discard a WifiUsabilityStats with LABEL_GOOD if there is no corresponding
* LABEL_BAD
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsIgnoreSingleLabelGood() throws Exception {
addGoodWifiUsabilityStats(new WifiLinkLayerStats());
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that we discard a WifiUsabilityStats with LABEL_BAD if there is no corresponding
* LABEL_GOOD
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsIgnoreSingleLabelBad() throws Exception {
addBadWifiUsabilityStats(new WifiLinkLayerStats());
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that the buffer for WifiUsabilityStats does not exceed the max length.
* Do this by trying to add more WifiUsabilityStats than the max length and then
* verifying that the decoded proto's length does not exceed the max length.
*
* Also verify that the length for the list of WifiUsabilityStatsEntry is capped.
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsBufferSizeIsCapped() throws Exception {
// simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
WifiLinkLayerStats stats = new WifiLinkLayerStats();
for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE + 1; j++) {
stats = addGoodWifiUsabilityStats(stats);
stats = addBadWifiUsabilityStats(stats);
stats.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
}
dumpProtoAndDeserialize();
assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD,
mDecodedProto.wifiUsabilityStatsList.length);
for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) {
assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE,
mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length);
assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length);
}
}
/**
* Verify that LABEL_GOOD stats are not generated more frequently than
* |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsLabelGoodHasMinimumPeriod() throws Exception {
// simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
WifiLinkLayerStats stats = new WifiLinkLayerStats();
for (int j = 0; j < 2; j++) {
stats = addGoodWifiUsabilityStats(stats);
stats = addBadWifiUsabilityStats(stats);
}
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_BAD stats are not generated more frequently than |MIN_DATA_STALL_WAIT_MS|
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum() throws Exception {
// simulate adding two LABEL_GOOD WifiUsabilityStats
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
stats1 = addGoodWifiUsabilityStats(stats1);
stats2.timeStampInMs = stats1.timeStampInMs
+ WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
addGoodWifiUsabilityStats(stats2);
WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
stats3 = nextRandomStats(stats3);
}
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
stats4 = nextRandomStats(stats4);
}
stats4.timeStampInMs = stats3.timeStampInMs - 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_BAD stats are generated if timestamp gap is larger than
* |MIN_DATA_STALL_WAIT_MS|
* @throws Exception
*/
@Test
public void testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum() throws Exception {
// simulate adding two LABEL_GOOD WifiUsabilityStats
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
stats1 = addGoodWifiUsabilityStats(stats1);
stats2.timeStampInMs = stats1.timeStampInMs
+ WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
addGoodWifiUsabilityStats(stats2);
WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
stats3 = nextRandomStats(stats3);
}
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
stats4 = nextRandomStats(stats4);
}
stats4.timeStampInMs = stats3.timeStampInMs + 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
dumpProtoAndDeserialize();
assertEquals(4, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Tests device mobility state metrics as states are changed.
*/
@Test
public void testDeviceMobilityStateMetrics_changeState() throws Exception {
// timeMs is initialized to 0 by the setUp() method
long timeMs = 1000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
timeMs += 2000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_LOW_MVMT);
dumpProtoAndDeserialize();
DeviceMobilityStatePnoScanStats[] expected = {
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0),
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY, 1, 2000, 0),
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_LOW_MVMT, 1, 0, 0)
};
assertDeviceMobilityStatePnoScanStatsEqual(
expected, mDecodedProto.mobilityStatePnoStatsList);
}
/**
* Tests device mobility state metrics as PNO scans are started and stopped.
*/
@Test
public void testDeviceMobilityStateMetrics_startStopPnoScans() throws Exception {
long timeMs = 1000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.logPnoScanStart();
timeMs += 2000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.logPnoScanStop();
mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
mWifiMetrics.logPnoScanStart();
timeMs += 4000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.logPnoScanStop();
timeMs += 8000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
dumpProtoAndDeserialize();
DeviceMobilityStatePnoScanStats[] expected = {
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN,
1, 1000 + 2000, 2000),
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY,
1, 4000 + 8000, 4000),
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_HIGH_MVMT, 1, 0, 0)
};
assertDeviceMobilityStatePnoScanStatsEqual(
expected, mDecodedProto.mobilityStatePnoStatsList);
}
/**
* Tests that the initial state is set up correctly.
*/
@Test
public void testDeviceMobilityStateMetrics_initialState() throws Exception {
dumpProtoAndDeserialize();
DeviceMobilityStatePnoScanStats[] expected = {
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 0, 0)
};
assertDeviceMobilityStatePnoScanStatsEqual(
expected, mDecodedProto.mobilityStatePnoStatsList);
}
/**
* Tests that logPnoScanStart() updates the total duration in addition to the PNO duration.
*/
@Test
public void testDeviceMobilityStateMetrics_startPnoScansUpdatesTotalDuration()
throws Exception {
long timeMs = 1000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.logPnoScanStart();
dumpProtoAndDeserialize();
DeviceMobilityStatePnoScanStats[] expected = {
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0)
};
assertDeviceMobilityStatePnoScanStatsEqual(
expected, mDecodedProto.mobilityStatePnoStatsList);
}
/**
* Tests that logPnoScanStop() updates the total duration in addition to the PNO duration.
*/
@Test
public void testDeviceMobilityStateMetrics_stopPnoScansUpdatesTotalDuration()
throws Exception {
long timeMs = 1000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.logPnoScanStart();
timeMs += 2000;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
mWifiMetrics.logPnoScanStop();
dumpProtoAndDeserialize();
DeviceMobilityStatePnoScanStats[] expected = {
buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN,
1, 1000 + 2000, 2000)
};
assertDeviceMobilityStatePnoScanStatsEqual(
expected, mDecodedProto.mobilityStatePnoStatsList);
}
/**
* Verify that clients should be notified of activity in case Wifi stats get updated.
*/
@Test
public void testClientNotification() throws RemoteException {
// Register Client for verification.
ArgumentCaptor<android.net.wifi.WifiUsabilityStatsEntry> usabilityStats =
ArgumentCaptor.forClass(android.net.wifi.WifiUsabilityStatsEntry.class);
mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
// Client should get the stats.
verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
usabilityStats.capture());
assertEquals(usabilityStats.getValue().getTotalRadioOnTimeMillis(), linkLayerStats.on_time);
assertEquals(usabilityStats.getValue().getTotalTxBad(), linkLayerStats.lostmpdu_be
+ linkLayerStats.lostmpdu_bk + linkLayerStats.lostmpdu_vi
+ linkLayerStats.lostmpdu_vo);
assertEquals(usabilityStats.getValue().getTimeStampMillis(), linkLayerStats.timeStampInMs);
assertEquals(usabilityStats.getValue().getTotalRoamScanTimeMillis(),
linkLayerStats.on_time_roam_scan);
}
/**
* Verify that remove client should be handled
*/
@Test
public void testRemoveClient() throws RemoteException {
// Register Client for verification.
mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
mWifiMetrics.removeOnWifiUsabilityListener(TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
verify(mAppBinder).unlinkToDeath(any(), anyInt());
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
anyBoolean(), any());
}
/**
* Verify that WifiMetrics adds for death notification on adding client.
*/
@Test
public void testAddsForBinderDeathOnAddClient() throws Exception {
mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
}
/**
* Verify that client fails to get message when listener add failed.
*/
@Test
public void testAddsListenerFailureOnLinkToDeath() throws Exception {
doThrow(new RemoteException())
.when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
// Client should not get any message listener add failed.
verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
anyBoolean(), any());
}
/**
* Verify that the label and the triggerType of Wifi usability stats are saved correctly
* during firmware alert is triggered.
* @throws Exception
*/
@Test
public void verifyFirmwareAlertUpdatesWifiUsabilityMetrics() throws Exception {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
long eventTimeMs = nextRandInt();
when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
// Add 1 LABEL_GOOD
WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
// Firmware alert occurs
mWifiMetrics.logFirmwareAlert(2);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
assertEquals(WifiUsabilityStats.LABEL_GOOD, statsList[0].label);
assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
assertEquals(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, statsList[1].triggerType);
assertEquals(eventTimeMs, statsList[1].timeStampMs);
assertEquals(2, statsList[1].firmwareAlertCode);
}
/**
* Verify that the label and the triggerType of Wifi usability stats are saved correctly
* during Wifi data stall is triggered.
* @throws Exception
*/
@Test
public void verifyWifiDataStallUpdatesWifiUsabilityMetrics() throws Exception {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
long eventTimeMs = nextRandInt();
when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
// Add 1 LABEL_GOOD
WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
// Wifi data stall occurs
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, statsList[1].triggerType);
assertEquals(-1, statsList[1].firmwareAlertCode);
assertEquals(eventTimeMs, statsList[1].timeStampMs);
}
/**
* Test the generation of 'WifiConfigStoreIODuration' read histograms.
*/
@Test
public void testWifiConfigStoreReadDurationsHistogramGeneration() throws Exception {
mWifiMetrics.noteWifiConfigStoreReadDuration(10);
mWifiMetrics.noteWifiConfigStoreReadDuration(20);
mWifiMetrics.noteWifiConfigStoreReadDuration(100);
mWifiMetrics.noteWifiConfigStoreReadDuration(90);
mWifiMetrics.noteWifiConfigStoreReadDuration(130);
mWifiMetrics.noteWifiConfigStoreReadDuration(250);
mWifiMetrics.noteWifiConfigStoreReadDuration(600);
dumpProtoAndDeserialize();
assertEquals(5, mDecodedProto.wifiConfigStoreIo.readDurations.length);
assertEquals(0, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
assertEquals(Integer.MIN_VALUE,
mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeStartMs);
assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeEndMs);
assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[0].count);
assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeStartMs);
assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeEndMs);
assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[1].count);
assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeStartMs);
assertEquals(150, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeEndMs);
assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[2].count);
assertEquals(200, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeStartMs);
assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeEndMs);
assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[3].count);
assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeStartMs);
assertEquals(Integer.MAX_VALUE,
mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeEndMs);
assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[4].count);
}
/**
* Test the generation of 'WifiConfigStoreIODuration' write histograms.
*/
@Test
public void testWifiConfigStoreWriteDurationsHistogramGeneration() throws Exception {
mWifiMetrics.noteWifiConfigStoreWriteDuration(10);
mWifiMetrics.noteWifiConfigStoreWriteDuration(40);
mWifiMetrics.noteWifiConfigStoreWriteDuration(60);
mWifiMetrics.noteWifiConfigStoreWriteDuration(90);
mWifiMetrics.noteWifiConfigStoreWriteDuration(534);
mWifiMetrics.noteWifiConfigStoreWriteDuration(345);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiConfigStoreIo.readDurations.length);
assertEquals(3, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
assertEquals(Integer.MIN_VALUE,
mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeStartMs);
assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeEndMs);
assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[0].count);
assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeStartMs);
assertEquals(100, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeEndMs);
assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[1].count);
assertEquals(300, mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeStartMs);
assertEquals(Integer.MAX_VALUE,
mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeEndMs);
assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[2].count);
}
/**
* Test link probe metrics.
*/
@Test
public void testLogLinkProbeMetrics() throws Exception {
mWifiMetrics.logLinkProbeSuccess(10000, -75, 50, 5);
mWifiMetrics.logLinkProbeFailure(30000, -80, 10,
WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK);
mWifiMetrics.logLinkProbeSuccess(3000, -71, 160, 12);
mWifiMetrics.logLinkProbeFailure(40000, -80, 6,
WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK);
mWifiMetrics.logLinkProbeSuccess(5000, -73, 160, 10);
mWifiMetrics.logLinkProbeFailure(2000, -78, 6,
WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_TIMEOUT);
dumpProtoAndDeserialize();
StaEvent[] expected = {
buildLinkProbeSuccessStaEvent(5),
buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK),
buildLinkProbeSuccessStaEvent(12),
buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK),
buildLinkProbeSuccessStaEvent(10),
buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT)
};
assertLinkProbeStaEventsEqual(expected, mDecodedProto.staEventList);
LinkProbeStats linkProbeStats = mDecodedProto.linkProbeStats;
Int32Count[] expectedSuccessRssiHistogram = {
buildInt32Count(-75, 1),
buildInt32Count(-73, 1),
buildInt32Count(-71, 1),
};
assertKeyCountsEqual(expectedSuccessRssiHistogram,
linkProbeStats.successRssiCounts);
Int32Count[] expectedFailureRssiHistogram = {
buildInt32Count(-80, 2),
buildInt32Count(-78, 1),
};
assertKeyCountsEqual(expectedFailureRssiHistogram,
linkProbeStats.failureRssiCounts);
Int32Count[] expectedSuccessLinkSpeedHistogram = {
buildInt32Count(50, 1),
buildInt32Count(160, 2)
};
assertKeyCountsEqual(expectedSuccessLinkSpeedHistogram,
linkProbeStats.successLinkSpeedCounts);
Int32Count[] expectedFailureLinkSpeedHistogram = {
buildInt32Count(6, 2),
buildInt32Count(10, 1)
};
assertKeyCountsEqual(expectedFailureLinkSpeedHistogram,
linkProbeStats.failureLinkSpeedCounts);
HistogramBucketInt32[] expectedSuccessTimeSinceLastTxSuccessSecondsHistogram = {
buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1),
buildHistogramBucketInt32(5, 15, 2)
};
assertHistogramBucketsEqual(expectedSuccessTimeSinceLastTxSuccessSecondsHistogram,
linkProbeStats.successSecondsSinceLastTxSuccessHistogram);
HistogramBucketInt32[] expectedFailureTimeSinceLastTxSuccessSecondsHistogram = {
buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1),
buildHistogramBucketInt32(15, 45, 2)
};
assertHistogramBucketsEqual(expectedFailureTimeSinceLastTxSuccessSecondsHistogram,
linkProbeStats.failureSecondsSinceLastTxSuccessHistogram);
HistogramBucketInt32[] expectedSuccessElapsedTimeMsHistogram = {
buildHistogramBucketInt32(5, 10, 1),
buildHistogramBucketInt32(10, 15, 2),
};
assertHistogramBucketsEqual(expectedSuccessElapsedTimeMsHistogram,
linkProbeStats.successElapsedTimeMsHistogram);
LinkProbeFailureReasonCount[] expectedFailureReasonCount = {
buildLinkProbeFailureReasonCount(
LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK, 2),
buildLinkProbeFailureReasonCount(
LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT, 1),
};
assertLinkProbeFailureReasonCountsEqual(expectedFailureReasonCount,
linkProbeStats.failureReasonCounts);
}
/**
* Tests counting the number of link probes triggered per day for each experiment.
*/
@Test
public void testIncrementLinkProbeExperimentProbeCount() throws Exception {
String experimentId1 = "screenOnDelay=6000,noTxDelay=3000,delayBetweenProbes=9000,"
+ "rssiThreshold=-70,linkSpeedThreshold=15,";
mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId1);
String experimentId2 = "screenOnDelay=9000,noTxDelay=12000,delayBetweenProbes=15000,"
+ "rssiThreshold=-72,linkSpeedThreshold=20,";
mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2);
mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2);
dumpProtoAndDeserialize();
ExperimentProbeCounts[] actual = mDecodedProto.linkProbeStats.experimentProbeCounts;
ExperimentProbeCounts[] expected = {
buildExperimentProbeCounts(experimentId1, 1),
buildExperimentProbeCounts(experimentId2, 2)
};
assertExperimentProbeCountsEqual(expected, actual);
}
/**
* Tests logNetworkSelectionDecision()
*/
@Test
public void testLogNetworkSelectionDecision() throws Exception {
mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6);
mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 1);
mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6);
mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 2);
mWifiMetrics.logNetworkSelectionDecision(3, 2, false, 15);
mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 6);
mWifiMetrics.logNetworkSelectionDecision(1, 4, true, 2);
dumpProtoAndDeserialize();
assertEquals(3, mDecodedProto.networkSelectionExperimentDecisionsList.length);
NetworkSelectionExperimentDecisions exp12 =
findUniqueNetworkSelectionExperimentDecisions(1, 2);
Int32Count[] exp12SameExpected = {
buildInt32Count(2, 1),
buildInt32Count(6, 2)
};
assertKeyCountsEqual(exp12SameExpected, exp12.sameSelectionNumChoicesCounter);
Int32Count[] exp12DiffExpected = {
buildInt32Count(1, 1),
buildInt32Count(6, 1)
};
assertKeyCountsEqual(exp12DiffExpected, exp12.differentSelectionNumChoicesCounter);
NetworkSelectionExperimentDecisions exp32 =
findUniqueNetworkSelectionExperimentDecisions(3, 2);
Int32Count[] exp32SameExpected = {};
assertKeyCountsEqual(exp32SameExpected, exp32.sameSelectionNumChoicesCounter);
Int32Count[] exp32DiffExpected = {
buildInt32Count(
WifiMetrics.NetworkSelectionExperimentResults.MAX_CHOICES, 1)
};
assertKeyCountsEqual(exp32DiffExpected, exp32.differentSelectionNumChoicesCounter);
NetworkSelectionExperimentDecisions exp14 =
findUniqueNetworkSelectionExperimentDecisions(1, 4);
Int32Count[] exp14SameExpected = {
buildInt32Count(2, 1)
};
assertKeyCountsEqual(exp14SameExpected, exp14.sameSelectionNumChoicesCounter);
Int32Count[] exp14DiffExpected = {};
assertKeyCountsEqual(exp14DiffExpected, exp14.differentSelectionNumChoicesCounter);
}
/**
* Test the generation of 'WifiNetworkRequestApiLog' message.
*/
@Test
public void testWifiNetworkRequestApiLog() throws Exception {
mWifiMetrics.incrementNetworkRequestApiNumRequest();
mWifiMetrics.incrementNetworkRequestApiNumRequest();
mWifiMetrics.incrementNetworkRequestApiNumRequest();
mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(7);
mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(0);
mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(1);
mWifiMetrics.incrementNetworkRequestApiNumConnectSuccess();
mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass();
mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass();
mWifiMetrics.incrementNetworkRequestApiNumUserReject();
mWifiMetrics.incrementNetworkRequestApiNumApps();
dumpProtoAndDeserialize();
assertEquals(3, mDecodedProto.wifiNetworkRequestApiLog.numRequest);
assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numConnectSuccess);
assertEquals(2, mDecodedProto.wifiNetworkRequestApiLog.numUserApprovalBypass);
assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numUserReject);
assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numApps);
HistogramBucketInt32[] expectedNetworkMatchSizeHistogram = {
buildHistogramBucketInt32(0, 1, 1),
buildHistogramBucketInt32(1, 5, 1),
buildHistogramBucketInt32(5, 10, 1)
};
assertHistogramBucketsEqual(expectedNetworkMatchSizeHistogram,
mDecodedProto.wifiNetworkRequestApiLog.networkMatchSizeHistogram);
}
/**
* Test the generation of 'WifiNetworkSuggestionApiLog' message.
*/
@Test
public void testWifiNetworkSuggestionApiLog() throws Exception {
mWifiMetrics.incrementNetworkSuggestionApiNumModification();
mWifiMetrics.incrementNetworkSuggestionApiNumModification();
mWifiMetrics.incrementNetworkSuggestionApiNumModification();
mWifiMetrics.incrementNetworkSuggestionApiNumModification();
mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess();
mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess();
mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure();
mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED);
mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED);
mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED);
mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED);
mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED);
mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING);
mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{
add(5);
add(100);
add(50);
add(120);
}});
// Second update should overwrite the prevous write.
mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{
add(7);
add(110);
add(40);
add(60);
}});
mWifiMetrics.incrementNetworkSuggestionUserRevokePermission();
mWifiMetrics.incrementNetworkSuggestionUserRevokePermission();
dumpProtoAndDeserialize();
assertEquals(4, mDecodedProto.wifiNetworkSuggestionApiLog.numModification);
assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectSuccess);
assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectFailure);
HistogramBucketInt32[] expectedNetworkListSizeHistogram = {
buildHistogramBucketInt32(5, 20, 1),
buildHistogramBucketInt32(20, 50, 1),
buildHistogramBucketInt32(50, 100, 1),
buildHistogramBucketInt32(100, 500, 1),
};
assertHistogramBucketsEqual(expectedNetworkListSizeHistogram,
mDecodedProto.wifiNetworkSuggestionApiLog.networkListSizeHistogram);
assertEquals(3, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType.length);
assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_CARRIER_PRIVILEGED,
mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[0].appType);
assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[0].count);
assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_NETWORK_PROVISIONING,
mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[1].appType);
assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[1].count);
assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_NON_PRIVILEGED,
mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[2].appType);
assertEquals(3, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[2].count);
}
/**
* Test the generation of 'UserReactionToApprovalUiEvent' message.
*/
@Test
public void testUserReactionToApprovalUiEvent() throws Exception {
mWifiMetrics.addUserApprovalSuggestionAppUiReaction(1, true);
mWifiMetrics.addUserApprovalSuggestionAppUiReaction(2, false);
mWifiMetrics.addUserApprovalCarrierUiReaction(
WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true);
mWifiMetrics.addUserApprovalCarrierUiReaction(
WifiCarrierInfoManager.ACTION_USER_DISMISS, false);
mWifiMetrics.addUserApprovalCarrierUiReaction(
WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER, false);
dumpProtoAndDeserialize();
assertEquals(2,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction.length);
assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_ALLOWED,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[0]
.userAction);
assertEquals(true,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[0]
.isDialog);
assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISALLOWED,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[1]
.userAction);
assertEquals(false,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[1]
.isDialog);
assertEquals(3,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction.length);
assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_ALLOWED,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[0]
.userAction);
assertEquals(true,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[0]
.isDialog);
assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISMISS,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[1]
.userAction);
assertEquals(false,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[1]
.isDialog);
assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISALLOWED,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[2]
.userAction);
assertEquals(false,
mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[2]
.isDialog);
}
private NetworkSelectionExperimentDecisions findUniqueNetworkSelectionExperimentDecisions(
int experiment1Id, int experiment2Id) {
NetworkSelectionExperimentDecisions result = null;
for (NetworkSelectionExperimentDecisions d
: mDecodedProto.networkSelectionExperimentDecisionsList) {
if (d.experiment1Id == experiment1Id && d.experiment2Id == experiment2Id) {
assertNull("duplicate found!", result);
result = d;
}
}
assertNotNull("not found!", result);
return result;
}
/**
* Verify that the label and the triggerType of Wifi usability stats are saved correctly
* during IP reachability lost message is received.
* @throws Exception
*/
@Test
public void verifyIpReachabilityLostUpdatesWifiUsabilityMetrics() throws Exception {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
long eventTimeMs = nextRandInt();
when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
// Add 1 LABEL_GOOD
WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
// IP reachability lost occurs
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
assertEquals(WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, statsList[1].triggerType);
assertEquals(eventTimeMs, statsList[1].timeStampMs);
}
/**
* Test the WifiLock active session statistics
*/
@Test
public void testWifiLockActiveSession() throws Exception {
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000);
mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000);
dumpProtoAndDeserialize();
assertEquals(10111000, mDecodedProto.wifiLockStats.highPerfActiveTimeMs);
assertEquals(20999000, mDecodedProto.wifiLockStats.lowLatencyActiveTimeMs);
HistogramBucketInt32[] expectedHighPerfHistogram = {
buildHistogramBucketInt32(1, 10, 1),
buildHistogramBucketInt32(10, 60, 1),
buildHistogramBucketInt32(60, 600, 1),
buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
};
HistogramBucketInt32[] expectedLowLatencyHistogram = {
buildHistogramBucketInt32(1, 10, 1),
buildHistogramBucketInt32(60, 600, 1),
buildHistogramBucketInt32(600, 3600, 1),
buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
};
assertHistogramBucketsEqual(expectedHighPerfHistogram,
mDecodedProto.wifiLockStats.highPerfActiveSessionDurationSecHistogram);
assertHistogramBucketsEqual(expectedLowLatencyHistogram,
mDecodedProto.wifiLockStats.lowLatencyActiveSessionDurationSecHistogram);
}
/**
* Test the WifiLock acquisition session statistics
*/
@Test
public void testWifiLockAcqSession() throws Exception {
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000);
mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000);
dumpProtoAndDeserialize();
HistogramBucketInt32[] expectedHighPerfHistogram = {
buildHistogramBucketInt32(1, 10, 1),
buildHistogramBucketInt32(10, 60, 1),
buildHistogramBucketInt32(60, 600, 1),
buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
};
HistogramBucketInt32[] expectedLowLatencyHistogram = {
buildHistogramBucketInt32(1, 10, 1),
buildHistogramBucketInt32(60, 600, 1),
buildHistogramBucketInt32(600, 3600, 1),
buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
};
assertHistogramBucketsEqual(expectedHighPerfHistogram,
mDecodedProto.wifiLockStats.highPerfLockAcqDurationSecHistogram);
assertHistogramBucketsEqual(expectedLowLatencyHistogram,
mDecodedProto.wifiLockStats.lowLatencyLockAcqDurationSecHistogram);
}
/**
* Verify that LABEL_GOOD stats are generated if Wifi score breaches low and there
* is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
*/
@Test
public void testGoodStatsAreGeneratedByWifiScoreBreachLow() throws Exception {
// The elapsed time falls into the interval for adding good stats
createTestForDataCollectionByScoreBreach(
WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
false, true);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
* time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
*/
@Test
public void testGoodStatsAreNotGeneratedByWifiScoreBreachLow() throws Exception {
// The elapsed time is shorter than necessary to add good stats
createTestForDataCollectionByScoreBreach(
WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1,
false, true);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
* time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS
* @throws Exception
*/
@Test
public void testGoodStatsAreNotGeneratedIfWifiScoreBreachExpires() throws Exception {
// The Wifi score breaching expires for adding good stats
createTestForDataCollectionByScoreBreach(
WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1,
false, true);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and there is
* WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
*/
@Test
public void testGoodStatsAreNotGeneratedIfBadEventOccured() throws Exception {
// The elapsed time falls into the interval for adding good stats and bad event occurs
createTestForDataCollectionByScoreBreach(
WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
true, true);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are generated if Wifi usability score breaches low and there
* is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
*/
@Test
public void testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
// The elapsed time falls into the interval for adding good stats
createTestForDataCollectionByScoreBreach(
WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
false, false);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
* the checking time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
*/
@Test
public void testGoodStatsAreNotGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
// The elapsed time is shorter than necessary to add good stats
createTestForDataCollectionByScoreBreach(
WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1,
false, false);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
* the checking time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS
* @throws Exception
*/
@Test
public void testGoodStatsAreNotGeneratedIfWifiUsabilityScoreBreachExpires() throws Exception {
// The Wifi usability score breaching expires for adding good stats
createTestForDataCollectionByScoreBreach(
WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1,
false, false);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and there
* is WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
*/
@Test
public void testGoodStatsAreNotGeneratedIfBadEventOccuredForUsabilityScore() throws Exception {
// The elapsed time falls into the interval for adding good stats and bad event occurs
createTestForDataCollectionByScoreBreach(
WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
true, false);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Verify that incrementNumWifiToggles increments the corrects fields based on input.
*/
@Test
public void testIncrementNumWifiToggles() throws Exception {
mWifiMetrics.incrementNumWifiToggles(true, true);
for (int i = 0; i < 2; i++) {
mWifiMetrics.incrementNumWifiToggles(true, false);
}
for (int i = 0; i < 3; i++) {
mWifiMetrics.incrementNumWifiToggles(false, true);
}
for (int i = 0; i < 4; i++) {
mWifiMetrics.incrementNumWifiToggles(false, false);
}
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.wifiToggleStats.numToggleOnPrivileged);
assertEquals(2, mDecodedProto.wifiToggleStats.numToggleOffPrivileged);
assertEquals(3, mDecodedProto.wifiToggleStats.numToggleOnNormal);
assertEquals(4, mDecodedProto.wifiToggleStats.numToggleOffNormal);
}
/**
* Verify metered stats are counted properly for saved and ephemeral networks.
*/
@Test
public void testMeteredNetworkMetrics() throws Exception {
// Test without metered override
WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork();
WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork();
config.fromWifiNetworkSuggestion = false;
config1.fromWifiNetworkSuggestion = true;
mWifiMetrics.addMeteredStat(config, false);
mWifiMetrics.addMeteredStat(config1, true);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numMetered);
assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
assertEquals(1, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
// Test with metered override
config = WifiConfigurationTestUtil.createPskNetwork();
config1 = WifiConfigurationTestUtil.createPskNetwork();
config.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
config1.meteredOverride = WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
mWifiMetrics.addMeteredStat(config, true);
mWifiMetrics.addMeteredStat(config1, true);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered);
assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
}
/**
* Verify that the same network does not get counted twice
*/
@Test
public void testMeteredNetworkMetricsNoDoubleCount() throws Exception {
WifiConfiguration config = new WifiConfiguration();
config.ephemeral = false;
mWifiMetrics.addMeteredStat(config, false);
mWifiMetrics.addMeteredStat(config, true);
mWifiMetrics.addMeteredStat(config, true);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
}
/**
* Create a test to verify data collection logic triggered by score breaching low
* @param elapsedTimeAfterBreach The elapsed time after score breaches low
* @param isThereBadEvent Whether there is a bad event happened after score breaches low
* @param isWifiScore Whether it is Wifi score or not that breaches the threshold
*/
private void createTestForDataCollectionByScoreBreach(
long elapsedTimeAfterBreach, boolean isThereBadEvent, boolean isWifiScore) {
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
addOneBadWifiUsabilityStats(info);
if (isWifiScore) {
stats2 = wifiScoreBreachesLow(info, stats2);
} else {
stats2 = wifiUsabilityScoreBreachesLow(info, stats2);
}
if (isThereBadEvent) {
mWifiMetrics.logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
}
when(mClock.getElapsedSinceBootMillis()).thenReturn(elapsedTimeAfterBreach);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
}
// Simulate adding one LABEL_BAD WifiUsabilityStats
private void addOneBadWifiUsabilityStats(WifiInfo info) {
WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
}
// Simulate that Wifi score breaches low
private WifiLinkLayerStats wifiScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2) {
int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
mWifiMetrics.incrementWifiScoreCount(upper);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
stats2 = nextRandomStats(stats2);
long timeMs = 0;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
// Wifi score breaches low
mWifiMetrics.incrementWifiScoreCount(lower);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
stats2 = nextRandomStats(stats2);
return stats2;
}
// Simulate that Wifi usability score breaches low
private WifiLinkLayerStats wifiUsabilityScoreBreachesLow(WifiInfo info,
WifiLinkLayerStats stats2) {
int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
mWifiMetrics.incrementWifiUsabilityScoreCount(1, upper, 30);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
stats2 = nextRandomStats(stats2);
long timeMs = 0;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
// Wifi usability score breaches low
mWifiMetrics.incrementWifiUsabilityScoreCount(2, lower, 30);
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
stats2 = nextRandomStats(stats2);
return stats2;
}
/**
* Verify the counts of passpoint profile type are correct.
* @param profileTypes type and count of installed passpoint profiles
*/
private void assertPasspointProfileTypeCount(PasspointProfileTypeCount[] profileTypes) {
for (PasspointProfileTypeCount passpointProfileType : profileTypes) {
switch(passpointProfileType.eapMethodType) {
case PasspointProfileTypeCount.TYPE_EAP_AKA:
assertEquals(NUM_EAP_AKA_TYPE, passpointProfileType.count);
break;
case PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME:
assertEquals(NUM_EAP_AKA_PRIME_TYPE, passpointProfileType.count);
break;
case PasspointProfileTypeCount.TYPE_EAP_SIM:
assertEquals(NUM_EAP_SIM_TYPE, passpointProfileType.count);
break;
case PasspointProfileTypeCount.TYPE_EAP_TLS:
assertEquals(NUM_EAP_TLS_TYPE, passpointProfileType.count);
break;
case PasspointProfileTypeCount.TYPE_EAP_TTLS:
assertEquals(NUM_EAP_TTLS_TYPE, passpointProfileType.count);
break;
default:
fail("unknown type counted");
}
}
}
/**
* Verify that the LABEL_BAD Wifi usability stats are not saved if screen state is off.
* @throws Exception
*/
@Test
public void verifyLabelBadStatsAreNotSavedIfScreenIsOff() throws Exception {
mWifiMetrics.setScreenState(false);
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
// Add 1 LABEL_GOOD
WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
// IP reachability lost occurs
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
// Wifi data stall occurs
mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
// Firmware alert occurs
mWifiMetrics.logFirmwareAlert(2);
dumpProtoAndDeserialize();
assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
}
/**
* Test the logging of connection duration stats
*/
@Test
public void testConnectionDurationStats() throws Exception {
for (int i = 0; i < 2; i++) {
mWifiMetrics.incrementConnectionDuration(5000, false, true);
mWifiMetrics.incrementConnectionDuration(3000, true, true);
mWifiMetrics.incrementConnectionDuration(1000, false, false);
mWifiMetrics.incrementConnectionDuration(500, true, false);
}
dumpProtoAndDeserialize();
assertEquals(6000,
mDecodedProto.connectionDurationStats.totalTimeSufficientThroughputMs);
assertEquals(10000,
mDecodedProto.connectionDurationStats.totalTimeInsufficientThroughputMs);
assertEquals(3000,
mDecodedProto.connectionDurationStats.totalTimeCellularDataOffMs);
}
/**
* Test the logging of isExternalWifiScorerOn
*/
@Test
public void testIsExternalWifiScorerOn() throws Exception {
mWifiMetrics.setIsExternalWifiScorerOn(true);
dumpProtoAndDeserialize();
assertEquals(true, mDecodedProto.isExternalWifiScorerOn);
}
/*
* Test the logging of Wi-Fi off
*/
@Test
public void testWifiOff() throws Exception {
// if not deferred, timeout and duration should be ignored.
mWifiMetrics.noteWifiOff(false, false, 0);
mWifiMetrics.noteWifiOff(false, true, 999);
// deferred, not timed out
mWifiMetrics.noteWifiOff(true, false, 0);
mWifiMetrics.noteWifiOff(true, false, 1000);
// deferred and timed out
mWifiMetrics.noteWifiOff(true, true, 2000);
mWifiMetrics.noteWifiOff(true, true, 2000);
mWifiMetrics.noteWifiOff(true, true, 4000);
dumpProtoAndDeserialize();
assertEquals(7,
mDecodedProto.wifiOffMetrics.numWifiOff);
assertEquals(5,
mDecodedProto.wifiOffMetrics.numWifiOffDeferring);
assertEquals(3,
mDecodedProto.wifiOffMetrics.numWifiOffDeferringTimeout);
Int32Count[] expectedHistogram = {
buildInt32Count(0, 1),
buildInt32Count(1000, 1),
buildInt32Count(2000, 2),
buildInt32Count(4000, 1),
};
assertKeyCountsEqual(expectedHistogram,
mDecodedProto.wifiOffMetrics.wifiOffDeferringTimeHistogram);
}
/*
* Test the logging of Wi-Fi off
*/
@Test
public void testSoftApConfigLimitationMetrics() throws Exception {
SoftApConfiguration originalConfig = new SoftApConfiguration.Builder()
.setSsid("TestSSID").build();
SoftApConfiguration needToResetCongig = new SoftApConfiguration.Builder(originalConfig)
.setPassphrase("TestPassphreas", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)
.setClientControlByUserEnabled(true)
.setMaxNumberOfClients(10)
.build();
mWifiMetrics.noteSoftApConfigReset(originalConfig, needToResetCongig);
mWifiMetrics.noteSoftApClientBlocked(5);
mWifiMetrics.noteSoftApClientBlocked(5);
mWifiMetrics.noteSoftApClientBlocked(5);
mWifiMetrics.noteSoftApClientBlocked(8);
dumpProtoAndDeserialize();
assertEquals(1,
mDecodedProto.softApConfigLimitationMetrics.numSecurityTypeResetToDefault);
assertEquals(1,
mDecodedProto.softApConfigLimitationMetrics.numMaxClientSettingResetToDefault);
assertEquals(1,
mDecodedProto.softApConfigLimitationMetrics.numClientControlByUserResetToDefault);
Int32Count[] expectedHistogram = {
buildInt32Count(5, 3),
buildInt32Count(8, 1),
};
assertKeyCountsEqual(expectedHistogram,
mDecodedProto.softApConfigLimitationMetrics.maxClientSettingWhenReachHistogram);
}
/**
* Test the logging of channel utilization
*/
@Test
public void testChannelUtilization() throws Exception {
mWifiMetrics.incrementChannelUtilizationCount(180, 2412);
mWifiMetrics.incrementChannelUtilizationCount(150, 2412);
mWifiMetrics.incrementChannelUtilizationCount(230, 2412);
mWifiMetrics.incrementChannelUtilizationCount(20, 5510);
mWifiMetrics.incrementChannelUtilizationCount(50, 5510);
dumpProtoAndDeserialize();
HistogramBucketInt32[] expected2GHistogram = {
buildHistogramBucketInt32(150, 175, 1),
buildHistogramBucketInt32(175, 200, 1),
buildHistogramBucketInt32(225, Integer.MAX_VALUE, 1),
};
HistogramBucketInt32[] expectedAbove2GHistogram = {
buildHistogramBucketInt32(Integer.MIN_VALUE, 25, 1),
buildHistogramBucketInt32(50, 75, 1),
};
assertHistogramBucketsEqual(expected2GHistogram,
mDecodedProto.channelUtilizationHistogram.utilization2G);
assertHistogramBucketsEqual(expectedAbove2GHistogram,
mDecodedProto.channelUtilizationHistogram.utilizationAbove2G);
}
/**
* Test the logging of Tx and Rx throughput
*/
@Test
public void testThroughput() throws Exception {
mWifiMetrics.incrementThroughputKbpsCount(500, 800, 2412);
mWifiMetrics.incrementThroughputKbpsCount(5_000, 4_000, 2412);
mWifiMetrics.incrementThroughputKbpsCount(54_000, 48_000, 2412);
mWifiMetrics.incrementThroughputKbpsCount(50_000, 49_000, 5510);
mWifiMetrics.incrementThroughputKbpsCount(801_000, 790_000, 5510);
mWifiMetrics.incrementThroughputKbpsCount(1100_000, 1200_000, 5510);
mWifiMetrics.incrementThroughputKbpsCount(1599_000, 1800_000, 6120);
dumpProtoAndDeserialize();
HistogramBucketInt32[] expectedTx2GHistogramMbps = {
buildHistogramBucketInt32(Integer.MIN_VALUE, 1, 1),
buildHistogramBucketInt32(5, 10, 1),
buildHistogramBucketInt32(50, 100, 1),
};
HistogramBucketInt32[] expectedRx2GHistogramMbps = {
buildHistogramBucketInt32(Integer.MIN_VALUE, 1, 1),
buildHistogramBucketInt32(1, 5, 1),
buildHistogramBucketInt32(25, 50, 1),
};
HistogramBucketInt32[] expectedTxAbove2GHistogramMbps = {
buildHistogramBucketInt32(50, 100, 1),
buildHistogramBucketInt32(800, 1200, 2),
buildHistogramBucketInt32(1200, 1600, 1),
};
HistogramBucketInt32[] expectedRxAbove2GHistogramMbps = {
buildHistogramBucketInt32(25, 50, 1),
buildHistogramBucketInt32(600, 800, 1),
buildHistogramBucketInt32(1200, 1600, 1),
buildHistogramBucketInt32(1600, Integer.MAX_VALUE, 1),
};
assertHistogramBucketsEqual(expectedTx2GHistogramMbps,
mDecodedProto.throughputMbpsHistogram.tx2G);
assertHistogramBucketsEqual(expectedTxAbove2GHistogramMbps,
mDecodedProto.throughputMbpsHistogram.txAbove2G);
assertHistogramBucketsEqual(expectedRx2GHistogramMbps,
mDecodedProto.throughputMbpsHistogram.rx2G);
assertHistogramBucketsEqual(expectedRxAbove2GHistogramMbps,
mDecodedProto.throughputMbpsHistogram.rxAbove2G);
}
/**
* Test the Initial partial scan statistics
*/
@Test
public void testInitPartialScan() throws Exception {
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(4, true);
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(2, false);
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(1, false);
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(7, true);
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(15, false);
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(2, true);
mWifiMetrics.incrementInitialPartialScanCount();
mWifiMetrics.reportInitialPartialScan(10, true);
dumpProtoAndDeserialize();
assertEquals(9, mDecodedProto.initPartialScanStats.numScans);
assertEquals(4, mDecodedProto.initPartialScanStats.numSuccessScans);
assertEquals(3, mDecodedProto.initPartialScanStats.numFailureScans);
HistogramBucketInt32[] expectedSuccessScanHistogram = {
buildHistogramBucketInt32(1, 3, 1),
buildHistogramBucketInt32(3, 5, 1),
buildHistogramBucketInt32(5, 10, 1),
buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1),
};
HistogramBucketInt32[] expectedFailureScanHistogram = {
buildHistogramBucketInt32(1, 3, 2),
buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1),
};
assertHistogramBucketsEqual(expectedSuccessScanHistogram,
mDecodedProto.initPartialScanStats.successfulScanChannelCountHistogram);
assertHistogramBucketsEqual(expectedFailureScanHistogram,
mDecodedProto.initPartialScanStats.failedScanChannelCountHistogram);
}
/**
* Test overlapping and non-overlapping connection events return overlapping duration correctly
*/
@Test
public void testOverlappingConnectionEvent() throws Exception {
// Connection event 1
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 1000);
// Connection event 2 overlaps with 1
assertEquals(1000, mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE));
// Connection event 2 ends
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 2000);
// Connection event 3 doesn't overlap with 2
assertEquals(0, mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE));
}
@Test
public void testCarrierWifiConnectionEvent() throws Exception {
mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess();
for (int i = 0; i < 2; i++) {
mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure();
}
for (int i = 0; i < 3; i++) {
mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure();
}
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.carrierWifiMetrics.numConnectionSuccess);
assertEquals(2, mDecodedProto.carrierWifiMetrics.numConnectionAuthFailure);
assertEquals(3, mDecodedProto.carrierWifiMetrics.numConnectionNonAuthFailure);
}
/**
* Verify the ConnectionEvent is labeled with networkType Passpoint correctly and that the OSU
* provisioned flag is set to true.
*/
@Test
public void testConnectionNetworkTypePasspointFromOsu() throws Exception {
WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
config.updateIdentifier = "7";
mWifiMetrics.startConnectionEvent(config, "RED",
WifiMetricsProto.ConnectionEvent.ROAM_NONE);
mWifiMetrics.endConnectionEvent(
WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
dumpProtoAndDeserialize();
assertEquals(1, mDecodedProto.connectionEvent.length);
assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT,
mDecodedProto.connectionEvent[0].networkType);
assertTrue(mDecodedProto.connectionEvent[0].isOsuProvisioned);
}
}