blob: d25a50a10cc706ee3111f46680d6c2c047b42f56 [file] [log] [blame]
/*
* Copyright (C) 2019 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 com.android.server.wifi.util.InformationElementUtil.BssLoad.CHANNEL_UTILIZATION_SCALE;
import android.content.Context;
import android.os.Handler;
import android.provider.DeviceConfig;
import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* This class allows getting all configurable flags from DeviceConfig.
*/
public class DeviceConfigFacade {
private Context mContext;
private final WifiMetrics mWifiMetrics;
private static final String NAMESPACE = "wifi";
// Default values of fields
@VisibleForTesting
protected static final int DEFAULT_ABNORMAL_CONNECTION_DURATION_MS =
(int) TimeUnit.SECONDS.toMillis(30);
// Default duration for evaluating Wifi condition to trigger a data stall
// measured in milliseconds
public static final int DEFAULT_DATA_STALL_DURATION_MS = 1500;
// Default threshold of Tx throughput below which to trigger a data stall measured in Kbps
public static final int DEFAULT_DATA_STALL_TX_TPUT_THR_KBPS = 2000;
// Default threshold of Rx throughput below which to trigger a data stall measured in Kbps
public static final int DEFAULT_DATA_STALL_RX_TPUT_THR_KBPS = 2000;
// Default threshold of Tx packet error rate above which to trigger a data stall in percentage
public static final int DEFAULT_DATA_STALL_TX_PER_THR = 90;
// Default threshold of CCA level above which to trigger a data stall
public static final int DEFAULT_DATA_STALL_CCA_LEVEL_THR = CHANNEL_UTILIZATION_SCALE;
// Default low threshold of L2 sufficient throughput in Kbps
public static final int DEFAULT_TPUT_SUFFICIENT_THR_LOW_KBPS = 1000;
// Default high threshold of L2 sufficient throughput in Kbps
public static final int DEFAULT_TPUT_SUFFICIENT_THR_HIGH_KBPS = 4000;
// Numerator part of default threshold of L2 throughput over L3 throughput ratio
public static final int DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM = 2;
// Denominator part of default threshold of L2 throughput over L3 throughput ratio
public static final int DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN = 1;
// Default threshold of Tx packet per second
public static final int DEFAULT_TX_PACKET_PER_SECOND_THR = 1;
// Default threshold of Rx packet per second
public static final int DEFAULT_RX_PACKET_PER_SECOND_THR = 1;
// Default high threshold values for various connection/disconnection cases
// All of them are in percent with respect to connection attempts
static final int DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT = 40;
static final int DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT = 30;
static final int DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT = 30;
static final int DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT = 30;
static final int DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT = 20;
static final int DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT = 25;
// Default health monitor abnormal count minimum for various cases
static final int DEFAULT_CONNECTION_FAILURE_COUNT_MIN = 6;
static final int DEFAULT_ASSOC_REJECTION_COUNT_MIN = 3;
static final int DEFAULT_ASSOC_TIMEOUT_COUNT_MIN = 3;
static final int DEFAULT_AUTH_FAILURE_COUNT_MIN = 3;
static final int DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN = 3;
static final int DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN = 3;
// Numerator part of default ratio threshold values for all cases
static final int DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR = 4;
// Denominator part of ratio threshold for all cases
static final int HEALTH_MONITOR_RATIO_THR_DENOMINATOR = 2;
// Minimum RSSI in dBm for connection stats collection
// Connection or disconnection events with RSSI below this threshold are not
// included in connection stats collection.
static final int DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM = -68;
// Default minimum number of connection attempts to qualify daily detection
static final int DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT = 10;
// Default minimum wait time between two bug report captures
static final int DEFAULT_BUG_REPORT_MIN_WINDOW_MS = 3_600_000;
// Default report-high threshold to take-bug-report threshold ratio.
// It should be larger than 1 since the bar to take bugreport should be higher.
static final int DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO = 2;
// Default overlapping connection duration threshold in ms to trigger bug report
static final int DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS = 75_000;
// Cached values of fields updated via updateDeviceConfigFlags()
private boolean mIsAbnormalConnectionBugreportEnabled;
private int mAbnormalConnectionDurationMs;
private int mDataStallDurationMs;
private int mDataStallTxTputThrKbps;
private int mDataStallRxTputThrKbps;
private int mDataStallTxPerThr;
private int mDataStallCcaLevelThr;
private int mTputSufficientLowThrKbps;
private int mTputSufficientHighThrKbps;
private int mTputSufficientRatioThrNum;
private int mTputSufficientRatioThrDen;
private int mTxPktPerSecondThr;
private int mRxPktPerSecondThr;
private int mConnectionFailureHighThrPercent;
private int mConnectionFailureCountMin;
private int mAssocRejectionHighThrPercent;
private int mAssocRejectionCountMin;
private int mAssocTimeoutHighThrPercent;
private int mAssocTimeoutCountMin;
private int mAuthFailureHighThrPercent;
private int mAuthFailureCountMin;
private int mShortConnectionNonlocalHighThrPercent;
private int mShortConnectionNonlocalCountMin;
private int mDisconnectionNonlocalHighThrPercent;
private int mDisconnectionNonlocalCountMin;
private int mHealthMonitorRatioThrNumerator;
private int mHealthMonitorMinRssiThrDbm;
private Set<String> mRandomizationFlakySsidHotlist;
private Set<String> mAggressiveMacRandomizationSsidAllowlist;
private Set<String> mAggressiveMacRandomizationSsidBlocklist;
private boolean mIsAbnormalConnectionFailureBugreportEnabled;
private boolean mIsAbnormalDisconnectionBugreportEnabled;
private int mHealthMonitorMinNumConnectionAttempt;
private int mBugReportMinWindowMs;
private int mBugReportThresholdExtraRatio;
private boolean mIsOverlappingConnectionBugreportEnabled;
private int mOverlappingConnectionDurationThresholdMs;
public DeviceConfigFacade(Context context, Handler handler, WifiMetrics wifiMetrics) {
mContext = context;
mWifiMetrics = wifiMetrics;
updateDeviceConfigFlags();
DeviceConfig.addOnPropertiesChangedListener(
NAMESPACE,
command -> handler.post(command),
properties -> {
updateDeviceConfigFlags();
});
}
private void updateDeviceConfigFlags() {
mIsAbnormalConnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
"abnormal_connection_bugreport_enabled", false);
mAbnormalConnectionDurationMs = DeviceConfig.getInt(NAMESPACE,
"abnormal_connection_duration_ms",
DEFAULT_ABNORMAL_CONNECTION_DURATION_MS);
mDataStallDurationMs = DeviceConfig.getInt(NAMESPACE,
"data_stall_duration_ms", DEFAULT_DATA_STALL_DURATION_MS);
mDataStallTxTputThrKbps = DeviceConfig.getInt(NAMESPACE,
"data_stall_tx_tput_thr_kbps", DEFAULT_DATA_STALL_TX_TPUT_THR_KBPS);
mDataStallRxTputThrKbps = DeviceConfig.getInt(NAMESPACE,
"data_stall_rx_tput_thr_kbps", DEFAULT_DATA_STALL_RX_TPUT_THR_KBPS);
mDataStallTxPerThr = DeviceConfig.getInt(NAMESPACE,
"data_stall_tx_per_thr", DEFAULT_DATA_STALL_TX_PER_THR);
mDataStallCcaLevelThr = DeviceConfig.getInt(NAMESPACE,
"data_stall_cca_level_thr", DEFAULT_DATA_STALL_CCA_LEVEL_THR);
mWifiMetrics.setDataStallDurationMs(mDataStallDurationMs);
mWifiMetrics.setDataStallTxTputThrKbps(mDataStallTxTputThrKbps);
mWifiMetrics.setDataStallRxTputThrKbps(mDataStallRxTputThrKbps);
mWifiMetrics.setDataStallTxPerThr(mDataStallTxPerThr);
mWifiMetrics.setDataStallCcaLevelThr(mDataStallCcaLevelThr);
mTputSufficientLowThrKbps = DeviceConfig.getInt(NAMESPACE,
"tput_sufficient_low_thr_kbps", DEFAULT_TPUT_SUFFICIENT_THR_LOW_KBPS);
mTputSufficientHighThrKbps = DeviceConfig.getInt(NAMESPACE,
"tput_sufficient_high_thr_kbps", DEFAULT_TPUT_SUFFICIENT_THR_HIGH_KBPS);
mTputSufficientRatioThrNum = DeviceConfig.getInt(NAMESPACE,
"tput_sufficient_ratio_thr_num", DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM);
mTputSufficientRatioThrDen = DeviceConfig.getInt(NAMESPACE,
"tput_sufficient_ratio_thr_den", DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN);
mTxPktPerSecondThr = DeviceConfig.getInt(NAMESPACE,
"tx_pkt_per_second_thr", DEFAULT_TX_PACKET_PER_SECOND_THR);
mRxPktPerSecondThr = DeviceConfig.getInt(NAMESPACE,
"rx_pkt_per_second_thr", DEFAULT_RX_PACKET_PER_SECOND_THR);
mConnectionFailureHighThrPercent = DeviceConfig.getInt(NAMESPACE,
"connection_failure_high_thr_percent",
DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT);
mConnectionFailureCountMin = DeviceConfig.getInt(NAMESPACE,
"connection_failure_count_min",
DEFAULT_CONNECTION_FAILURE_COUNT_MIN);
mAssocRejectionHighThrPercent = DeviceConfig.getInt(NAMESPACE,
"assoc_rejection_high_thr_percent",
DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT);
mAssocRejectionCountMin = DeviceConfig.getInt(NAMESPACE,
"assoc_rejection_count_min",
DEFAULT_ASSOC_REJECTION_COUNT_MIN);
mAssocTimeoutHighThrPercent = DeviceConfig.getInt(NAMESPACE,
"assoc_timeout_high_thr_percent",
DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT);
mAssocTimeoutCountMin = DeviceConfig.getInt(NAMESPACE,
"assoc_timeout_count_min",
DEFAULT_ASSOC_TIMEOUT_COUNT_MIN);
mAuthFailureHighThrPercent = DeviceConfig.getInt(NAMESPACE,
"auth_failure_high_thr_percent",
DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT);
mAuthFailureCountMin = DeviceConfig.getInt(NAMESPACE,
"auth_failure_count_min",
DEFAULT_AUTH_FAILURE_COUNT_MIN);
mShortConnectionNonlocalHighThrPercent = DeviceConfig.getInt(NAMESPACE,
"short_connection_nonlocal_high_thr_percent",
DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT);
mShortConnectionNonlocalCountMin = DeviceConfig.getInt(NAMESPACE,
"short_connection_nonlocal_count_min",
DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN);
mDisconnectionNonlocalHighThrPercent = DeviceConfig.getInt(NAMESPACE,
"disconnection_nonlocal_high_thr_percent",
DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT);
mDisconnectionNonlocalCountMin = DeviceConfig.getInt(NAMESPACE,
"disconnection_nonlocal_count_min",
DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN);
mHealthMonitorRatioThrNumerator = DeviceConfig.getInt(NAMESPACE,
"health_monitor_ratio_thr_numerator",
DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR);
mHealthMonitorMinRssiThrDbm = DeviceConfig.getInt(NAMESPACE,
"health_monitor_min_rssi_thr_dbm",
DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM);
mRandomizationFlakySsidHotlist =
getUnmodifiableSetQuoted("randomization_flaky_ssid_hotlist");
mAggressiveMacRandomizationSsidAllowlist =
getUnmodifiableSetQuoted("aggressive_randomization_ssid_allowlist");
mAggressiveMacRandomizationSsidBlocklist =
getUnmodifiableSetQuoted("aggressive_randomization_ssid_blocklist");
mIsAbnormalConnectionFailureBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
"abnormal_connection_failure_bugreport_enabled", false);
mIsAbnormalDisconnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
"abnormal_disconnection_bugreport_enabled", false);
mHealthMonitorMinNumConnectionAttempt = DeviceConfig.getInt(NAMESPACE,
"health_monitor_min_num_connection_attempt",
DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT);
mBugReportMinWindowMs = DeviceConfig.getInt(NAMESPACE,
"bug_report_min_window_ms",
DEFAULT_BUG_REPORT_MIN_WINDOW_MS);
mBugReportThresholdExtraRatio = DeviceConfig.getInt(NAMESPACE,
"report_bug_report_threshold_extra_ratio",
DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO);
mIsOverlappingConnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
"overlapping_connection_bugreport_enabled", false);
mOverlappingConnectionDurationThresholdMs = DeviceConfig.getInt(NAMESPACE,
"overlapping_connection_duration_threshold_ms",
DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS);
}
private Set<String> getUnmodifiableSetQuoted(String key) {
String rawList = DeviceConfig.getString(NAMESPACE, key, "");
Set<String> result = new ArraySet<>();
String[] list = rawList.split(",");
for (String cur : list) {
if (cur.length() == 0) {
continue;
}
result.add("\"" + cur + "\"");
}
return Collections.unmodifiableSet(result);
}
/**
* Gets the feature flag for reporting abnormally long connections.
*/
public boolean isAbnormalConnectionBugreportEnabled() {
return mIsAbnormalConnectionBugreportEnabled;
}
/**
* Gets the threshold for classifying abnormally long connections.
*/
public int getAbnormalConnectionDurationMs() {
return mAbnormalConnectionDurationMs;
}
/**
* Gets the duration of evaluating Wifi condition to trigger a data stall.
*/
public int getDataStallDurationMs() {
return mDataStallDurationMs;
}
/**
* Gets the threshold of Tx throughput below which to trigger a data stall.
*/
public int getDataStallTxTputThrKbps() {
return mDataStallTxTputThrKbps;
}
/**
* Gets the threshold of Rx throughput below which to trigger a data stall.
*/
public int getDataStallRxTputThrKbps() {
return mDataStallRxTputThrKbps;
}
/**
* Gets the threshold of Tx packet error rate above which to trigger a data stall.
*/
public int getDataStallTxPerThr() {
return mDataStallTxPerThr;
}
/**
* Gets the threshold of CCA level above which to trigger a data stall.
*/
public int getDataStallCcaLevelThr() {
return mDataStallCcaLevelThr;
}
/**
* Gets the low threshold of L2 throughput below which L2 throughput is always insufficient
*/
public int getTputSufficientLowThrKbps() {
return mTputSufficientLowThrKbps;
}
/**
* Gets the high threshold of L2 throughput above which L2 throughput is always sufficient
*/
public int getTputSufficientHighThrKbps() {
return mTputSufficientHighThrKbps;
}
/**
* Gets the numerator part of L2 throughput over L3 throughput ratio sufficiency threshold
* above which L2 throughput is sufficient
*/
public int getTputSufficientRatioThrNum() {
return mTputSufficientRatioThrNum;
}
/**
* Gets the denominator part of L2 throughput over L3 throughput ratio sufficiency threshold
* above which L2 throughput is sufficient
*/
public int getTputSufficientRatioThrDen() {
return mTputSufficientRatioThrDen;
}
/**
* Gets the threshold of Tx packet per second
* below which Tx throughput sufficiency check will always pass
*/
public int getTxPktPerSecondThr() {
return mTxPktPerSecondThr;
}
/**
* Gets the threshold of Rx packet per second
* below which Rx throughput sufficiency check will always pass
*/
public int getRxPktPerSecondThr() {
return mRxPktPerSecondThr;
}
/**
* Gets the high threshold of connection failure rate in percent
*/
public int getConnectionFailureHighThrPercent() {
return mConnectionFailureHighThrPercent;
}
/**
* Gets connection failure min count
*/
public int getConnectionFailureCountMin() {
return mConnectionFailureCountMin;
}
/**
* Gets the high threshold of association rejection rate in percent
*/
public int getAssocRejectionHighThrPercent() {
return mAssocRejectionHighThrPercent;
}
/**
* Gets association rejection min count
*/
public int getAssocRejectionCountMin() {
return mAssocRejectionCountMin;
}
/**
* Gets the high threshold of association timeout rate in percent
*/
public int getAssocTimeoutHighThrPercent() {
return mAssocTimeoutHighThrPercent;
}
/**
* Gets association timeout min count
*/
public int getAssocTimeoutCountMin() {
return mAssocTimeoutCountMin;
}
/**
* Gets the high threshold of authentication failure rate in percent
*/
public int getAuthFailureHighThrPercent() {
return mAuthFailureHighThrPercent;
}
/**
* Gets authentication failure min count
*/
public int getAuthFailureCountMin() {
return mAuthFailureCountMin;
}
/**
* Gets the high threshold of nonlocal short connection rate in percent
*/
public int getShortConnectionNonlocalHighThrPercent() {
return mShortConnectionNonlocalHighThrPercent;
}
/**
* Gets nonlocal short connection min count
*/
public int getShortConnectionNonlocalCountMin() {
return mShortConnectionNonlocalCountMin;
}
/**
* Gets the high threshold of nonlocal disconnection rate in percent
*/
public int getDisconnectionNonlocalHighThrPercent() {
return mDisconnectionNonlocalHighThrPercent;
}
/**
* Gets nonlocal disconnection min count
*/
public int getDisconnectionNonlocalCountMin() {
return mDisconnectionNonlocalCountMin;
}
/**
* Gets health monitor ratio threshold, numerator part
*/
public int getHealthMonitorRatioThrNumerator() {
return mHealthMonitorRatioThrNumerator;
}
/**
* Gets health monitor min RSSI threshold in dBm
*/
public int getHealthMonitorMinRssiThrDbm() {
return mHealthMonitorMinRssiThrDbm;
}
/**
* Gets the Set of SSIDs in the flaky SSID hotlist.
*/
public Set<String> getRandomizationFlakySsidHotlist() {
return mRandomizationFlakySsidHotlist;
}
/**
* Gets the list of SSIDs for aggressive MAC randomization.
*/
public Set<String> getAggressiveMacRandomizationSsidAllowlist() {
return mAggressiveMacRandomizationSsidAllowlist;
}
/**
* Gets the list of SSIDs that aggressive MAC randomization should not be used for.
*/
public Set<String> getAggressiveMacRandomizationSsidBlocklist() {
return mAggressiveMacRandomizationSsidBlocklist;
}
/**
* Gets the feature flag for reporting abnormal connection failure.
*/
public boolean isAbnormalConnectionFailureBugreportEnabled() {
return mIsAbnormalConnectionFailureBugreportEnabled;
}
/**
* Gets the feature flag for reporting abnormal disconnection.
*/
public boolean isAbnormalDisconnectionBugreportEnabled() {
return mIsAbnormalDisconnectionBugreportEnabled;
}
/**
* Gets health monitor min number of connection attempt threshold
*/
public int getHealthMonitorMinNumConnectionAttempt() {
return mHealthMonitorMinNumConnectionAttempt;
}
/**
* Gets minimum wait time between two bug report captures
*/
public int getBugReportMinWindowMs() {
return mBugReportMinWindowMs;
}
/**
* Gets the extra ratio of threshold to trigger bug report.
*/
public int getBugReportThresholdExtraRatio() {
return mBugReportThresholdExtraRatio;
}
/**
* Gets the feature flag for reporting overlapping connection.
*/
public boolean isOverlappingConnectionBugreportEnabled() {
return mIsOverlappingConnectionBugreportEnabled;
}
/**
* Gets overlapping connection duration threshold in ms
*/
public int getOverlappingConnectionDurationThresholdMs() {
return mOverlappingConnectionDurationThresholdMs;
}
}