Merge "Wifi: Add ether_type to sending offloaded packet"
diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java
index 09d041b..d118d83 100644
--- a/service/java/com/android/server/wifi/ActiveModeWarden.java
+++ b/service/java/com/android/server/wifi/ActiveModeWarden.java
@@ -556,6 +556,12 @@
} // class ModeStateMachine
private class SoftApCallbackImpl extends ModeCallback implements WifiManager.SoftApCallback {
+ private int mMode;
+
+ private SoftApCallbackImpl(int mode) {
+ mMode = mode;
+ }
+
@Override
public void onStateChanged(int state, int reason) {
if (state == WifiManager.WIFI_AP_STATE_DISABLED) {
@@ -566,17 +572,17 @@
updateBatteryStatsWifiState(false);
}
- if (mSoftApCallback != null) {
+ if (mSoftApCallback != null && mMode == WifiManager.IFACE_IP_MODE_TETHERED) {
mSoftApCallback.onStateChanged(state, reason);
}
}
@Override
public void onNumClientsChanged(int numClients) {
- if (mSoftApCallback != null) {
- mSoftApCallback.onNumClientsChanged(numClients);
- } else {
+ if (mSoftApCallback == null) {
Log.d(TAG, "SoftApCallback is null. Dropping NumClientsChanged event.");
+ } else if (mMode == WifiManager.IFACE_IP_MODE_TETHERED) {
+ mSoftApCallback.onNumClientsChanged(numClients);
}
}
}
@@ -591,7 +597,7 @@
config = null;
}
- SoftApCallbackImpl callback = new SoftApCallbackImpl();
+ SoftApCallbackImpl callback = new SoftApCallbackImpl(softapConfig.getTargetMode());
ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig);
callback.setActiveModeManager(manager);
manager.start();
diff --git a/service/java/com/android/server/wifi/AvailableNetworkNotifier.java b/service/java/com/android/server/wifi/AvailableNetworkNotifier.java
index c28d521..7def2f3 100644
--- a/service/java/com/android/server/wifi/AvailableNetworkNotifier.java
+++ b/service/java/com/android/server/wifi/AvailableNetworkNotifier.java
@@ -38,6 +38,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -140,11 +141,18 @@
/** System wide identifier for notification in Notification Manager */
private final int mSystemMessageNotificationId;
+ /**
+ * The nominator id for this class, from
+ * {@link com.android.server.wifi.nano.WifiMetricsProto.ConnectionEvent.ConnectionNominator}
+ */
+ private final int mNominatorId;
+
public AvailableNetworkNotifier(
String tag,
String storeDataIdentifier,
String toggleSettingsName,
int notificationIdentifier,
+ int nominatorId,
Context context,
Looper looper,
FrameworkFacade framework,
@@ -158,6 +166,7 @@
mStoreDataIdentifier = storeDataIdentifier;
mToggleSettingsName = toggleSettingsName;
mSystemMessageNotificationId = notificationIdentifier;
+ mNominatorId = nominatorId;
mContext = context;
mHandler = new Handler(looper);
mFrameworkFacade = framework;
@@ -425,13 +434,19 @@
"User initiated connection to recommended network: "
+ "\"" + mRecommendedNetwork.SSID + "\"");
WifiConfiguration network = createRecommendedNetworkConfig(mRecommendedNetwork);
- Message msg = Message.obtain();
- msg.what = WifiManager.CONNECT_NETWORK;
- msg.arg1 = WifiConfiguration.INVALID_NETWORK_ID;
- msg.obj = network;
- msg.replyTo = mSrcMessenger;
- mClientModeImpl.sendMessage(msg);
- addNetworkToBlacklist(mRecommendedNetwork.SSID);
+
+ NetworkUpdateResult result = mConfigManager.addOrUpdateNetwork(network, Process.WIFI_UID);
+ if (result.isSuccess()) {
+ mWifiMetrics.setNominatorForNetwork(result.netId, mNominatorId);
+
+ Message msg = Message.obtain();
+ msg.what = WifiManager.CONNECT_NETWORK;
+ msg.arg1 = result.netId;
+ msg.obj = null;
+ msg.replyTo = mSrcMessenger;
+ mClientModeImpl.sendMessage(msg);
+ addNetworkToBlacklist(mRecommendedNetwork.SSID);
+ }
mState = STATE_CONNECTING_IN_NOTIFICATION;
mHandler.postDelayed(
diff --git a/service/java/com/android/server/wifi/CarrierNetworkConfig.java b/service/java/com/android/server/wifi/CarrierNetworkConfig.java
index cf39e0a..dc25721 100644
--- a/service/java/com/android/server/wifi/CarrierNetworkConfig.java
+++ b/service/java/com/android/server/wifi/CarrierNetworkConfig.java
@@ -53,14 +53,22 @@
private static final int ENCODED_SSID_INDEX = 0;
private static final int EAP_TYPE_INDEX = 1;
private static final int CONFIG_ELEMENT_SIZE = 2;
+
private static final Uri CONTENT_URI = Uri.parse("content://carrier_information/carrier");
private boolean mDbg = false;
private final Map<String, NetworkInfo> mCarrierNetworkMap;
private boolean mIsCarrierImsiEncryptionInfoAvailable = false;
+ private int mBase64EncodingMethod = Base64.DEFAULT;
private ImsiEncryptionInfo mLastImsiEncryptionInfo = null; // used for dumpsys only
+ // RFC2045: adds Line Feed at each 76 chars and encode it.
+ public static final int ENCODING_METHOD_RFC_2045 = 2045;
+
+ // RFC4648: encodes whole data into one string.
+ public static final int ENCODING_METHOD_RFC_4648 = 4648;
+
/**
* Enable/disable verbose logging.
*/
@@ -118,6 +126,13 @@
}
/**
+ * @return the base64 encoding flag for current carrier.
+ */
+ public int getBase64EncodingFlag() {
+ return mBase64EncodingMethod;
+ }
+
+ /**
* @return True if carrier IMSI encryption info is available, False otherwise.
*/
public boolean isCarrierEncryptionInfoAvailable() {
@@ -230,6 +245,16 @@
return;
}
+ int encodeMethod = carrierConfig.getInt(
+ CarrierConfigManager.KEY_IMSI_ENCODING_METHOD_INT, ENCODING_METHOD_RFC_2045);
+ if (encodeMethod != ENCODING_METHOD_RFC_2045 && encodeMethod != ENCODING_METHOD_RFC_4648) {
+ Log.e(TAG, "Invalid encoding method type: " + encodeMethod);
+ return;
+ }
+ mBase64EncodingMethod = Base64.DEFAULT;
+ if (encodeMethod == ENCODING_METHOD_RFC_4648) {
+ mBase64EncodingMethod = Base64.NO_WRAP;
+ }
for (String networkConfig : networkConfigs) {
String[] configArr = networkConfig.split(NETWORK_CONFIG_SEPARATOR);
if (configArr.length != CONFIG_ELEMENT_SIZE) {
@@ -237,9 +262,11 @@
continue;
}
try {
+
String ssid = new String(Base64.decode(
- configArr[ENCODED_SSID_INDEX], Base64.DEFAULT));
+ configArr[ENCODED_SSID_INDEX], mBase64EncodingMethod));
int eapType = parseEapType(Integer.parseInt(configArr[EAP_TYPE_INDEX]));
+
// Verify EAP type, must be a SIM based EAP type.
if (eapType == -1) {
Log.e(TAG, "Invalid EAP type: " + configArr[EAP_TYPE_INDEX]);
@@ -281,6 +308,7 @@
pw.println("mCarrierNetworkMap=" + mCarrierNetworkMap);
pw.println("mIsCarrierImsiEncryptionInfoAvailable="
+ mIsCarrierImsiEncryptionInfoAvailable);
+ pw.println("mBase64EncodingMethod=" + mBase64EncodingMethod);
pw.println("mLastImsiEncryptionInfo=" + mLastImsiEncryptionInfo);
}
}
diff --git a/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java b/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
index b052c7d..323cfc0 100644
--- a/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
@@ -110,6 +110,17 @@
}
config.enterpriseConfig.setEapMethod(eapType);
+ // Check if we already have a network with the same credentials in WifiConfigManager
+ // database. If yes, we should check if the network is currently blacklisted.
+ WifiConfiguration existingNetwork =
+ mWifiConfigManager.getConfiguredNetwork(config.configKey());
+ if (existingNetwork != null
+ && !existingNetwork.getNetworkSelectionStatus().isNetworkEnabled()
+ && !mWifiConfigManager.tryEnableNetwork(existingNetwork.networkId)) {
+ mLocalLog.log(TAG + ": Ignoring blacklisted network: "
+ + WifiNetworkSelector.toNetworkString(existingNetwork));
+ continue;
+ }
// Add the newly created WifiConfiguration to WifiConfigManager.
NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork(config,
Process.WIFI_UID);
@@ -131,7 +142,10 @@
config = mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
- WifiConfiguration.NetworkSelectionStatus nss = config.getNetworkSelectionStatus();
+ WifiConfiguration.NetworkSelectionStatus nss = null;
+ if (config != null) {
+ nss = config.getNetworkSelectionStatus();
+ }
if (nss == null) {
mLocalLog.log(TAG + ": null network selection status for: " + config);
continue;
diff --git a/service/java/com/android/server/wifi/CarrierNetworkNotifier.java b/service/java/com/android/server/wifi/CarrierNetworkNotifier.java
index 747cf07..5af4001 100644
--- a/service/java/com/android/server/wifi/CarrierNetworkNotifier.java
+++ b/service/java/com/android/server/wifi/CarrierNetworkNotifier.java
@@ -26,7 +26,7 @@
import android.provider.Settings;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.server.wifi.util.ScanResultUtil;
+import com.android.server.wifi.nano.WifiMetricsProto;
/**
* This class handles the "carrier wi-fi network available" notification
@@ -50,14 +50,16 @@
ClientModeImpl clientModeImpl,
ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder) {
super(TAG, STORE_DATA_IDENTIFIER, TOGGLE_SETTINGS_NAME,
- SystemMessage.NOTE_CARRIER_NETWORK_AVAILABLE, context, looper, framework, clock,
+ SystemMessage.NOTE_CARRIER_NETWORK_AVAILABLE,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER,
+ context, looper, framework, clock,
wifiMetrics, wifiConfigManager, wifiConfigStore, clientModeImpl,
connectToNetworkNotificationBuilder);
}
@Override
WifiConfiguration createRecommendedNetworkConfig(ScanResult recommendedNetwork) {
- WifiConfiguration network = ScanResultUtil.createNetworkFromScanResult(recommendedNetwork);
+ WifiConfiguration network = super.createRecommendedNetworkConfig(recommendedNetwork);
int eapMethod = recommendedNetwork.carrierApEapType;
if (eapMethod == Eap.SIM || eapMethod == Eap.AKA || eapMethod == Eap.AKA_PRIME) {
diff --git a/service/java/com/android/server/wifi/CellularLinkLayerStats.java b/service/java/com/android/server/wifi/CellularLinkLayerStats.java
new file mode 100644
index 0000000..25f2949
--- /dev/null
+++ b/service/java/com/android/server/wifi/CellularLinkLayerStats.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 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 android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.NetworkType;
+
+/**
+ * A class representing the link layer statistics of the primary registered cell
+ * of cellular network
+ */
+public class CellularLinkLayerStats {
+ /** Cellular data network type currently in use on the device for data transmission */
+ private @NetworkType int mDataNetworkType =
+ TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ /**
+ * Cellular signal strength in dBm, NR: CsiRsrp, LTE: Rsrp, WCDMA/TDSCDMA: Rscp,
+ * CDMA: Rssi, EVDO: Rssi, GSM: Rssi
+ */
+ private int mSignalStrengthDbm = SignalStrength.INVALID;
+ /**
+ * Cellular signal strength in dB, NR: CsiSinr, LTE: Rsrq, WCDMA: EcNo, TDSCDMA: invalid,
+ * CDMA: Ecio, EVDO: SNR, GSM: invalid
+ */
+ private int mSignalStrengthDb = SignalStrength.INVALID;
+ /** Whether it is a new or old registered cell */
+ private boolean mIsSameRegisteredCell = false;
+
+ public void setDataNetworkType(@NetworkType int dataNetworkType) {
+ mDataNetworkType = dataNetworkType;
+ }
+
+ public void setSignalStrengthDbm(int signalStrengthDbm) {
+ mSignalStrengthDbm = signalStrengthDbm;
+ }
+
+ public void setIsSameRegisteredCell(boolean isSameRegisteredCell) {
+ mIsSameRegisteredCell = isSameRegisteredCell;
+ }
+
+ public void setSignalStrengthDb(int signalStrengthDb) {
+ mSignalStrengthDb = signalStrengthDb;
+ }
+
+ public @NetworkType int getDataNetworkType() {
+ return mDataNetworkType;
+ }
+
+ public boolean getIsSameRegisteredCell() {
+ return mIsSameRegisteredCell;
+ }
+
+ public int getSignalStrengthDb() {
+ return mSignalStrengthDb;
+ }
+
+ public int getSignalStrengthDbm() {
+ return mSignalStrengthDbm;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder();
+ sbuf.append(" CellularLinkLayerStats: ").append('\n')
+ .append(" Data Network Type: ")
+ .append(mDataNetworkType).append('\n')
+ .append(" Signal Strength in dBm: ")
+ .append(mSignalStrengthDbm).append('\n')
+ .append(" Signal Strength in dB: ")
+ .append(mSignalStrengthDb).append('\n')
+ .append(" Is it the same registered cell? ")
+ .append(mIsSameRegisteredCell).append('\n');
+ return sbuf.toString();
+ }
+}
diff --git a/service/java/com/android/server/wifi/CellularLinkLayerStatsCollector.java b/service/java/com/android/server/wifi/CellularLinkLayerStatsCollector.java
new file mode 100644
index 0000000..473ced3
--- /dev/null
+++ b/service/java/com/android/server/wifi/CellularLinkLayerStatsCollector.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 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 android.telephony.TelephonyManager.NETWORK_TYPE_CDMA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EVDO_0;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GSM;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_TD_SCDMA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+
+import android.content.Context;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoNr;
+import android.telephony.CellInfoTdscdma;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellSignalStrength;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthNr;
+import android.telephony.CellSignalStrengthTdscdma;
+import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * A class collecting the latest cellular link layer stats
+ */
+public class CellularLinkLayerStatsCollector {
+ private static final String TAG = "CellStatsCollector";
+ private static final boolean DBG = false;
+
+ private Context mContext;
+ private SubscriptionManager mSubManager = null;
+ private TelephonyManager mCachedDefaultDataTelephonyManager = null;
+ private int mCachedDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private CellInfo mLastPrimaryCellInfo = null;
+ private int mLastDataNetworkType = NETWORK_TYPE_UNKNOWN;
+
+ public CellularLinkLayerStatsCollector(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Get the latest DataNetworkType, SignalStrength, CellInfo and other information from
+ * default data sim's TelephonyManager, parse the values of primary registered cell and return
+ * them as an instance of CellularLinkLayerStats
+ */
+ public CellularLinkLayerStats update() {
+ CellularLinkLayerStats cellStats = new CellularLinkLayerStats();
+
+ retrieveDefaultDataTelephonyManager();
+ if (mCachedDefaultDataTelephonyManager == null) {
+ if (DBG) Log.v(TAG, cellStats.toString());
+ return cellStats;
+ }
+
+ SignalStrength signalStrength = mCachedDefaultDataTelephonyManager.getSignalStrength();
+ List<CellSignalStrength> cssList = null;
+ if (signalStrength != null) cssList = signalStrength.getCellSignalStrengths();
+
+ if (mCachedDefaultDataTelephonyManager.getDataNetworkType() == NETWORK_TYPE_UNKNOWN
+ || cssList == null || cssList.size() == 0) {
+ mLastPrimaryCellInfo = null;
+ mLastDataNetworkType = NETWORK_TYPE_UNKNOWN;
+ if (DBG) Log.v(TAG, cellStats.toString());
+ return cellStats;
+ }
+ if (DBG) Log.v(TAG, "Cell Signal Strength List size = " + cssList.size());
+
+ CellSignalStrength primaryCss = cssList.get(0);
+ cellStats.setSignalStrengthDbm(primaryCss.getDbm());
+
+ updateSignalStrengthDbAndNetworkTypeOfCellStats(primaryCss, cellStats);
+
+ int networkType = cellStats.getDataNetworkType();
+ CellInfo primaryCellInfo = getPrimaryCellInfo(mCachedDefaultDataTelephonyManager,
+ networkType);
+ boolean isSameRegisteredCell = getIsSameRegisteredCell(primaryCellInfo, networkType);
+ cellStats.setIsSameRegisteredCell(isSameRegisteredCell);
+
+ // Update for the next call
+ mLastPrimaryCellInfo = primaryCellInfo;
+ mLastDataNetworkType = networkType;
+
+ if (DBG) Log.v(TAG, cellStats.toString());
+ return cellStats;
+ }
+
+ private void retrieveDefaultDataTelephonyManager() {
+ if (!initSubManager()) return;
+
+ int defaultDataSubId = mSubManager.getDefaultDataSubscriptionId();
+ if (DBG) Log.v(TAG, "default Data Sub ID = " + defaultDataSubId);
+ if (defaultDataSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mCachedDefaultDataTelephonyManager = null;
+ return;
+ }
+
+ if (defaultDataSubId != mCachedDefaultDataSubId
+ || mCachedDefaultDataTelephonyManager == null) {
+ mCachedDefaultDataSubId = defaultDataSubId;
+ TelephonyManager defaultSubTelephonyManager = (TelephonyManager) mContext
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if (defaultDataSubId == mSubManager.getDefaultSubscriptionId()) {
+ mCachedDefaultDataTelephonyManager = defaultSubTelephonyManager;
+ } else {
+ mCachedDefaultDataTelephonyManager = defaultSubTelephonyManager
+ .createForSubscriptionId(defaultDataSubId);
+ }
+ }
+ }
+
+ private boolean initSubManager() {
+ if (mSubManager == null) {
+ mSubManager = (SubscriptionManager) mContext.getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ }
+ return (mSubManager != null);
+ }
+
+ /**
+ * Update dB value and network type base on CellSignalStrength subclass type.
+ * It follows the same order as that in SignalStrength.getPrimary().
+ * TODO: NR may move up in the future
+ */
+ private void updateSignalStrengthDbAndNetworkTypeOfCellStats(CellSignalStrength primaryCss,
+ CellularLinkLayerStats cellStats) {
+ if (primaryCss instanceof CellSignalStrengthLte) {
+ CellSignalStrengthLte cssLte = (CellSignalStrengthLte) primaryCss;
+ cellStats.setSignalStrengthDb(cssLte.getRsrq());
+ cellStats.setDataNetworkType(NETWORK_TYPE_LTE);
+ } else if (primaryCss instanceof CellSignalStrengthCdma) {
+ CellSignalStrengthCdma cssCdma = (CellSignalStrengthCdma) primaryCss;
+ int evdoSnr = cssCdma.getEvdoSnr();
+ int cdmaEcio = cssCdma.getCdmaEcio();
+ if (evdoSnr != SignalStrength.INVALID) {
+ cellStats.setSignalStrengthDb(evdoSnr);
+ cellStats.setDataNetworkType(NETWORK_TYPE_EVDO_0);
+ } else {
+ cellStats.setSignalStrengthDb(cdmaEcio);
+ cellStats.setDataNetworkType(NETWORK_TYPE_CDMA);
+ }
+ } else if (primaryCss instanceof CellSignalStrengthTdscdma) {
+ cellStats.setDataNetworkType(NETWORK_TYPE_TD_SCDMA);
+ } else if (primaryCss instanceof CellSignalStrengthWcdma) {
+ CellSignalStrengthWcdma cssWcdma = (CellSignalStrengthWcdma) primaryCss;
+ cellStats.setSignalStrengthDb(cssWcdma.getEcNo());
+ cellStats.setDataNetworkType(NETWORK_TYPE_UMTS);
+ } else if (primaryCss instanceof CellSignalStrengthGsm) {
+ cellStats.setDataNetworkType(NETWORK_TYPE_GSM);
+ } else if (primaryCss instanceof CellSignalStrengthNr) {
+ CellSignalStrengthNr cssNr = (CellSignalStrengthNr) primaryCss;
+ cellStats.setSignalStrengthDb(cssNr.getCsiSinr());
+ cellStats.setDataNetworkType(NETWORK_TYPE_NR);
+ } else {
+ Log.e(TAG, "invalid CellSignalStrength");
+ }
+ }
+
+ private CellInfo getPrimaryCellInfo(TelephonyManager defaultDataTelephonyManager,
+ int networkType) {
+ List<CellInfo> cellInfoList = getRegisteredCellInfo(defaultDataTelephonyManager);
+ int cilSize = cellInfoList.size();
+ CellInfo primaryCellInfo = null;
+ // CellInfo.getCellConnectionStatus() should tell if it is primary serving cell.
+ // However, it currently always returns 0 (CONNECTION_NONE) for registered cells.
+ // Therefore, the workaround of deriving primary serving cell is
+ // to check if the registered cellInfo subclass type matches networkType
+ for (int i = 0; i < cilSize; ++i) {
+ CellInfo cellInfo = cellInfoList.get(i);
+ if ((cellInfo instanceof CellInfoTdscdma && networkType == NETWORK_TYPE_TD_SCDMA)
+ || (cellInfo instanceof CellInfoCdma && (networkType == NETWORK_TYPE_CDMA
+ || networkType == NETWORK_TYPE_EVDO_0))
+ || (cellInfo instanceof CellInfoLte && networkType == NETWORK_TYPE_LTE)
+ || (cellInfo instanceof CellInfoWcdma && networkType == NETWORK_TYPE_UMTS)
+ || (cellInfo instanceof CellInfoGsm && networkType == NETWORK_TYPE_GSM)
+ || (cellInfo instanceof CellInfoNr && networkType == NETWORK_TYPE_NR)) {
+ primaryCellInfo = cellInfo;
+ }
+ }
+ return primaryCellInfo;
+ }
+
+ private boolean getIsSameRegisteredCell(CellInfo primaryCellInfo, int networkType) {
+ boolean isSameRegisteredCell;
+ if (primaryCellInfo != null && mLastPrimaryCellInfo != null) {
+ isSameRegisteredCell = primaryCellInfo.getCellIdentity()
+ .equals(mLastPrimaryCellInfo.getCellIdentity());
+ } else if (primaryCellInfo == null && mLastPrimaryCellInfo == null) {
+ // This is a workaround when it can't find primaryCellInfo for two consecutive times.
+ isSameRegisteredCell = true;
+ } else {
+ // only one of them is null and it is a strong indication of primary cell change.
+ isSameRegisteredCell = false;
+ }
+
+ if (mLastDataNetworkType == NETWORK_TYPE_UNKNOWN || mLastDataNetworkType != networkType) {
+ isSameRegisteredCell = false;
+ }
+ return isSameRegisteredCell;
+ }
+
+ private List<CellInfo> getRegisteredCellInfo(TelephonyManager defaultDataTelephonyManager) {
+ List<CellInfo> allList = defaultDataTelephonyManager.getAllCellInfo();
+ List<CellInfo> cellInfoList = new ArrayList<>();
+ for (CellInfo ci : allList) {
+ if (ci.isRegistered()) cellInfoList.add(ci);
+ if (DBG) Log.v(TAG, ci.toString());
+ }
+ return cellInfoList;
+ }
+}
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 7497aaf..dcf8432 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -17,7 +17,6 @@
package com.android.server.wifi;
import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable;
-import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER_DISCONNECT;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
@@ -811,6 +810,7 @@
mFacade.makeSupplicantStateTracker(context, mWifiConfigManager, getHandler());
mWifiConnectivityManager = mWifiInjector.makeWifiConnectivityManager(this);
+
mLinkProperties = new LinkProperties();
mMcastLockManagerFilterController = new McastLockManagerFilterController();
@@ -872,15 +872,6 @@
}
});
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- sendMessage(CMD_BOOT_COMPLETED);
- }
- },
- new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));
-
mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext,
Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
@@ -1172,7 +1163,8 @@
private boolean connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect) {
logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid
+ ", forceReconnect = " + forceReconnect);
- if (mWifiConfigManager.getConfiguredNetwork(netId) == null) {
+ WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId);
+ if (config == null) {
loge("connectToUserSelectNetwork Invalid network Id=" + netId);
return false;
}
@@ -1191,6 +1183,10 @@
logi("connectToUserSelectNetwork already connecting/connected=" + netId);
} else {
mWifiConnectivityManager.prepareForForcedConnection(netId);
+ if (uid == Process.SYSTEM_UID) {
+ mWifiMetrics.setNominatorForNetwork(config.networkId,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
+ }
startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY);
}
return true;
@@ -1590,19 +1586,20 @@
}
/**
- * Method to trigger a disconnect.
- * Note: To be used from within the wifi stack.
+ * Disconnect from Access Point
*/
- public void disconnectCommandInternal() {
- sendMessage(CMD_DISCONNECT, 0 /* fromExternal */);
+ public void disconnectCommand() {
+ sendMessage(CMD_DISCONNECT);
}
/**
* Method to trigger a disconnect.
- * Note: To be used from public API surface.
+ *
+ * @param uid UID of requesting caller
+ * @param reason disconnect reason
*/
- public void disconnectCommandExternal() {
- sendMessage(CMD_DISCONNECT, 1 /* fromExternal */);
+ public void disconnectCommand(int uid, int reason) {
+ sendMessage(CMD_DISCONNECT, uid, reason);
}
/**
@@ -1692,13 +1689,14 @@
* scanResults per network type({@link WifiManager#PASSPOINT_HOME_NETWORK} and {@link
* WifiManager#PASSPOINT_ROAMING_NETWORK}).
*/
+ @NonNull
Map<String, Map<Integer, List<ScanResult>>> syncGetAllMatchingFqdnsForScanResults(
List<ScanResult> scanResults,
AsyncChannel channel) {
Message resultMsg = channel.sendMessageSynchronously(
CMD_GET_ALL_MATCHING_FQDNS_FOR_SCAN_RESULTS,
scanResults);
- if (messageIsNull(resultMsg)) return null;
+ if (messageIsNull(resultMsg)) return new HashMap<>();
Map<String, Map<Integer, List<ScanResult>>> configs =
(Map<String, Map<Integer, List<ScanResult>>>) resultMsg.obj;
resultMsg.recycle();
@@ -1713,12 +1711,13 @@
* @param channel Channel for communicating with the state machine
* @return Map that consists of {@link OsuProvider} and a matching list of {@link ScanResult}.
*/
+ @NonNull
public Map<OsuProvider, List<ScanResult>> syncGetMatchingOsuProviders(
List<ScanResult> scanResults,
AsyncChannel channel) {
Message resultMsg =
channel.sendMessageSynchronously(CMD_GET_MATCHING_OSU_PROVIDERS, scanResults);
- if (messageIsNull(resultMsg)) return null;
+ if (messageIsNull(resultMsg)) return new HashMap<>();
Map<OsuProvider, List<ScanResult>> providers =
(Map<OsuProvider, List<ScanResult>>) resultMsg.obj;
resultMsg.recycle();
@@ -1732,12 +1731,13 @@
* @param channel AsyncChannel to use for the response
* @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}.
*/
+ @NonNull
public Map<OsuProvider, PasspointConfiguration> syncGetMatchingPasspointConfigsForOsuProviders(
List<OsuProvider> osuProviders, AsyncChannel channel) {
Message resultMsg =
channel.sendMessageSynchronously(
CMD_GET_MATCHING_PASSPOINT_CONFIGS_FOR_OSU_PROVIDERS, osuProviders);
- if (messageIsNull(resultMsg)) return null;
+ if (messageIsNull(resultMsg)) return new HashMap<>();
Map<OsuProvider, PasspointConfiguration> result =
(Map<OsuProvider, PasspointConfiguration>) resultMsg.obj;
resultMsg.recycle();
@@ -1755,12 +1755,13 @@
* @return List of {@link WifiConfiguration} converted from
* {@link com.android.server.wifi.hotspot2.PasspointProvider}
*/
+ @NonNull
public List<WifiConfiguration> syncGetWifiConfigsForPasspointProfiles(List<String> fqdnList,
AsyncChannel channel) {
Message resultMsg =
channel.sendMessageSynchronously(
CMD_GET_WIFI_CONFIGS_FOR_PASSPOINT_PROFILES, fqdnList);
- if (messageIsNull(resultMsg)) return null;
+ if (messageIsNull(resultMsg)) return new ArrayList<>();
List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
resultMsg.recycle();
return result;
@@ -2062,6 +2063,13 @@
}
/**
+ * Trigger message to handle boot completed event.
+ */
+ public void handleBootCompleted() {
+ sendMessage(CMD_BOOT_COMPLETED);
+ }
+
+ /**
* Trigger message to handle user switch event.
*/
public void handleUserSwitch(int userId) {
@@ -3462,7 +3470,7 @@
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
@@ -3675,7 +3683,7 @@
if (removedNetworkIds.contains(mTargetNetworkId)
|| removedNetworkIds.contains(mLastNetworkId)) {
// Disconnect and let autojoin reselect a new network
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
break;
case CMD_USER_UNLOCK:
@@ -3746,7 +3754,12 @@
loge("Error! unhandled message" + message);
break;
}
- return HANDLED;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+
+ return handleStatus;
}
}
@@ -3978,7 +3991,7 @@
Set<Integer> removedNetworkIds;
int reasonCode;
boolean timedOut;
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
switch (message.what) {
case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
@@ -4133,7 +4146,7 @@
netId = message.arg1;
if (netId == mTargetNetworkId || netId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
break;
case CMD_ENABLE_NETWORK:
@@ -4157,7 +4170,7 @@
replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED);
if (netId == mTargetNetworkId || netId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
} else {
loge("Failed to disable network");
@@ -4172,7 +4185,7 @@
if (config.networkId == mTargetNetworkId
|| config.networkId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
}
break;
@@ -4186,7 +4199,8 @@
// Pair<identity, encrypted identity>
Pair<String, String> identityPair =
TelephonyUtil.getSimIdentity(getTelephonyManager(),
- new TelephonyUtil(), mTargetWifiConfiguration);
+ new TelephonyUtil(), mTargetWifiConfiguration,
+ mWifiInjector.getCarrierNetworkConfig());
Log.i(TAG, "SUP_REQUEST_IDENTITY: identityPair=" + identityPair);
if (identityPair != null && identityPair.first != null) {
mWifiNative.simIdentityResponse(mInterfaceName, netId,
@@ -4224,7 +4238,7 @@
handle3GAuthRequest(requestData);
}
} else {
- loge("Invalid sim auth request");
+ loge("Invalid SIM auth request");
}
break;
case CMD_GET_MATCHING_OSU_PROVIDERS:
@@ -4261,7 +4275,7 @@
break;
case CMD_START_ROAM:
mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
- return HANDLED;
+ break;
case CMD_START_CONNECT:
/* connect command coming from auto-join */
netId = message.arg1;
@@ -4332,7 +4346,7 @@
if (removedNetworkIds.contains(mTargetNetworkId)
|| removedNetworkIds.contains(mLastNetworkId)) {
// Disconnect and let autojoin reselect a new network.
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
break;
case CMD_REMOVE_USER_CONFIGURATIONS:
@@ -4341,7 +4355,7 @@
if (removedNetworkIds.contains(mTargetNetworkId)
|| removedNetworkIds.contains(mLastNetworkId)) {
// Disconnect and let autojoin reselect a new network.
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
break;
case WifiManager.CONNECT_NETWORK:
@@ -4422,7 +4436,7 @@
netId = message.arg1;
if (netId == mTargetNetworkId || netId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
break;
case CMD_ASSOCIATED_BSSID:
@@ -4438,7 +4452,8 @@
someBssid));
}
}
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
case WifiMonitor.NETWORK_CONNECTION_EVENT:
if (mVerboseLoggingEnabled) log("Network connection established");
mLastNetworkId = message.arg1;
@@ -4486,7 +4501,7 @@
} else {
logw("Connected to unknown networkId " + mLastNetworkId
+ ", disconnecting...");
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
break;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
@@ -4519,7 +4534,7 @@
if (isProviderOwnedNetwork(mTargetNetworkId, fqdn)
|| isProviderOwnedNetwork(mLastNetworkId, fqdn)) {
logd("Disconnect from current network since its provider is updated");
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
replyToMessage(message, message.what, SUCCESS);
} else {
@@ -4532,7 +4547,7 @@
if (isProviderOwnedNetwork(mTargetNetworkId, fqdn)
|| isProviderOwnedNetwork(mLastNetworkId, fqdn)) {
logd("Disconnect from current network since its provider is removed");
- disconnectCommandInternal();
+ sendMessage(CMD_DISCONNECT);
}
mWifiConfigManager.removePasspointConfiguredNetwork(fqdn);
replyToMessage(message, message.what, SUCCESS);
@@ -4622,9 +4637,15 @@
mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false);
break;
default:
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return HANDLED;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+
+ return handleStatus;
}
}
@@ -4982,7 +5003,7 @@
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
switch (message.what) {
case CMD_PRE_DHCP_ACTION:
@@ -5054,6 +5075,10 @@
if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj);
mWifiDiagnostics.captureBugReportData(
WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST);
+ mWifiMetrics.logWifiIsUnusableEvent(
+ WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
+ mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
+ WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST);
if (mIpReachabilityDisconnectEnabled) {
handleIpReachabilityLost();
transitionTo(mDisconnectingState);
@@ -5062,17 +5087,8 @@
}
break;
case CMD_DISCONNECT:
- boolean fromExternal = message.arg1 == 1;
- if (fromExternal) {
- mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_API);
- // For external disconnect requests, temporarily disable the network.
- mWifiConfigManager.updateNetworkSelectionStatus(
- mLastNetworkId, DISABLED_BY_WIFI_MANAGER_DISCONNECT);
- } else {
- mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_GENERIC);
- }
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_GENERIC);
mWifiNative.disconnect(mInterfaceName);
transitionTo(mDisconnectingState);
break;
@@ -5092,7 +5108,8 @@
replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED);
break;
}
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
case WifiMonitor.NETWORK_CONNECTION_EVENT:
mWifiInfo.setBSSID((String) message.obj);
mLastNetworkId = message.arg1;
@@ -5137,7 +5154,7 @@
mPollRssiIntervalMsecs);
if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi());
mWifiTrafficPoller.notifyOnDataActivity(mWifiInfo.txSuccess,
- mWifiInfo.rxSuccess);
+ mWifiInfo.rxSuccess);
} else {
// Polling has completed
}
@@ -5217,7 +5234,8 @@
}
}
/* allow parent state to reset data for other networks */
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
case CMD_START_IP_PACKET_OFFLOAD: {
int slot = message.arg1;
int intervalSeconds = message.arg2;
@@ -5251,10 +5269,15 @@
break;
}
default:
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return HANDLED;
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+
+ return handleStatus;
}
/**
@@ -5380,7 +5403,7 @@
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
switch(message.what) {
case CMD_START_CONNECT:
@@ -5396,15 +5419,21 @@
WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
WifiMetricsProto.ConnectionEvent.HLF_NONE,
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
case CMD_SET_HIGH_PERF_MODE:
mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
deferMessage(message);
break;
default:
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return HANDLED;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+ return handleStatus;
}
}
@@ -5470,8 +5499,9 @@
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, this);
WifiConfiguration config;
+ boolean handleStatus = HANDLED;
+
switch (message.what) {
case CMD_IP_CONFIGURATION_LOST:
config = getCurrentWifiConfiguration();
@@ -5479,12 +5509,13 @@
mWifiDiagnostics.captureBugReportData(
WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE);
}
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
case CMD_UNWANTED_NETWORK:
if (mVerboseLoggingEnabled) {
log("Roaming and CS doesnt want the network -> ignore");
}
- return HANDLED;
+ break;
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
/**
* If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT
@@ -5586,9 +5617,14 @@
}
break;
default:
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return HANDLED;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+ return handleStatus;
}
@Override
@@ -5633,7 +5669,7 @@
@Override
public boolean processMessage(Message message) {
WifiConfiguration config = null;
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
switch (message.what) {
case CMD_UNWANTED_NETWORK:
@@ -5677,7 +5713,7 @@
}
}
}
- return HANDLED;
+ break;
case CMD_NETWORK_STATUS:
if (message.arg1 == NetworkAgent.VALID_NETWORK) {
// stop collect last-mile stats since validation pass
@@ -5696,16 +5732,17 @@
config.networkId, true);
}
}
- return HANDLED;
+ break;
case CMD_ACCEPT_UNVALIDATED:
boolean accept = (message.arg1 != 0);
mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept);
- return HANDLED;
+ break;
case CMD_ASSOCIATED_BSSID:
// ASSOCIATING to a new BSSID while already connected, indicates
// that driver is roaming
mLastDriverRoamAttempt = mClock.getWallClockMillis();
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
long lastRoam = 0;
reportConnectionAttemptEnd(
@@ -5781,9 +5818,15 @@
}
break;
default:
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return HANDLED;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+
+ return handleStatus;
}
@Override
@@ -5820,7 +5863,8 @@
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
+
switch (message.what) {
case CMD_DISCONNECT:
if (mVerboseLoggingEnabled) {
@@ -5845,9 +5889,14 @@
transitionTo(mDisconnectedState);
break;
default:
- return NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return HANDLED;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+ return handleStatus;
}
}
@@ -5875,9 +5924,7 @@
@Override
public boolean processMessage(Message message) {
- boolean ret = HANDLED;
-
- logStateAndMessage(message, this);
+ boolean handleStatus = HANDLED;
switch (message.what) {
case CMD_DISCONNECT:
@@ -5908,6 +5955,9 @@
// Update Passpoint information before setNetworkDetailedState as
// WifiTracker monitors NETWORK_STATE_CHANGED_ACTION to update UI.
+ mWifiInfo.setFQDN(null);
+ mWifiInfo.setOsuAp(false);
+ mWifiInfo.setProviderFriendlyName(null);
if (config != null && (config.isPasspoint() || config.osu)) {
if (config.isPasspoint()) {
mWifiInfo.setFQDN(config.FQDN);
@@ -5919,7 +5969,7 @@
}
setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
/* ConnectModeState does the rest of the handling */
- ret = NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
break;
case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
NetworkInfo info = (NetworkInfo) message.obj;
@@ -5933,16 +5983,21 @@
break;
} else {
// ConnectModeState handles it
- ret = NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
}
break;
case CMD_SCREEN_STATE_CHANGED:
handleScreenStateChanged(message.arg1 != 0);
break;
default:
- ret = NOT_HANDLED;
+ handleStatus = NOT_HANDLED;
+ break;
}
- return ret;
+
+ if (handleStatus == HANDLED) {
+ logStateAndMessage(message, this);
+ }
+ return handleStatus;
}
@Override
diff --git a/service/java/com/android/server/wifi/CompatibilityScorer.java b/service/java/com/android/server/wifi/CompatibilityScorer.java
index a4783f1..550eca7 100644
--- a/service/java/com/android/server/wifi/CompatibilityScorer.java
+++ b/service/java/com/android/server/wifi/CompatibilityScorer.java
@@ -68,8 +68,6 @@
/**
* Calculates an individual candidate's score.
- *
- * This relies mostly on the scores provided by the evaluator.
*/
private ScoredCandidate scoreCandidate(Candidate candidate) {
int rssiSaturationThreshold = mScoringParams.getGoodRssi(candidate.getFrequency());
@@ -94,7 +92,10 @@
// which evaluator added the candidate.
score -= 1000 * candidate.getEvaluatorId();
- return new ScoredCandidate(score, 10, candidate);
+ // The old method breaks ties on the basis of RSSI, which we can
+ // emulate easily since our score does not need to be an integer.
+ double tieBreaker = candidate.getScanRssi() / 1000.0;
+ return new ScoredCandidate(score + tieBreaker, 10, candidate);
}
@Override
diff --git a/service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java b/service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java
index 136d5c7..ddc0b71 100644
--- a/service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java
+++ b/service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java
@@ -21,16 +21,21 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiNetworkSuggestion;
import android.util.LocalLog;
-import android.util.Pair;
+import android.util.Log;
import com.android.server.wifi.util.ScanResultUtil;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
/**
@@ -74,19 +79,10 @@
WifiConfiguration currentNetwork, String currentBssid, boolean connected,
boolean untrustedNetworkAllowed,
@NonNull OnConnectableListener onConnectableListener) {
- Map<WifiNetworkSuggestion, Pair<WifiConfiguration, ScanDetail>> candidateMap =
- new HashMap<>();
+ MatchMetaInfo matchMetaInfo = new MatchMetaInfo();
for (int i = 0; i < scanDetails.size(); i++) {
ScanDetail scanDetail = scanDetails.get(i);
ScanResult scanResult = scanDetail.getScanResult();
- Set<WifiNetworkSuggestion> matchingNetworkSuggestions =
- mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail);
- if (matchingNetworkSuggestions == null || matchingNetworkSuggestions.isEmpty()) {
- continue;
- }
- // All matching network credentials are considered equal. So, put any one of them.
- WifiNetworkSuggestion matchingNetworkSuggestion =
- matchingNetworkSuggestions.stream().findAny().get();
// If the user previously forgot this network, don't select it.
if (mWifiConfigManager.wasEphemeralNetworkDeleted(
ScanResultUtil.createQuotedSSID(scanResult.SSID))) {
@@ -94,9 +90,20 @@
+ WifiNetworkSelector.toScanId(scanResult));
continue;
}
+ Set<WifiNetworkSuggestion> matchingNetworkSuggestions =
+ mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail);
+ if (matchingNetworkSuggestions == null || matchingNetworkSuggestions.isEmpty()) {
+ continue;
+ }
+ // All matching suggestions have the same network credentials type. So, use any one of
+ // them to lookup/add the credentials to WifiConfigManager.
+ // Note: Apps could provide different credentials (password, ceritificate) for the same
+ // network, need to handle that in the future.
+ WifiNetworkSuggestion matchingNetworkSuggestion =
+ matchingNetworkSuggestions.stream().findAny().get();
// Check if we already have a network with the same credentials in WifiConfigManager
// database. If yes, we should check if the network is currently blacklisted.
- WifiConfiguration wCmConfiguredNetwork =
+ WifiConfiguration wCmConfiguredNetwork =
mWifiConfigManager.getConfiguredNetwork(
matchingNetworkSuggestion.wifiConfiguration.configKey());
if (wCmConfiguredNetwork != null) {
@@ -106,35 +113,23 @@
+ WifiNetworkSelector.toNetworkString(wCmConfiguredNetwork));
continue;
}
- mLocalLog.log(String.format("network suggestion candidate %s (existing)",
- WifiNetworkSelector.toNetworkString(wCmConfiguredNetwork)));
- } else {
- wCmConfiguredNetwork = addCandidateToWifiConfigManager(
- matchingNetworkSuggestion.wifiConfiguration,
- matchingNetworkSuggestion.suggestorUid,
- matchingNetworkSuggestion.suggestorPackageName);
- if (wCmConfiguredNetwork == null) continue;
- mLocalLog.log(String.format("network suggestion candidate %s (new)",
- WifiNetworkSelector.toNetworkString(wCmConfiguredNetwork)));
}
- candidateMap.put(matchingNetworkSuggestion,
- Pair.create(wCmConfiguredNetwork, scanDetail));
- onConnectableListener.onConnectable(scanDetail, wCmConfiguredNetwork, 0);
+ matchMetaInfo.putAll(matchingNetworkSuggestions, wCmConfiguredNetwork, scanDetail);
}
-
- // Pick the matching network suggestion corresponding to the highest RSSI. This will need to
- // be replaced by a more sophisticated algorithm.
- Map.Entry<WifiNetworkSuggestion, Pair<WifiConfiguration, ScanDetail>>
- candidate = candidateMap
- .entrySet()
- .stream()
- .max(Comparator.comparing(e -> e.getValue().second.getScanResult().level))
- .orElse(null);
- if (candidate == null) {
+ // Return early on no match.
+ if (matchMetaInfo.isEmpty()) {
mLocalLog.log("did not see any matching network suggestions.");
return null;
}
- return candidate.getValue().first;
+ // Note: These matched sets should be very small & hence these additional manipulations that
+ // follow should not be very expensive.
+ PerNetworkSuggestionMatchMetaInfo candidate =
+ matchMetaInfo.findConnectableNetworksAndPickBest(onConnectableListener);
+ if (candidate == null) { // should never happen.
+ Log.wtf(TAG, "Unexepectedly got null");
+ return null;
+ }
+ return candidate.wCmConfiguredNetwork;
}
// Add and enable this network to the central database (i.e WifiConfigManager).
@@ -169,4 +164,136 @@
public String getName() {
return TAG;
}
+
+ // Container classes to handle book-keeping while we're iterating through the scan list.
+ private class PerNetworkSuggestionMatchMetaInfo {
+ public final WifiNetworkSuggestion wifiNetworkSuggestion;
+ public final ScanDetail matchingScanDetail;
+ public WifiConfiguration wCmConfiguredNetwork; // Added to WifiConfigManager.
+
+ PerNetworkSuggestionMatchMetaInfo(@NonNull WifiNetworkSuggestion wifiNetworkSuggestion,
+ @Nullable WifiConfiguration wCmConfiguredNetwork,
+ @NonNull ScanDetail matchingScanDetail) {
+ this.wifiNetworkSuggestion = wifiNetworkSuggestion;
+ this.wCmConfiguredNetwork = wCmConfiguredNetwork;
+ this.matchingScanDetail = matchingScanDetail;
+ }
+ }
+
+ private class PerAppMatchMetaInfo {
+ public final List<PerNetworkSuggestionMatchMetaInfo> networkInfos = new ArrayList<>();
+
+ /**
+ * Add the network suggestion & associated info to this package meta info.
+ */
+ public void put(WifiNetworkSuggestion wifiNetworkSuggestion,
+ WifiConfiguration matchingWifiConfiguration,
+ ScanDetail matchingScanDetail) {
+ networkInfos.add(new PerNetworkSuggestionMatchMetaInfo(
+ wifiNetworkSuggestion, matchingWifiConfiguration, matchingScanDetail));
+ }
+
+ /**
+ * Pick the highest priority networks among the current match info candidates for this
+ * app.
+ */
+ public List<PerNetworkSuggestionMatchMetaInfo> getHighestPriorityNetworks() {
+ // Partition the list to a map of network suggestions keyed in by the priorities.
+ // There can be multiple networks with the same priority, hence a list in the value.
+ Map<Integer, List<PerNetworkSuggestionMatchMetaInfo>> matchedNetworkInfosPerPriority =
+ networkInfos.stream()
+ .collect(Collectors.toMap(
+ e -> e.wifiNetworkSuggestion.wifiConfiguration.priority,
+ e -> Arrays.asList(e),
+ (v1, v2) -> { // concatenate networks with the same priority.
+ List<PerNetworkSuggestionMatchMetaInfo> concatList =
+ new ArrayList<>(v1);
+ concatList.addAll(v2);
+ return concatList;
+ }));
+ if (matchedNetworkInfosPerPriority.isEmpty()) { // should never happen.
+ Log.wtf(TAG, "Unexepectedly got empty");
+ return Collections.EMPTY_LIST;
+ }
+ // Return the list associated with the highest priority value.
+ return matchedNetworkInfosPerPriority.get(Collections.max(
+ matchedNetworkInfosPerPriority.keySet()));
+ }
+ }
+
+ private class MatchMetaInfo {
+ private Map<String, PerAppMatchMetaInfo> mAppInfos = new HashMap<>();
+
+ /**
+ * Add all the network suggestion & associated info.
+ */
+ public void putAll(Set<WifiNetworkSuggestion> wifiNetworkSuggestions,
+ WifiConfiguration wCmConfiguredNetwork,
+ ScanDetail matchingScanDetail) {
+ // Separate the suggestions into buckets for each app to allow sorting based on
+ // priorities set by app.
+ for (WifiNetworkSuggestion wifiNetworkSuggestion : wifiNetworkSuggestions) {
+ PerAppMatchMetaInfo appInfo = mAppInfos.computeIfAbsent(
+ wifiNetworkSuggestion.suggestorPackageName, k -> new PerAppMatchMetaInfo());
+ appInfo.put(wifiNetworkSuggestion, wCmConfiguredNetwork, matchingScanDetail);
+ }
+ }
+
+ /**
+ * Are there any matched candidates?
+ */
+ public boolean isEmpty() {
+ return mAppInfos.isEmpty();
+ }
+
+ /**
+ * Find all the connectable networks and pick the best network among the current match info
+ * candidates.
+ *
+ * Among the highest priority suggestions from different packages, choose the suggestion
+ * with the highest RSSI.
+ * Note: This should need to be replaced by a more sophisticated algorithm.
+ */
+ public PerNetworkSuggestionMatchMetaInfo findConnectableNetworksAndPickBest(
+ @NonNull OnConnectableListener onConnectableListener) {
+ List<PerNetworkSuggestionMatchMetaInfo> allMatchedNetworkInfos = new ArrayList<>();
+ for (PerAppMatchMetaInfo appInfo : mAppInfos.values()) {
+ List<PerNetworkSuggestionMatchMetaInfo> matchedNetworkInfos =
+ appInfo.getHighestPriorityNetworks();
+ for (PerNetworkSuggestionMatchMetaInfo matchedNetworkInfo : matchedNetworkInfos) {
+ // if the network does not already exist in WifiConfigManager, add now.
+ if (matchedNetworkInfo.wCmConfiguredNetwork == null) {
+ matchedNetworkInfo.wCmConfiguredNetwork = addCandidateToWifiConfigManager(
+ matchedNetworkInfo.wifiNetworkSuggestion.wifiConfiguration,
+ matchedNetworkInfo.wifiNetworkSuggestion.suggestorUid,
+ matchedNetworkInfo.wifiNetworkSuggestion.suggestorPackageName);
+ if (matchedNetworkInfo.wCmConfiguredNetwork == null) continue;
+ mLocalLog.log(String.format("network suggestion candidate %s (new)",
+ WifiNetworkSelector.toNetworkString(
+ matchedNetworkInfo.wCmConfiguredNetwork)));
+ } else {
+ mLocalLog.log(String.format("network suggestion candidate %s (existing)",
+ WifiNetworkSelector.toNetworkString(
+ matchedNetworkInfo.wCmConfiguredNetwork)));
+ }
+ allMatchedNetworkInfos.add(matchedNetworkInfo);
+ // Invoke onConnectable for the best networks from each app.
+ onConnectableListener.onConnectable(
+ matchedNetworkInfo.matchingScanDetail,
+ matchedNetworkInfo.wCmConfiguredNetwork,
+ 0);
+ }
+ }
+ PerNetworkSuggestionMatchMetaInfo networkInfo = allMatchedNetworkInfos
+ .stream()
+ .max(Comparator.comparing(e -> e.matchingScanDetail.getScanResult().level))
+ .orElse(null);
+ if (networkInfo == null) { // should never happen.
+ Log.wtf(TAG, "Unexepectedly got null");
+ return null;
+ }
+ return networkInfo;
+ }
+ }
+
}
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
index 7f61ed9..97f390f 100644
--- a/service/java/com/android/server/wifi/OpenNetworkNotifier.java
+++ b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
@@ -21,6 +21,7 @@
import android.provider.Settings;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.server.wifi.nano.WifiMetricsProto;
/**
* This class handles the "open wi-fi network available" notification
@@ -44,7 +45,9 @@
ClientModeImpl clientModeImpl,
ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder) {
super(TAG, STORE_DATA_IDENTIFIER, TOGGLE_SETTINGS_NAME,
- SystemMessage.NOTE_NETWORK_AVAILABLE, context, looper, framework, clock,
+ SystemMessage.NOTE_NETWORK_AVAILABLE,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE,
+ context, looper, framework, clock,
wifiMetrics, wifiConfigManager, wifiConfigStore, clientModeImpl,
connectToNetworkNotificationBuilder);
}
diff --git a/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java b/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java
index 0d6af75..6622269 100644
--- a/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java
@@ -154,7 +154,7 @@
// Track scan results for open wifi networks
if (configuredNetwork == null) {
if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) {
- scoreTracker.trackUntrustedCandidate(scanResult);
+ scoreTracker.trackUntrustedCandidate(scanDetail);
}
continue;
}
@@ -184,7 +184,8 @@
onConnectableListener.onConnectable(scanDetail, configuredNetwork, 0);
}
- return scoreTracker.getCandidateConfiguration();
+
+ return scoreTracker.getCandidateConfiguration(onConnectableListener);
}
/** Used to track the network with the highest score. */
@@ -198,6 +199,7 @@
private WifiConfiguration mEphemeralConfig;
private WifiConfiguration mSavedConfig;
private ScanResult mScanResultCandidate;
+ private ScanDetail mScanDetailCandidate;
/**
* Returns the available external network score or null if no score is available.
@@ -219,12 +221,14 @@
return null;
}
- /** Track an untrusted {@link ScanResult}. */
- void trackUntrustedCandidate(ScanResult scanResult) {
+ /** Track an untrusted {@link ScanDetail}. */
+ void trackUntrustedCandidate(ScanDetail scanDetail) {
+ ScanResult scanResult = scanDetail.getScanResult();
Integer score = getNetworkScore(scanResult, false /* isCurrentNetwork */);
if (score != null && score > mHighScore) {
mHighScore = score;
mScanResultCandidate = scanResult;
+ mScanDetailCandidate = scanDetail;
mBestCandidateType = EXTERNAL_SCORED_UNTRUSTED_NETWORK;
debugLog(WifiNetworkSelector.toScanId(scanResult)
+ " becomes the new untrusted candidate.");
@@ -241,6 +245,7 @@
if (score != null && score > mHighScore) {
mHighScore = score;
mScanResultCandidate = scanResult;
+ mScanDetailCandidate = null;
mBestCandidateType = EXTERNAL_SCORED_UNTRUSTED_NETWORK;
mEphemeralConfig = config;
mWifiConfigManager.setNetworkCandidateScanResult(config.networkId, scanResult, 0);
@@ -262,6 +267,7 @@
mHighScore = score;
mSavedConfig = config;
mScanResultCandidate = scanResult;
+ mScanDetailCandidate = null;
mBestCandidateType = EXTERNAL_SCORED_SAVED_NETWORK;
mWifiConfigManager.setNetworkCandidateScanResult(config.networkId, scanResult, 0);
debugLog(WifiNetworkSelector.toScanId(scanResult)
@@ -271,7 +277,8 @@
/** Returns the best candidate network tracked by this {@link ScoreTracker}. */
@Nullable
- WifiConfiguration getCandidateConfiguration() {
+ WifiConfiguration getCandidateConfiguration(
+ @NonNull OnConnectableListener onConnectableListener) {
int candidateNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
switch (mBestCandidateType) {
case ScoreTracker.EXTERNAL_SCORED_UNTRUSTED_NETWORK:
@@ -305,6 +312,11 @@
break;
}
candidateNetworkId = result.getNetworkId();
+ if (mScanDetailCandidate == null) {
+ // This should never happen, but if it does, WNS will log a wtf.
+ // A message here might help with the diagnosis.
+ Log.e(TAG, "mScanDetailCandidate is null!");
+ }
mWifiConfigManager.setNetworkCandidateScanResult(candidateNetworkId,
mScanResultCandidate, 0);
mLocalLog.log(String.format("new ephemeral candidate %s network ID:%d, "
@@ -324,7 +336,13 @@
mLocalLog.log("ScoredNetworkEvaluator did not see any good candidates.");
break;
}
- return mWifiConfigManager.getConfiguredNetwork(candidateNetworkId);
+ WifiConfiguration ans = mWifiConfigManager.getConfiguredNetwork(
+ candidateNetworkId);
+ if (ans != null && mScanDetailCandidate != null) {
+ // This is a newly created config, so we need to call onConnectable.
+ onConnectableListener.onConnectable(mScanDetailCandidate, ans, 0);
+ }
+ return ans;
}
}
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 92bec08..9332c59 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -16,8 +16,6 @@
package com.android.server.wifi;
-import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX;
-
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.admin.DeviceAdminInfo;
@@ -128,7 +126,6 @@
1, // threshold for DISABLED_NO_INTERNET_TEMPORARY
1, // threshold for DISABLED_WPS_START
6, // threshold for DISABLED_TLS_VERSION_MISMATCH
- 1, // threshold for DISABLED_BY_WIFI_MANAGER_DISCONNECT
1, // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS
1, // threshold for DISABLED_NO_INTERNET_PERMANENT
1, // threshold for DISABLED_BY_WIFI_MANAGER
@@ -153,7 +150,6 @@
10 * 60 * 1000, // threshold for DISABLED_NO_INTERNET_TEMPORARY
0 * 60 * 1000, // threshold for DISABLED_WPS_START
Integer.MAX_VALUE, // threshold for DISABLED_TLS_VERSION
- 1 * 60 * 60 * 1000, // threshold for DISABLED_BY_WIFI_MANAGER_DISCONNECT
Integer.MAX_VALUE, // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS
Integer.MAX_VALUE, // threshold for DISABLED_NO_INTERNET_PERMANENT
Integer.MAX_VALUE, // threshold for DISABLED_BY_WIFI_MANAGER
@@ -940,11 +936,7 @@
internalConfig.allowedGroupManagementCiphers =
(BitSet) externalConfig.allowedGroupManagementCiphers.clone();
}
- if (externalConfig.allowedSuiteBCiphers != null
- && !externalConfig.allowedSuiteBCiphers.isEmpty()) {
- internalConfig.allowedSuiteBCiphers =
- (BitSet) externalConfig.allowedSuiteBCiphers.clone();
- }
+ // allowedSuiteBCiphers is set internally according to the certificate type
// Copy over the |IpConfiguration| parameters if set.
if (externalConfig.getIpConfiguration() != null) {
@@ -1068,7 +1060,7 @@
*/
private void updateRandomizedMacAddress(WifiConfiguration config) {
// Update randomized MAC address according to stored map
- final String key = config.configKey();
+ final String key = config.getSsidAndSecurityTypeString();
// If the key is not found in the current store, then it means this network has never been
// seen before. So add it to store.
if (!mRandomizedMacAddressMapping.containsKey(key)) {
@@ -1175,8 +1167,8 @@
newInternalConfig) && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)
&& !mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) {
Log.e(TAG, "UID " + uid + " does not have permission to modify MAC randomization "
- + "Settings " + config.configKey() + ". Must have NETWORK_SETTINGS or"
- + "NETWORK_SETUP_WIZARD.");
+ + "Settings " + config.getSsidAndSecurityTypeString() + ". Must have "
+ + "NETWORK_SETTINGS or NETWORK_SETUP_WIZARD.");
return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
}
@@ -1568,7 +1560,7 @@
if (reason == NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
setNetworkSelectionEnabled(config);
setNetworkStatus(config, WifiConfiguration.Status.ENABLED);
- } else if (reason < NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX) {
+ } else if (reason < NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) {
setNetworkSelectionTemporarilyDisabled(config, reason);
} else {
setNetworkSelectionPermanentlyDisabled(config, reason);
@@ -2796,7 +2788,8 @@
if (TelephonyUtil.isSimConfig(config)) {
Pair<String, String> currentIdentity =
TelephonyUtil.getSimIdentity(mTelephonyManager,
- new TelephonyUtil(), config);
+ new TelephonyUtil(), config,
+ mWifiInjector.getCarrierNetworkConfig());
if (mVerboseLoggingEnabled) {
Log.d(TAG, "New identity for config " + config + ": " + currentIdentity);
}
@@ -2878,6 +2871,8 @@
Log.w(TAG, "User switch before store is read!");
mConfiguredNetworks.setNewUser(userId);
mCurrentUserId = userId;
+ // Reset any state from previous user unlock.
+ mDeferredUserUnlockRead = false;
// Cannot read data from new user's CE store file before they log-in.
mPendingUnlockStoreRead = true;
return new HashSet<>();
@@ -2912,12 +2907,16 @@
if (mVerboseLoggingEnabled) {
Log.v(TAG, "Handling user unlock for " + userId);
}
+ if (userId != mCurrentUserId) {
+ Log.e(TAG, "Ignore user unlock for non current user " + userId);
+ return;
+ }
if (mPendingStoreRead) {
Log.w(TAG, "Ignore user unlock until store is read!");
mDeferredUserUnlockRead = true;
return;
}
- if (userId == mCurrentUserId && mPendingUnlockStoreRead) {
+ if (mPendingUnlockStoreRead) {
handleUserUnlockOrSwitch(mCurrentUserId);
}
}
@@ -3041,7 +3040,7 @@
*/
private void generateRandomizedMacAddresses() {
for (WifiConfiguration config : getInternalConfiguredNetworks()) {
- mRandomizedMacAddressMapping.put(config.configKey(),
+ mRandomizedMacAddressMapping.put(config.getSsidAndSecurityTypeString(),
config.getOrCreateRandomizedMacAddress().toString());
}
}
diff --git a/service/java/com/android/server/wifi/WifiCountryCode.java b/service/java/com/android/server/wifi/WifiCountryCode.java
index 41a366d..a669508 100644
--- a/service/java/com/android/server/wifi/WifiCountryCode.java
+++ b/service/java/com/android/server/wifi/WifiCountryCode.java
@@ -21,6 +21,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.Locale;
/**
@@ -34,6 +36,7 @@
private final WifiNative mWifiNative;
private boolean DBG = false;
private boolean mReady = false;
+ private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
/** config option that indicate whether or not to reset country code to default when
* cellular radio indicates country code loss
@@ -41,7 +44,10 @@
private boolean mRevertCountryCodeOnCellularLoss;
private String mDefaultCountryCode = null;
private String mTelephonyCountryCode = null;
- private String mCurrentCountryCode = null;
+ private String mDriverCountryCode = null;
+ private String mTelephonyCountryTimestamp = null;
+ private String mDriverCountryTimestamp = null;
+ private String mReadyTimestamp = null;
public WifiCountryCode(
WifiNative wifiNative,
@@ -58,14 +64,11 @@
Log.w(TAG, "config_wifi_revert_country_code_on_cellular_loss is set, "
+ "but there is no default country code.");
mRevertCountryCodeOnCellularLoss = false;
- return;
}
}
- if (mRevertCountryCodeOnCellularLoss) {
- Log.d(TAG, "Country code will be reverted to " + mDefaultCountryCode
- + " on MCC loss");
- }
+ Log.d(TAG, "mDefaultCountryCode " + mDefaultCountryCode
+ + " mRevertCountryCodeOnCellularLoss " + mRevertCountryCodeOnCellularLoss);
}
/**
@@ -85,7 +88,7 @@
* phone default one.
*/
public synchronized void airplaneModeEnabled() {
- if (DBG) Log.d(TAG, "Airplane Mode Enabled");
+ Log.d(TAG, "Airplane Mode Enabled");
// Airplane mode is enabled, we need to reset the country code to phone default.
// Country code will be set upon when wpa_supplicant starts next time.
mTelephonyCountryCode = null;
@@ -98,8 +101,8 @@
* started but not yet L2 connected.
*/
public synchronized void setReadyForChange(boolean ready) {
- if (DBG) Log.d(TAG, "Set ready: " + ready);
mReady = ready;
+ mReadyTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
// We are ready to set country code now.
// We need to post pending country code request.
if (mReady) {
@@ -115,11 +118,13 @@
* @return Returns true if the country code passed in is acceptable.
*/
public synchronized boolean setCountryCode(String countryCode) {
- if (DBG) Log.d(TAG, "Receive set country code request: " + countryCode);
+ Log.d(TAG, "Receive set country code request: " + countryCode);
+ mTelephonyCountryTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
+
// Empty country code.
if (TextUtils.isEmpty(countryCode)) {
if (mRevertCountryCodeOnCellularLoss) {
- if (DBG) Log.d(TAG, "Received empty country code, reset to default country code");
+ Log.d(TAG, "Received empty country code, reset to default country code");
mTelephonyCountryCode = null;
}
} else {
@@ -129,7 +134,10 @@
// set once wpa_supplicant is ready.
if (mReady) {
updateCountryCode();
+ } else {
+ Log.d(TAG, "skip update supplicant not ready yet");
}
+
return true;
}
@@ -143,7 +151,7 @@
* Returns null if no Country Code was sent to driver.
*/
public synchronized String getCountryCodeSentToDriver() {
- return mCurrentCountryCode;
+ return mDriverCountryCode;
}
/**
@@ -161,20 +169,21 @@
* Method to dump the current state of this WifiCounrtyCode object.
*/
public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mCurrentCountryCode != null) {
- pw.println("CountryCode sent to driver: " + mCurrentCountryCode);
- } else {
- if (pickCountryCode() != null) {
- pw.println("CountryCode: " + pickCountryCode() + " was not sent to driver");
- } else {
- pw.println("CountryCode was not initialized");
- }
- }
+
+ pw.println("mRevertCountryCodeOnCellularLoss: " + mRevertCountryCodeOnCellularLoss);
+ pw.println("mDefaultCountryCode: " + mDefaultCountryCode);
+ pw.println("mDriverCountryCode: " + mDriverCountryCode);
+ pw.println("mTelephonyCountryCode: " + mTelephonyCountryCode);
+ pw.println("mTelephonyCountryTimestamp: " + mTelephonyCountryTimestamp);
+ pw.println("mDriverCountryTimestamp: " + mDriverCountryTimestamp);
+ pw.println("mReadyTimestamp: " + mReadyTimestamp);
+ pw.println("mReady: " + mReady);
}
private void updateCountryCode() {
- if (DBG) Log.d(TAG, "Update country code");
String country = pickCountryCode();
+ Log.d(TAG, "updateCountryCode to " + country);
+
// We do not check if the country code equals the current one.
// There are two reasons:
// 1. Wpa supplicant may silently modify the country code.
@@ -200,9 +209,10 @@
}
private boolean setCountryCodeNative(String country) {
+ mDriverCountryTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
if (mWifiNative.setCountryCode(mWifiNative.getClientInterfaceName(), country)) {
Log.d(TAG, "Succeeded to set country code to: " + country);
- mCurrentCountryCode = country;
+ mDriverCountryCode = country;
return true;
}
Log.d(TAG, "Failed to set country code to: " + country);
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index a5425db..b288ccb 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -530,8 +530,6 @@
}
private boolean flushDump(int errorCode) {
- if (mBuildProperties.isUserBuild()) return false;
-
if (errorCode == REPORT_REASON_USER_ACTION) return false;
long currentTime = mClock.getWallClockMillis();
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 7938108..49f8c85 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -151,6 +151,7 @@
private final DppManager mDppManager;
private final LinkProbeManager mLinkProbeManager;
private final IpMemoryStore mIpMemoryStore;
+ private final CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector;
public WifiInjector(Context context) {
if (context == null) {
@@ -194,8 +195,10 @@
RttMetrics rttMetrics = new RttMetrics(mClock);
mWifiP2pMetrics = new WifiP2pMetrics(mClock);
mDppMetrics = new DppMetrics();
+ mCellularLinkLayerStatsCollector = new CellularLinkLayerStatsCollector(mContext);
mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, clientModeImplLooper,
- awareMetrics, rttMetrics, new WifiPowerMetrics(), mWifiP2pMetrics, mDppMetrics);
+ awareMetrics, rttMetrics, new WifiPowerMetrics(), mWifiP2pMetrics, mDppMetrics,
+ mCellularLinkLayerStatsCollector);
// Modules interacting with Native.
mWifiMonitor = new WifiMonitor(this);
mHalDeviceManager = new HalDeviceManager(mClock);
@@ -251,7 +254,7 @@
new Handler(clientModeImplLooper));
mWifiMetrics.setScoringParams(mScoringParams);
mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiScoreCard, mScoringParams,
- mWifiConfigManager, mClock, mConnectivityLocalLog, mWifiMetrics);
+ mWifiConfigManager, mClock, mConnectivityLocalLog, mWifiMetrics, mWifiNative);
CompatibilityScorer compatibilityScorer = new CompatibilityScorer(mScoringParams);
mWifiNetworkSelector.registerCandidateScorer(compatibilityScorer);
ScoreCardBasedScorer scoreCardBasedScorer = new ScoreCardBasedScorer(mScoringParams);
@@ -316,7 +319,7 @@
mWifiConfigStore, mWifiNetworkSuggestionsManager, mWifiMetrics.getWakeupMetrics(),
this, mFrameworkFacade, mClock);
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService(),
- mClientModeImpl, mFrameworkFacade, clientModeImplLooper);
+ mClientModeImpl, mFrameworkFacade, clientModeImplLooper, mClock, mWifiMetrics);
mWifiController = new WifiController(mContext, mClientModeImpl, clientModeImplLooper,
mSettingsStore, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade,
mActiveModeWarden);
@@ -481,6 +484,10 @@
return mPasspointManager;
}
+ public CarrierNetworkConfig getCarrierNetworkConfig() {
+ return mCarrierNetworkConfig;
+ }
+
public WakeupController getWakeupController() {
return mWakeupController;
}
diff --git a/service/java/com/android/server/wifi/WifiKeyStore.java b/service/java/com/android/server/wifi/WifiKeyStore.java
index 3054fe5..a22be9b 100644
--- a/service/java/com/android/server/wifi/WifiKeyStore.java
+++ b/service/java/com/android/server/wifi/WifiKeyStore.java
@@ -26,10 +26,13 @@
import android.util.ArraySet;
import android.util.Log;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.security.Key;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
@@ -220,26 +223,51 @@
* @param config Config corresponding to the network.
*/
public void removeKeys(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- // a valid client certificate is configured
- if (!TextUtils.isEmpty(client)) {
- if (mVerboseLoggingEnabled) Log.d(TAG, "removing client private key and user cert");
- mKeyStore.delete(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
- mKeyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
+ // Do not remove keys that were manually installed by the user
+ if (config.isAppInstalledDeviceKeyAndCert()) {
+ String client = config.getClientCertificateAlias();
+ // a valid client certificate is configured
+ if (!TextUtils.isEmpty(client)) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "removing client private key and user cert");
+ }
+ mKeyStore.delete(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
+ mKeyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
+ }
}
- String[] aliases = config.getCaCertificateAliases();
- // a valid ca certificate is configured
- if (aliases != null) {
- for (String ca : aliases) {
- if (!TextUtils.isEmpty(ca)) {
- if (mVerboseLoggingEnabled) Log.d(TAG, "removing CA cert: " + ca);
- mKeyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
+ // Do not remove CA certs that were manually installed by the user
+ if (config.isAppInstalledCaCert()) {
+ String[] aliases = config.getCaCertificateAliases();
+ // a valid ca certificate is configured
+ if (aliases != null) {
+ for (String ca : aliases) {
+ if (!TextUtils.isEmpty(ca)) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "removing CA cert: " + ca);
+ }
+ mKeyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
+ }
}
}
}
}
+
+ /**
+ * @param certData byte array of the certificate
+ */
+ private X509Certificate buildCACertificate(byte[] certData) {
+ try {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ InputStream inputStream = new ByteArrayInputStream(certData);
+ X509Certificate caCertificateX509 = (X509Certificate) certificateFactory
+ .generateCertificate(inputStream);
+ return caCertificateX509;
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
/**
* Update/Install keys for given enterprise network.
*
@@ -267,6 +295,61 @@
return false;
}
}
+
+ // For WPA3-Enterprise 192-bit networks, set the SuiteBCipher field based on the
+ // CA certificate type. Suite-B requires SHA384, reject other certs.
+ if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) {
+ // Read the first CA certificate, and initialize
+ byte[] certData = mKeyStore.get(
+ Credentials.CA_CERTIFICATE + config.enterpriseConfig.getCaCertificateAlias(),
+ android.os.Process.WIFI_UID);
+
+ if (certData == null) {
+ Log.e(TAG, "Failed reading CA certificate for Suite-B");
+ return false;
+ }
+
+ X509Certificate x509CaCert = buildCACertificate(certData);
+
+ if (x509CaCert != null) {
+ String sigAlgOid = x509CaCert.getSigAlgOID();
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Signature algorithm: " + sigAlgOid);
+ }
+ config.allowedSuiteBCiphers.clear();
+
+ // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates
+ // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192
+ // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term
+ // Suite-B was already coined in the IEEE 802.11-2016 specification for
+ // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates
+ // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally
+ // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments,
+ // we are supporting both types here.
+ if (sigAlgOid.equals("1.2.840.113549.1.1.12")) {
+ // sha384WithRSAEncryption
+ config.allowedSuiteBCiphers.set(
+ WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Selecting Suite-B RSA");
+ }
+ } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) {
+ // ecdsa-with-SHA384
+ config.allowedSuiteBCiphers.set(
+ WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Selecting Suite-B ECDSA");
+ }
+ } else {
+ Log.e(TAG, "Invalid CA certificate type for Suite-B: "
+ + sigAlgOid);
+ return false;
+ }
+ } else {
+ Log.e(TAG, "Invalid CA certificate for Suite-B");
+ return false;
+ }
+ }
return true;
}
}
diff --git a/service/java/com/android/server/wifi/WifiLockManager.java b/service/java/com/android/server/wifi/WifiLockManager.java
index 7354182..3d4ceb1 100644
--- a/service/java/com/android/server/wifi/WifiLockManager.java
+++ b/service/java/com/android/server/wifi/WifiLockManager.java
@@ -56,12 +56,14 @@
private boolean mVerboseLoggingEnabled = false;
+ private final Clock mClock;
private final Context mContext;
private final IBatteryStats mBatteryStats;
private final FrameworkFacade mFrameworkFacade;
private final ClientModeImpl mClientModeImpl;
private final ActivityManager mActivityManager;
private final ClientModeImplInterfaceHandler mCmiIfaceHandler;
+ private final WifiMetrics mWifiMetrics;
private WifiAsyncChannel mClientModeImplChannel;
private final List<WifiLock> mWifiLocks = new ArrayList<>();
@@ -80,9 +82,11 @@
private int mFullHighPerfLocksReleased;
private int mFullLowLatencyLocksAcquired;
private int mFullLowLatencyLocksReleased;
+ private long mCurrentSessionStartTimeMs;
WifiLockManager(Context context, IBatteryStats batteryStats,
- ClientModeImpl clientModeImpl, FrameworkFacade frameworkFacade, Looper looper) {
+ ClientModeImpl clientModeImpl, FrameworkFacade frameworkFacade, Looper looper,
+ Clock clock, WifiMetrics wifiMetrics) {
mContext = context;
mBatteryStats = batteryStats;
mClientModeImpl = clientModeImpl;
@@ -90,6 +94,8 @@
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mCmiIfaceHandler = new ClientModeImplInterfaceHandler(looper);
mCurrentOpMode = WifiManager.WIFI_MODE_NO_LOCKS_HELD;
+ mClock = clock;
+ mWifiMetrics = wifiMetrics;
// Register for UID fg/bg transitions
registerUidImportanceTransitions();
@@ -540,6 +546,8 @@
switch(wifiLock.mMode) {
case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
++mFullHighPerfLocksReleased;
+ mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
+ mClock.getElapsedSinceBootMillis() - wifiLock.getAcqTimestamp());
// Stop blaming only if blaming was set before (conditions are met).
// This is to avoid calling the api unncessarily, since this API is
// reference counted in batteryStats and statsd
@@ -550,6 +558,8 @@
case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
removeWsFromLlWatchList(wifiLock.getWorkSource());
++mFullLowLatencyLocksReleased;
+ mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
+ mClock.getElapsedSinceBootMillis() - wifiLock.getAcqTimestamp());
break;
default:
// Do nothing
@@ -581,6 +591,8 @@
Slog.e(TAG, "Failed to reset the OpMode from hi-perf to Normal");
return false;
}
+ mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
+ mClock.getElapsedSinceBootMillis() - mCurrentSessionStartTimeMs);
break;
case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
@@ -588,6 +600,8 @@
Slog.e(TAG, "Failed to reset the OpMode from low-latency to Normal");
return false;
}
+ mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
+ mClock.getElapsedSinceBootMillis() - mCurrentSessionStartTimeMs);
break;
case WifiManager.WIFI_MODE_NO_LOCKS_HELD:
@@ -606,6 +620,7 @@
Slog.e(TAG, "Failed to set the OpMode to hi-perf");
return false;
}
+ mCurrentSessionStartTimeMs = mClock.getElapsedSinceBootMillis();
break;
case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
@@ -613,6 +628,7 @@
Slog.e(TAG, "Failed to set the OpMode to low-latency");
return false;
}
+ mCurrentSessionStartTimeMs = mClock.getElapsedSinceBootMillis();
break;
case WifiManager.WIFI_MODE_NO_LOCKS_HELD:
@@ -650,20 +666,32 @@
private boolean setLowLatencyMode(boolean enabled) {
int lowLatencySupport = getLowLatencyModeSupport();
- if (lowLatencySupport == LOW_LATENCY_SUPPORTED) {
- return mClientModeImpl.setLowLatencyMode(enabled);
- } else if (lowLatencySupport == LOW_LATENCY_NOT_SUPPORTED) {
- // Since low-latency mode is not supported, use power save instead
- // Note: low-latency mode enabled ==> power-save disabled
- if (mVerboseLoggingEnabled) {
- Slog.d(TAG, "low-latency is not supported, using power-save instead");
- }
-
- return mClientModeImpl.setPowerSave(!enabled);
- } else {
- // Support undefined, no need to attempt either functions
+ if (lowLatencySupport == LOW_LATENCY_SUPPORT_UNDEFINED) {
+ // Support undefined, no action is taken
return false;
}
+
+ if (lowLatencySupport == LOW_LATENCY_SUPPORTED) {
+ if (!mClientModeImpl.setLowLatencyMode(enabled)) {
+ Slog.e(TAG, "Failed to set low latency mode");
+ return false;
+ }
+
+ if (!mClientModeImpl.setPowerSave(!enabled)) {
+ Slog.e(TAG, "Failed to set power save mode");
+ // Revert the low latency mode
+ mClientModeImpl.setLowLatencyMode(!enabled);
+ return false;
+ }
+ } else if (lowLatencySupport == LOW_LATENCY_NOT_SUPPORTED) {
+ // Only set power save mode
+ if (!mClientModeImpl.setPowerSave(!enabled)) {
+ Slog.e(TAG, "Failed to set power save mode");
+ return false;
+ }
+ }
+
+ return true;
}
private synchronized WifiLock findLockByBinder(IBinder binder) {
@@ -810,6 +838,7 @@
IBinder mBinder;
int mMode;
WorkSource mWorkSource;
+ long mAcqTimestamp;
WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) {
mTag = tag;
@@ -817,6 +846,7 @@
mUid = Binder.getCallingUid();
mMode = lockMode;
mWorkSource = ws;
+ mAcqTimestamp = mClock.getElapsedSinceBootMillis();
try {
mBinder.linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -836,6 +866,10 @@
return mBinder;
}
+ protected long getAcqTimestamp() {
+ return mAcqTimestamp;
+ }
+
public void binderDied() {
releaseLock(mBinder);
}
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 077d3db..d70fa30 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -38,6 +38,7 @@
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Base64;
import android.util.Log;
@@ -67,6 +68,7 @@
import com.android.server.wifi.nano.WifiMetricsProto.StaEvent.ConfigInfo;
import com.android.server.wifi.nano.WifiMetricsProto.WifiIsUnusableEvent;
import com.android.server.wifi.nano.WifiMetricsProto.WifiLinkLayerUsageStats;
+import com.android.server.wifi.nano.WifiMetricsProto.WifiLockStats;
import com.android.server.wifi.nano.WifiMetricsProto.WifiNetworkRequestApiLog;
import com.android.server.wifi.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog;
import com.android.server.wifi.nano.WifiMetricsProto.WifiUsabilityStats;
@@ -123,7 +125,7 @@
private static final int MIN_WIFI_SCORE = 0;
private static final int MAX_WIFI_SCORE = NetworkAgent.WIFI_BASE_SCORE;
private static final int MIN_WIFI_USABILITY_SCORE = 0; // inclusive
- private static final int MAX_WIFI_USABILITY_SCORE = 60; // inclusive
+ private static final int MAX_WIFI_USABILITY_SCORE = 100; // inclusive
@VisibleForTesting
static final int LOW_WIFI_SCORE = 50; // Mobile data score
@VisibleForTesting
@@ -150,7 +152,7 @@
private static final int WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED_DEFAULT = 1; // 1 = true
private static final int WIFI_LINK_SPEED_METRICS_ENABLED_DEFAULT = 1; // 1 = true
// Max number of WifiUsabilityStatsEntry elements to store in the ringbuffer.
- public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 20;
+ public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 40;
// Max number of WifiUsabilityStats elements to store for each type.
public static final int MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE = 10;
// Max number of WifiUsabilityStats per labeled type to upload to server
@@ -362,6 +364,19 @@
{5, 20, 50, 100, 500};
private final IntHistogram mWifiNetworkSuggestionApiListSizeHistogram =
new IntHistogram(NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS);
+ private final WifiLockStats mWifiLockStats = new WifiLockStats();
+ private static final int[] WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS =
+ {1, 10, 60, 600, 3600};
+
+ private final IntHistogram mWifiLockHighPerfAcqDurationSecHistogram =
+ new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
+ private final IntHistogram mWifiLockLowLatencyAcqDurationSecHistogram =
+ new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
+
+ private final IntHistogram mWifiLockHighPerfActiveSessionDurationSecHistogram =
+ new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
+ private final IntHistogram mWifiLockLowLatencyActiveSessionDurationSecHistogram =
+ new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
/**
* (experiment1Id, experiment2Id) =>
@@ -370,6 +385,14 @@
private Map<Pair<Integer, Integer>, NetworkSelectionExperimentResults>
mNetworkSelectionExperimentPairNumChoicesCounts = new ArrayMap<>();
+ private final CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector;
+
+ /**
+ * Tracks the nominator for each network (i.e. which entity made the suggestion to connect).
+ * This object should not be cleared.
+ */
+ private final SparseIntArray mNetworkIdToNominatorId = new SparseIntArray();
+
@VisibleForTesting
static class NetworkSelectionExperimentResults {
public static final int MAX_CHOICES = 10;
@@ -641,8 +664,8 @@
case WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED:
sb.append("NOMINATOR_EXTERNAL_SCORED");
break;
- case WifiMetricsProto.ConnectionEvent.NOMINATOR_NETREC:
- sb.append("NOMINATOR_NETREC");
+ case WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER:
+ sb.append("NOMINATOR_SPECIFIER");
break;
case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE:
sb.append("NOMINATOR_SAVED_USER_CONNECT_CHOICE");
@@ -682,7 +705,8 @@
public WifiMetrics(Context context, FrameworkFacade facade, Clock clock, Looper looper,
WifiAwareMetrics awareMetrics, RttMetrics rttMetrics,
WifiPowerMetrics wifiPowerMetrics, WifiP2pMetrics wifiP2pMetrics,
- DppMetrics dppMetrics) {
+ DppMetrics dppMetrics,
+ CellularLinkLayerStatsCollector cellularLinkLayerStatsCollector) {
mContext = context;
mFacade = facade;
mClock = clock;
@@ -695,6 +719,7 @@
mWifiPowerMetrics = wifiPowerMetrics;
mWifiP2pMetrics = wifiP2pMetrics;
mDppMetrics = dppMetrics;
+ mCellularLinkLayerStatsCollector = cellularLinkLayerStatsCollector;
loadSettings();
mHandler = new Handler(looper) {
public void handleMessage(Message msg) {
@@ -983,26 +1008,9 @@
mCurrentConnectionEvent.mConnectionEvent.useRandomizedMac =
config.macRandomizationSetting
== WifiConfiguration.RANDOMIZATION_PERSISTENT;
- if (config.fromWifiNetworkSpecifier) {
- mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
- WifiMetricsProto.ConnectionEvent.NOMINATOR_NETREC;
- } else if (config.fromWifiNetworkSuggestion) {
- mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
- WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION;
- } else if (config.isPasspoint()) {
- mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
- WifiMetricsProto.ConnectionEvent.NOMINATOR_PASSPOINT;
- } else if (!config.trusted) {
- mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
- WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED;
- } else if (!config.ephemeral) {
- mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
- WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED;
- } else {
- // TODO(b/127452844): populate other nominator fields
- mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
- WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN;
- }
+ mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
+ mNetworkIdToNominatorId.get(config.networkId,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN);
ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
if (candidate != null) {
// Cache the RSSI of the candidate, as the connection event level is updated
@@ -2723,6 +2731,17 @@
pw.println("mWifiNetworkSuggestionApiLog:\n" + mWifiNetworkSuggestionApiLog);
pw.println("mWifiNetworkSuggestionApiMatchSizeHistogram:\n"
+ mWifiNetworkRequestApiMatchSizeHistogram);
+ pw.println("mNetworkIdToNominatorId:\n" + mNetworkIdToNominatorId);
+ pw.println("mWifiLockStats:\n" + mWifiLockStats);
+ pw.println("mWifiLockHighPerfAcqDurationSecHistogram:\n"
+ + mWifiLockHighPerfAcqDurationSecHistogram);
+ pw.println("mWifiLockLowLatencyAcqDurationSecHistogram:\n"
+ + mWifiLockLowLatencyAcqDurationSecHistogram);
+ pw.println("mWifiLockHighPerfActiveSessionDurationSecHistogram:\n"
+ + mWifiLockHighPerfActiveSessionDurationSecHistogram);
+ pw.println("mWifiLockLowLatencyActiveSessionDurationSecHistogram:\n"
+ + mWifiLockLowLatencyActiveSessionDurationSecHistogram);
+
}
}
}
@@ -2759,6 +2778,11 @@
line.append(",rx_link_speed_mbps=" + entry.rxLinkSpeedMbps);
line.append(",seq_num_inside_framework=" + entry.seqNumInsideFramework);
line.append(",is_same_bssid_and_freq=" + entry.isSameBssidAndFreq);
+ line.append(",cellular_data_network_type=" + entry.cellularDataNetworkType);
+ line.append(",cellular_signal_strength_dbm=" + entry.cellularSignalStrengthDbm);
+ line.append(",cellular_signal_strength_db=" + entry.cellularSignalStrengthDb);
+ line.append(",is_same_registered_cell=" + entry.isSameRegisteredCell);
+ line.append(",device_mobility_state=" + entry.deviceMobilityState);
pw.println(line.toString());
}
@@ -3231,6 +3255,20 @@
mWifiNetworkSuggestionApiLog.networkListSizeHistogram =
mWifiNetworkSuggestionApiListSizeHistogram.toProto();
mWifiLogProto.wifiNetworkSuggestionApiLog = mWifiNetworkSuggestionApiLog;
+
+ mWifiLockStats.highPerfLockAcqDurationSecHistogram =
+ mWifiLockHighPerfAcqDurationSecHistogram.toProto();
+
+ mWifiLockStats.lowLatencyLockAcqDurationSecHistogram =
+ mWifiLockLowLatencyAcqDurationSecHistogram.toProto();
+
+ mWifiLockStats.highPerfActiveSessionDurationSecHistogram =
+ mWifiLockHighPerfActiveSessionDurationSecHistogram.toProto();
+
+ mWifiLockStats.lowLatencyActiveSessionDurationSecHistogram =
+ mWifiLockLowLatencyActiveSessionDurationSecHistogram.toProto();
+
+ mWifiLogProto.wifiLockStats = mWifiLockStats;
}
}
@@ -3406,6 +3444,11 @@
mWifiNetworkSuggestionApiLog.clear();
mWifiNetworkRequestApiMatchSizeHistogram.clear();
mWifiNetworkSuggestionApiListSizeHistogram.clear();
+ mWifiLockHighPerfAcqDurationSecHistogram.clear();
+ mWifiLockLowLatencyAcqDurationSecHistogram.clear();
+ mWifiLockHighPerfActiveSessionDurationSecHistogram.clear();
+ mWifiLockLowLatencyActiveSessionDurationSecHistogram.clear();
+ mWifiLockStats.clear();
}
}
@@ -4011,6 +4054,8 @@
break;
case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
break;
+ case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
+ break;
default:
Log.e(TAG, "Unknown WifiIsUnusableEvent: " + triggerType);
return;
@@ -4154,6 +4199,16 @@
wifiUsabilityStatsEntry.rxLinkSpeedMbps = info.getRxLinkSpeedMbps();
wifiUsabilityStatsEntry.isSameBssidAndFreq = isSameBssidAndFreq;
wifiUsabilityStatsEntry.seqNumInsideFramework = mSeqNumInsideFramework;
+ wifiUsabilityStatsEntry.deviceMobilityState = mCurrentDeviceMobilityState;
+
+ CellularLinkLayerStats cls = mCellularLinkLayerStatsCollector.update();
+ if (DBG) Log.v(TAG, "Latest Cellular Link Layer Stats: " + cls);
+ wifiUsabilityStatsEntry.cellularDataNetworkType =
+ parseDataNetworkTypeToProto(cls.getDataNetworkType());
+ wifiUsabilityStatsEntry.cellularSignalStrengthDbm = cls.getSignalStrengthDbm();
+ wifiUsabilityStatsEntry.cellularSignalStrengthDb = cls.getSignalStrengthDb();
+ wifiUsabilityStatsEntry.isSameRegisteredCell = cls.getIsSameRegisteredCell();
+
mWifiUsabilityStatsEntriesList.add(wifiUsabilityStatsEntry);
mWifiUsabilityStatsCounter++;
if (mWifiUsabilityStatsCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) {
@@ -4173,6 +4228,53 @@
}
}
+ private int parseDataNetworkTypeToProto(int cellularDataNetworkType) {
+ switch (cellularDataNetworkType) {
+ case TelephonyManager.NETWORK_TYPE_UNKNOWN:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_UNKNOWN;
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_GSM;
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_CDMA;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_EVDO_0;
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_UMTS;
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_TD_SCDMA;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_LTE;
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_NR;
+ default:
+ Log.e(TAG, "Unknown data network type : " + cellularDataNetworkType);
+ return WifiUsabilityStatsEntry.NETWORK_TYPE_UNKNOWN;
+ }
+ }
+
+ private int parseDataNetworkTypeFromProto(int cellularDataNetworkType) {
+ switch (cellularDataNetworkType) {
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_UNKNOWN:
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_GSM:
+ return TelephonyManager.NETWORK_TYPE_GSM;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_CDMA:
+ return TelephonyManager.NETWORK_TYPE_CDMA;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_EVDO_0:
+ return TelephonyManager.NETWORK_TYPE_EVDO_0;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_UMTS:
+ return TelephonyManager.NETWORK_TYPE_UMTS;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_TD_SCDMA:
+ return TelephonyManager.NETWORK_TYPE_TD_SCDMA;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_LTE:
+ return TelephonyManager.NETWORK_TYPE_LTE;
+ case WifiUsabilityStatsEntry.NETWORK_TYPE_NR:
+ return TelephonyManager.NETWORK_TYPE_NR;
+ default:
+ Log.e(TAG, "Unknown data network type : " + cellularDataNetworkType);
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ }
+ }
/**
* Send Wifi usability stats.
* @param seqNum
@@ -4208,6 +4310,7 @@
probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN;
Log.e(TAG, "Unknown link probe status: " + s.probeStatusSinceLastUpdate);
}
+ int cellularDataNetworkType = parseDataNetworkTypeFromProto(s.cellularDataNetworkType);
return new android.net.wifi.WifiUsabilityStatsEntry(s.timeStampMs, s.rssi,
s.linkSpeedMbps, s.totalTxSuccess, s.totalTxRetries,
s.totalTxBad, s.totalRxSuccess, s.totalRadioOnTimeMs,
@@ -4216,7 +4319,9 @@
s.totalPnoScanTimeMs, s.totalHotspot2ScanTimeMs, s.totalCcaBusyFreqTimeMs,
s.totalRadioOnFreqTimeMs, s.totalBeaconRx, probeStatus,
s.probeElapsedTimeSinceLastUpdateMs, s.probeMcsRateSinceLastUpdate,
- s.rxLinkSpeedMbps
+ s.rxLinkSpeedMbps, cellularDataNetworkType,
+ s.cellularSignalStrengthDbm, s.cellularSignalStrengthDb,
+ s.isSameRegisteredCell
);
}
@@ -4251,6 +4356,11 @@
out.rxLinkSpeedMbps = s.rxLinkSpeedMbps;
out.isSameBssidAndFreq = s.isSameBssidAndFreq;
out.seqNumInsideFramework = s.seqNumInsideFramework;
+ out.cellularDataNetworkType = s.cellularDataNetworkType;
+ out.cellularSignalStrengthDbm = s.cellularSignalStrengthDbm;
+ out.cellularSignalStrengthDb = s.cellularSignalStrengthDb;
+ out.isSameRegisteredCell = s.isSameRegisteredCell;
+ out.deviceMobilityState = s.deviceMobilityState;
return out;
}
@@ -4280,9 +4390,10 @@
// Only add a good event if at least |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
// has passed.
if (mWifiUsabilityStatsListGood.isEmpty()
- || mWifiUsabilityStatsListGood.getLast().stats[0].timeStampMs
+ || mWifiUsabilityStatsListGood.getLast().stats[mWifiUsabilityStatsListGood
+ .getLast().stats.length - 1].timeStampMs
+ MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS
- < mWifiUsabilityStatsEntriesList.get(0).timeStampMs) {
+ < mWifiUsabilityStatsEntriesList.getLast().timeStampMs) {
while (mWifiUsabilityStatsListGood.size()
>= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
mWifiUsabilityStatsListGood.remove(
@@ -4295,9 +4406,10 @@
// Only add a bad event if at least |MIN_DATA_STALL_WAIT_MS|
// has passed.
if (mWifiUsabilityStatsListBad.isEmpty()
- || (mWifiUsabilityStatsListBad.getLast().stats[0].timeStampMs
+ || (mWifiUsabilityStatsListBad.getLast().stats[mWifiUsabilityStatsListBad
+ .getLast().stats.length - 1].timeStampMs
+ MIN_DATA_STALL_WAIT_MS
- < mWifiUsabilityStatsEntriesList.get(0).timeStampMs)) {
+ < mWifiUsabilityStatsEntriesList.getLast().timeStampMs)) {
while (mWifiUsabilityStatsListBad.size()
>= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
mWifiUsabilityStatsListBad.remove(
@@ -4640,4 +4752,55 @@
}
}
}
+
+ /**
+ * Sets the nominator for a network (i.e. which entity made the suggestion to connect)
+ * @param networkId the ID of the network, from its {@link WifiConfiguration}
+ * @param nominatorId the entity that made the suggestion to connect to this network,
+ * from {@link WifiMetricsProto.ConnectionEvent.ConnectionNominator}
+ */
+ public void setNominatorForNetwork(int networkId, int nominatorId) {
+ synchronized (mLock) {
+ if (networkId == WifiConfiguration.INVALID_NETWORK_ID) return;
+ mNetworkIdToNominatorId.put(networkId, nominatorId);
+ }
+ }
+
+ /** Add a WifiLock acqusition session */
+ public void addWifiLockAcqSession(int lockType, long duration) {
+ switch (lockType) {
+ case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+ mWifiLockHighPerfAcqDurationSecHistogram.increment((int) (duration / 1000));
+ break;
+
+ case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
+ mWifiLockLowLatencyAcqDurationSecHistogram.increment((int) (duration / 1000));
+ break;
+
+ default:
+ Log.e(TAG, "addWifiLockAcqSession: Invalid lock type: " + lockType);
+ break;
+ }
+ }
+
+ /** Add a WifiLock active session */
+ public void addWifiLockActiveSession(int lockType, long duration) {
+ switch (lockType) {
+ case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+ mWifiLockStats.highPerfActiveTimeMs += duration;
+ mWifiLockHighPerfActiveSessionDurationSecHistogram.increment(
+ (int) (duration / 1000));
+ break;
+
+ case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
+ mWifiLockStats.lowLatencyActiveTimeMs += duration;
+ mWifiLockLowLatencyActiveSessionDurationSecHistogram.increment(
+ (int) (duration / 1000));
+ break;
+
+ default:
+ Log.e(TAG, "addWifiLockActiveSession: Invalid lock type: " + lockType);
+ break;
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 43f673a..3e5dc3c 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -139,6 +139,8 @@
public InterfaceCallback externalListener;
/** Network observer registered for this interface */
public NetworkObserverInternal networkObserver;
+ /** Interface feature set / capabilities */
+ public long featureSet;
Iface(int id, @Iface.IfaceType int type) {
this.id = id;
@@ -968,6 +970,8 @@
onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
initializeNwParamsForClientInterface(iface.name);
Log.i(TAG, "Successfully setup " + iface);
+
+ iface.featureSet = getSupportedFeatureSetInternal(iface.name);
return iface.name;
}
}
@@ -1019,6 +1023,8 @@
// update the interface state before we exit.
onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
Log.i(TAG, "Successfully setup " + iface);
+
+ iface.featureSet = getSupportedFeatureSetInternal(iface.name);
return iface.name;
}
}
@@ -1073,6 +1079,8 @@
// update the interface state before we exit.
onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
Log.i(TAG, "Successfully setup " + iface);
+
+ iface.featureSet = getSupportedFeatureSetInternal(iface.name);
return iface.name;
}
}
@@ -2618,6 +2626,24 @@
* @return bitmask defined by WifiManager.WIFI_FEATURE_*
*/
public long getSupportedFeatureSet(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ Iface iface = mIfaceMgr.getIface(ifaceName);
+ if (iface == null) {
+ Log.e(TAG, "Could not get Iface object for interface " + ifaceName);
+ return 0;
+ }
+
+ return iface.featureSet;
+ }
+ }
+
+ /**
+ * Get the supported features
+ *
+ * @param ifaceName Name of the interface.
+ * @return bitmask defined by WifiManager.WIFI_FEATURE_*
+ */
+ private long getSupportedFeatureSetInternal(@NonNull String ifaceName) {
return mSupplicantStaIfaceHal.getAdvancedKeyMgmtCapabilities(ifaceName)
| mWifiVendorHal.getSupportedFeatureSet(ifaceName);
}
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index 174379e..168200b 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -56,6 +56,7 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.nano.WifiMetricsProto;
import com.android.server.wifi.util.ExternalCallbackTracker;
import com.android.server.wifi.util.ScanResultUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -63,6 +64,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -136,6 +138,8 @@
private boolean mPeriodicScanTimerSet = false;
private boolean mConnectionTimeoutSet = false;
private boolean mIsPeriodicScanPaused = false;
+ // We sent a new connection request and are waiting for connection success.
+ private boolean mPendingConnectionSuccess = false;
private boolean mWifiEnabled = false;
/**
* Indicates that we have new data to serialize.
@@ -712,6 +716,9 @@
// necessary checks when processing CONNECT_NETWORK.
int networkId = addNetworkToWifiConfigManager(network);
+ mWifiMetrics.setNominatorForNetwork(networkId,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER);
+
// Send the connect request to ClientModeImpl.
// TODO(b/117601161): Refactor this.
Message msg = Message.obtain();
@@ -733,12 +740,8 @@
WifiConfiguration networkToConnect =
new WifiConfiguration(mActiveSpecificNetworkRequestSpecifier.wifiConfiguration);
networkToConnect.SSID = network.SSID;
- // If the request is for a specific SSID and BSSID, then set WifiConfiguration.BSSID field
- // to prevent roaming.
- if (isActiveRequestForSingleAccessPoint()) {
- networkToConnect.BSSID =
- mActiveSpecificNetworkRequestSpecifier.bssidPatternMatcher.first.toString();
- }
+ // Set the WifiConfiguration.BSSID field to prevent roaming.
+ networkToConnect.BSSID = findBestBssidFromActiveMatchedScanResultsForNetwork(network);
// Mark the network ephemeral so that it's automatically removed at the end of connection.
networkToConnect.ephemeral = true;
networkToConnect.fromWifiNetworkSpecifier = true;
@@ -748,6 +751,8 @@
// Trigger connection to the network.
connectToNetwork(networkToConnect);
+ // Triggered connection to network, now wait for the connection status.
+ mPendingConnectionSuccess = true;
}
private void handleConnectToNetworkUserSelection(WifiConfiguration network) {
@@ -796,7 +801,10 @@
* Invoked by {@link ClientModeImpl} on successful connection to a network.
*/
private void handleNetworkConnectionSuccess(@NonNull WifiConfiguration connectedNetwork) {
- if (mUserSelectedNetwork == null || connectedNetwork == null) return;
+ if (mUserSelectedNetwork == null || connectedNetwork == null
+ || !mPendingConnectionSuccess) {
+ return;
+ }
if (!isUserSelectedNetwork(connectedNetwork)) {
Log.w(TAG, "Connected to unknown network " + connectedNetwork + ". Ignoring...");
return;
@@ -819,7 +827,9 @@
* Invoked by {@link ClientModeImpl} on failure to connect to a network.
*/
private void handleNetworkConnectionFailure(@NonNull WifiConfiguration failedNetwork) {
- if (mUserSelectedNetwork == null || failedNetwork == null) return;
+ if (mUserSelectedNetwork == null || failedNetwork == null || !mPendingConnectionSuccess) {
+ return;
+ }
if (!isUserSelectedNetwork(failedNetwork)) {
Log.w(TAG, "Connection failed to unknown network " + failedNetwork + ". Ignoring...");
return;
@@ -904,6 +914,7 @@
mUserSelectedNetworkConnectRetryCount = 0;
mIsPeriodicScanPaused = false;
mActiveMatchedScanResults = null;
+ mPendingConnectionSuccess = false;
// Cancel periodic scan, connection timeout alarm.
cancelPeriodicScans();
cancelConnectionTimeout();
@@ -933,6 +944,7 @@
mConnectedSpecificNetworkRequestSpecifier = mActiveSpecificNetworkRequestSpecifier;
mActiveSpecificNetworkRequest = null;
mActiveSpecificNetworkRequestSpecifier = null;
+ mPendingConnectionSuccess = false;
// Cancel connection timeout alarm.
cancelConnectionTimeout();
}
@@ -940,7 +952,7 @@
// Invoked at the termination of current connected request processing.
private void teardownForConnectedNetwork() {
Log.i(TAG, "Disconnecting from network on reset");
- mWifiInjector.getClientModeImpl().disconnectCommandInternal();
+ mWifiInjector.getClientModeImpl().disconnectCommand();
mConnectedSpecificNetworkRequest = null;
mConnectedSpecificNetworkRequestSpecifier = null;
// ensure there is no active request in progress.
@@ -1166,6 +1178,33 @@
return false;
}
+ // Will return the best bssid to use for the current request's connection.
+ //
+ // Note: This will never return null, unless there is some internal error.
+ // For ex:
+ // i) The latest scan results were empty.
+ // ii) The latest scan result did not contain any BSSID for the SSID user chose.
+ private @Nullable String findBestBssidFromActiveMatchedScanResultsForNetwork(
+ @NonNull WifiConfiguration network) {
+ if (mActiveSpecificNetworkRequestSpecifier == null
+ || mActiveMatchedScanResults == null) return null;
+ ScanResult selectedScanResult = mActiveMatchedScanResults
+ .stream()
+ .filter(scanResult -> Objects.equals(
+ ScanResultMatchInfo.fromScanResult(scanResult),
+ ScanResultMatchInfo.fromWifiConfiguration(network)))
+ .max(Comparator.comparing(scanResult -> scanResult.level))
+ .orElse(null);
+ if (selectedScanResult == null) { // Should never happen.
+ Log.wtf(TAG, "Expected to find at least one matching scan result");
+ return null;
+ }
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "Best bssid selected for the request " + selectedScanResult);
+ }
+ return selectedScanResult.BSSID;
+ }
+
private @Nullable ScanResult
findUserApprovedAccessPointForActiveRequestFromActiveMatchedScanResults() {
if (mActiveSpecificNetworkRequestSpecifier == null
diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java
index e7608ed..0b6f03e 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -28,6 +30,7 @@
import android.os.Process;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
import android.util.Pair;
@@ -35,6 +38,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.server.wifi.nano.WifiMetricsProto;
import com.android.server.wifi.util.ScanResultUtil;
import java.lang.annotation.Retention;
@@ -77,6 +81,11 @@
public static final int WIFI_POOR_SCORE = ConnectedScore.WIFI_TRANSITION_SCORE - 10;
/**
+ * The identifier string of the CandidateScorer to use (in the absence of overrides).
+ */
+ public static final String PRESET_CANDIDATE_SCORER_NAME = null;
+
+ /**
* Experiment ID for the legacy scorer.
*/
public static final int LEGACY_CANDIDATE_SCORER_EXP_ID = 0;
@@ -96,8 +105,11 @@
private final int mStayOnNetworkMinimumTxRate;
private final int mStayOnNetworkMinimumRxRate;
private final boolean mEnableAutoJoinWhenAssociated;
+ private final WifiNative mWifiNative;
private final Map<String, WifiCandidates.CandidateScorer> mCandidateScorers = new ArrayMap<>();
+ private boolean mIsEasyConnectSupportedInitialized = false;
+ private boolean mIsEasyConnectSupported;
/**
* WiFi Network Selector supports various categories of networks. Each category
@@ -407,6 +419,17 @@
return validScanDetails;
}
+ private boolean isEnhancedOpenSupported() {
+ if (mIsEasyConnectSupportedInitialized) {
+ return mIsEasyConnectSupported;
+ }
+
+ mIsEasyConnectSupportedInitialized = true;
+ mIsEasyConnectSupported = (mWifiNative.getSupportedFeatureSet(
+ mWifiNative.getClientInterfaceName()) & WIFI_FEATURE_OWE) != 0;
+ return mIsEasyConnectSupported;
+ }
+
/**
* This returns a list of ScanDetails that were filtered in the process of network selection.
* The list is further filtered for only open unsaved networks.
@@ -417,6 +440,7 @@
*/
public List<ScanDetail> getFilteredScanDetailsForOpenUnsavedNetworks() {
List<ScanDetail> openUnsavedNetworks = new ArrayList<>();
+ boolean enhancedOpenSupported = isEnhancedOpenSupported();
for (ScanDetail scanDetail : mFilteredNetworks) {
ScanResult scanResult = scanDetail.getScanResult();
@@ -424,6 +448,12 @@
continue;
}
+ // Filter out Enhanced Open networks on devices that do not support it
+ if (ScanResultUtil.isScanResultForOweNetwork(scanResult)
+ && !enhancedOpenSupported) {
+ continue;
+ }
+
// Skip saved networks
if (mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail) != null) {
continue;
@@ -575,6 +605,8 @@
localLog("After user selection adjustment, the final candidate is:"
+ WifiNetworkSelector.toNetworkString(candidate) + " : "
+ scanResultCandidate.BSSID);
+ mWifiMetrics.setNominatorForNetwork(candidate.networkId,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE);
}
return candidate;
}
@@ -628,6 +660,7 @@
// Determine the weight for the last user selection
final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();
final double lastSelectionWeight = calculateLastSelectionWeight();
+ final ArraySet<Integer> mNetworkIds = new ArraySet<>();
// Go through the registered network evaluators in order
WifiConfiguration selectedNetwork = null;
@@ -643,6 +676,7 @@
(scanDetail, config, score) -> {
if (config != null) {
mConnectableNetworks.add(Pair.create(scanDetail, config));
+ mNetworkIds.add(config.networkId);
if (config.networkId == lastUserSelectedNetworkId) {
wifiCandidates.add(scanDetail, config,
registeredEvaluator.getId(), score, lastSelectionWeight);
@@ -650,8 +684,14 @@
wifiCandidates.add(scanDetail, config,
registeredEvaluator.getId(), score);
}
+ mWifiMetrics.setNominatorForNetwork(config.networkId,
+ evaluatorIdToNominatorId(registeredEvaluator.getId()));
}
});
+ if (choice != null && !mNetworkIds.contains(choice.networkId)) {
+ Log.wtf(TAG, registeredEvaluator.getName()
+ + " failed to report choice with noConnectibleListener");
+ }
if (selectedNetwork == null && choice != null) {
selectedNetwork = choice; // First one wins
localLog(registeredEvaluator.getName() + " selects "
@@ -690,75 +730,80 @@
}
}
+ ArrayMap<Integer, Integer> experimentNetworkSelections = new ArrayMap<>(); // for metrics
+
+ final int legacySelectedNetworkId = selectedNetwork == null
+ ? WifiConfiguration.INVALID_NETWORK_ID
+ : selectedNetwork.networkId;
+
+ int selectedNetworkId = legacySelectedNetworkId;
+
+ // Run all the CandidateScorers
boolean legacyOverrideWanted = true;
-
- // Run any (experimental) CandidateScorers we have
- try {
- int activeExperimentId = LEGACY_CANDIDATE_SCORER_EXP_ID; // default legacy
- ArrayMap<Integer, WifiConfiguration> experimentNetworkSelections = new ArrayMap<>();
- experimentNetworkSelections.put(activeExperimentId, selectedNetwork);
-
- for (WifiCandidates.CandidateScorer candidateScorer : mCandidateScorers.values()) {
- String id = candidateScorer.getIdentifier();
- int expid = experimentIdFromIdentifier(id);
- WifiCandidates.ScoredCandidate choice = wifiCandidates.choose(candidateScorer);
- if (choice.candidateKey != null) {
- boolean thisOne = (expid == mScoringParams.getExperimentIdentifier());
- localLog(id + (thisOne ? " chooses " : " would choose ")
- + choice.candidateKey.networkId
- + " score " + choice.value + "+/-" + choice.err
- + " expid " + expid);
- int networkId = choice.candidateKey.networkId;
- WifiConfiguration thisSelectedNetwork =
- mWifiConfigManager.getConfiguredNetwork(networkId);
- experimentNetworkSelections.put(expid, thisSelectedNetwork);
- if (thisOne) { // update selected network only if this experiment is active
- activeExperimentId = expid; // ensures that experiment id actually exists
- selectedNetwork = thisSelectedNetwork;
- legacyOverrideWanted = candidateScorer.userConnectChoiceOverrideWanted();
- Log.i(TAG, id + " chooses " + networkId);
- }
- } else {
- localLog(candidateScorer.getIdentifier() + " found no candidates");
- experimentNetworkSelections.put(expid, null);
- }
+ final WifiCandidates.CandidateScorer activeScorer = getActiveCandidateScorer();
+ for (WifiCandidates.CandidateScorer candidateScorer : mCandidateScorers.values()) {
+ WifiCandidates.ScoredCandidate choice;
+ try {
+ choice = wifiCandidates.choose(candidateScorer);
+ } catch (RuntimeException e) {
+ Log.wtf(TAG, "Exception running a CandidateScorer", e);
+ continue;
}
-
- for (Map.Entry<Integer, WifiConfiguration> entry :
- experimentNetworkSelections.entrySet()) {
- int experimentId = entry.getKey();
- if (experimentId == activeExperimentId) continue;
- WifiConfiguration thisSelectedNetwork = entry.getValue();
- mWifiMetrics.logNetworkSelectionDecision(experimentId, activeExperimentId,
- isSameNetworkSelection(selectedNetwork, thisSelectedNetwork),
- groupedCandidates.size());
+ int networkId = choice.candidateKey == null
+ ? WifiConfiguration.INVALID_NETWORK_ID
+ : choice.candidateKey.networkId;
+ String chooses = " would choose ";
+ if (candidateScorer == activeScorer) {
+ chooses = " chooses ";
+ legacyOverrideWanted = candidateScorer.userConnectChoiceOverrideWanted();
+ selectedNetworkId = networkId;
}
- } catch (RuntimeException e) {
- Log.wtf(TAG, "Exception running a CandidateScorer, disabling", e);
- mCandidateScorers.clear();
+ String id = candidateScorer.getIdentifier();
+ int expid = experimentIdFromIdentifier(id);
+ localLog(id + chooses + networkId
+ + " score " + choice.value + "+/-" + choice.err
+ + " expid " + expid);
+ experimentNetworkSelections.put(expid, networkId);
}
- if (selectedNetwork != null) {
- // Update the copy of WifiConfiguration to reflect the scan result candidate update
- // above.
- selectedNetwork = mWifiConfigManager.getConfiguredNetwork(selectedNetwork.networkId);
- if (selectedNetwork != null && legacyOverrideWanted) {
- selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork);
- }
+ // Update metrics about differences in the selections made by various methods
+ final int activeExperimentId = activeScorer == null ? LEGACY_CANDIDATE_SCORER_EXP_ID
+ : experimentIdFromIdentifier(activeScorer.getIdentifier());
+ experimentNetworkSelections.put(LEGACY_CANDIDATE_SCORER_EXP_ID, legacySelectedNetworkId);
+ for (Map.Entry<Integer, Integer> entry :
+ experimentNetworkSelections.entrySet()) {
+ int experimentId = entry.getKey();
+ if (experimentId == activeExperimentId) continue;
+ int thisSelectedNetworkId = entry.getValue();
+ mWifiMetrics.logNetworkSelectionDecision(experimentId, activeExperimentId,
+ selectedNetworkId == thisSelectedNetworkId,
+ groupedCandidates.size());
+ }
+
+ // Get a fresh copy of WifiConfiguration reflecting any scan result updates
+ selectedNetwork = mWifiConfigManager.getConfiguredNetwork(selectedNetworkId);
+ if (selectedNetwork != null && legacyOverrideWanted) {
+ selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork);
mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis();
}
return selectedNetwork;
}
- private static boolean isSameNetworkSelection(WifiConfiguration c1, WifiConfiguration c2) {
- if (c1 == null && c2 == null) {
- return true;
- } else if (c1 == null && c2 != null) {
- return false;
- } else if (c1 != null && c2 == null) {
- return false;
- } else {
- return c1.networkId == c2.networkId;
+ private static int evaluatorIdToNominatorId(@NetworkEvaluator.EvaluatorId int evaluatorId) {
+ switch (evaluatorId) {
+ case NetworkEvaluator.EVALUATOR_ID_SAVED:
+ return WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED;
+ case NetworkEvaluator.EVALUATOR_ID_SUGGESTION:
+ return WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION;
+ case NetworkEvaluator.EVALUATOR_ID_PASSPOINT:
+ return WifiMetricsProto.ConnectionEvent.NOMINATOR_PASSPOINT;
+ case NetworkEvaluator.EVALUATOR_ID_CARRIER:
+ return WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER;
+ case NetworkEvaluator.EVALUATOR_ID_SCORED:
+ return WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED;
+ default:
+ Log.e(TAG, "UnrecognizedEvaluatorId" + evaluatorId);
+ return WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN;
}
}
@@ -774,6 +819,24 @@
return lastSelectionWeight;
}
+ private WifiCandidates.CandidateScorer getActiveCandidateScorer() {
+ WifiCandidates.CandidateScorer ans = mCandidateScorers.get(PRESET_CANDIDATE_SCORER_NAME);
+ int overrideExperimentId = mScoringParams.getExperimentIdentifier();
+ if (overrideExperimentId >= MIN_SCORER_EXP_ID) {
+ for (WifiCandidates.CandidateScorer candidateScorer : mCandidateScorers.values()) {
+ int expId = experimentIdFromIdentifier(candidateScorer.getIdentifier());
+ if (expId == overrideExperimentId) {
+ ans = candidateScorer;
+ break;
+ }
+ }
+ }
+ if (ans == null && PRESET_CANDIDATE_SCORER_NAME != null) {
+ Log.wtf(TAG, PRESET_CANDIDATE_SCORER_NAME + " is not registered!");
+ }
+ return ans;
+ }
+
/**
* Register a network evaluator
*
@@ -807,7 +870,7 @@
}
/**
- * Derives a numeric experiment identifer from a CandidateScorer's identifier.
+ * Derives a numeric experiment identifier from a CandidateScorer's identifier.
*
* @returns a positive number that starts with the decimal digits ID_PREFIX
*/
@@ -817,16 +880,18 @@
}
private static final int ID_SUFFIX_MOD = 1_000_000;
private static final int ID_PREFIX = 42;
+ private static final int MIN_SCORER_EXP_ID = ID_PREFIX * ID_SUFFIX_MOD;
WifiNetworkSelector(Context context, WifiScoreCard wifiScoreCard, ScoringParams scoringParams,
WifiConfigManager configManager, Clock clock, LocalLog localLog,
- WifiMetrics wifiMetrics) {
+ WifiMetrics wifiMetrics, WifiNative wifiNative) {
mWifiConfigManager = configManager;
mClock = clock;
mWifiScoreCard = wifiScoreCard;
mScoringParams = scoringParams;
mLocalLog = localLog;
mWifiMetrics = wifiMetrics;
+ mWifiNative = wifiNative;
mEnableAutoJoinWhenAssociated = context.getResources().getBoolean(
R.bool.config_wifi_framework_enable_associated_network_selection);
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
index ad09dce..c2aade9 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
@@ -504,7 +504,7 @@
if (mActiveNetworkSuggestionsMatchingConnection.isEmpty()) {
Log.i(TAG, "Only network suggestion matching the connected network removed. "
+ "Disconnecting...");
- mWifiInjector.getClientModeImpl().disconnectCommandInternal();
+ mWifiInjector.getClientModeImpl().disconnectCommand();
}
}
}
@@ -549,7 +549,7 @@
* Add the provided list of network suggestions from the corresponding app's active list.
*/
public @WifiManager.NetworkSuggestionsStatusCode int add(
- List<WifiNetworkSuggestion> networkSuggestions, String packageName) {
+ List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) {
if (mVerboseLoggingEnabled) {
Log.v(TAG, "Adding " + networkSuggestions.size() + " networks from " + packageName);
}
@@ -561,6 +561,10 @@
if (perAppInfo == null) {
perAppInfo = new PerAppInfo(packageName);
mActiveNetworkSuggestionsPerApp.put(packageName, perAppInfo);
+ if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) {
+ Log.i(TAG, "Setting the carrier provisioning app approved");
+ perAppInfo.hasUserApproved = true;
+ }
}
Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions =
convertToExtendedWnsSet(networkSuggestions, perAppInfo);
@@ -581,7 +585,7 @@
}
if (perAppInfo.extNetworkSuggestions.isEmpty()) {
// Start tracking app-op changes from the app if they have active suggestions.
- startTrackingAppOpsChange(packageName, networkSuggestions.get(0).suggestorUid);
+ startTrackingAppOpsChange(packageName, uid);
}
perAppInfo.extNetworkSuggestions.addAll(extNetworkSuggestions);
// Update the max size for this app.
diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java
index a96ba7f..850a206 100644
--- a/service/java/com/android/server/wifi/WifiScoreCard.java
+++ b/service/java/com/android/server/wifi/WifiScoreCard.java
@@ -814,4 +814,21 @@
return Base64.encodeToString(raw, Base64.DEFAULT);
}
+ /**
+ * Clears the internal state.
+ *
+ * This is called in response to a factoryReset call from Settings.
+ * The memory store will be called after we are called, to wipe the stable
+ * storage as well. Since we will have just removed all of our networks,
+ * it is very unlikely that we're connected, or will connect immediately.
+ * Any in-flight reads will land in the objects we are dropping here, and
+ * the memory store should drop the in-flight writes. Ideally we would
+ * avoid issuing reads until we were sure that the memory store had
+ * received the factoryReset.
+ */
+ public void clear() {
+ mApForBssid.clear();
+ resetConnectionStateInternal(false);
+ }
+
}
diff --git a/service/java/com/android/server/wifi/WifiService.java b/service/java/com/android/server/wifi/WifiService.java
index d298fbb..b934ea1 100644
--- a/service/java/com/android/server/wifi/WifiService.java
+++ b/service/java/com/android/server/wifi/WifiService.java
@@ -42,6 +42,8 @@
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.checkAndStartWifi();
+ } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ mImpl.handleBootCompleted();
}
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 7a69eaa..17d7ef8 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -591,15 +591,23 @@
}
}
+ public void handleBootCompleted() {
+ Log.d(TAG, "Handle boot completed");
+ mClientModeImpl.handleBootCompleted();
+ }
+
public void handleUserSwitch(int userId) {
+ Log.d(TAG, "Handle user switch " + userId);
mClientModeImpl.handleUserSwitch(userId);
}
public void handleUserUnlock(int userId) {
+ Log.d(TAG, "Handle user unlock " + userId);
mClientModeImpl.handleUserUnlock(userId);
}
public void handleUserStop(int userId) {
+ Log.d(TAG, "Handle user stop " + userId);
mClientModeImpl.handleUserStop(userId);
}
@@ -1644,7 +1652,7 @@
return false;
}
mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush();
- mClientModeImpl.disconnectCommandExternal();
+ mClientModeImpl.disconnectCommand();
return true;
}
@@ -2907,6 +2915,7 @@
mWifiInjector.getWifiConfigManager().clearDeletedEphemeralNetworks();
mClientModeImpl.clearNetworkRequestUserApprovedAccessPoints();
mWifiNetworkSuggestionsManager.clear();
+ mWifiInjector.getWifiScoreCard().clear();
});
}
}
@@ -3220,11 +3229,12 @@
if (mVerboseLoggingEnabled) {
mLog.info("addNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush();
}
+ int callingUid = Binder.getCallingUid();
Mutable<Integer> success = new Mutable<>();
boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
() -> {
success.value = mWifiNetworkSuggestionsManager.add(
- networkSuggestions, callingPackageName);
+ networkSuggestions, callingUid, callingPackageName);
}, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
if (!runWithScissorsSuccess) {
Log.e(TAG, "Failed to post runnable to add network suggestions");
diff --git a/service/java/com/android/server/wifi/WifiSettingsStore.java b/service/java/com/android/server/wifi/WifiSettingsStore.java
index 40ae05c..71b4deb 100644
--- a/service/java/com/android/server/wifi/WifiSettingsStore.java
+++ b/service/java/com/android/server/wifi/WifiSettingsStore.java
@@ -117,7 +117,8 @@
} else {
/* On airplane mode disable, restore wifi state if necessary */
if (testAndClearWifiSavedState() ||
- mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE) {
+ mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE
+ || mPersistWifiState == WIFI_DISABLED_AIRPLANE_ON) {
persistWifiState(WIFI_ENABLED);
}
}
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index e641106..1ac73ae 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -42,17 +42,18 @@
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import android.net.wifi.aware.WifiAwareUtils;
import android.os.Build;
+import android.os.Handler;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.Clock;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -60,6 +61,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.net.DatagramSocket;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
@@ -97,7 +99,13 @@
private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1;
private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1;
+ @VisibleForTesting
+ public static final int ADDRESS_VALIDATION_RETRY_INTERVAL_MS = 1_000; // 1 second
+ @VisibleForTesting
+ public static final int ADDRESS_VALIDATION_TIMEOUT_MS = 5_000; // 5 seconds
+
private final WifiAwareStateManager mMgr;
+ private final Clock mClock;
public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper();
private static final NetworkCapabilities sNetworkCapabilitiesFilter = new NetworkCapabilities();
private final Set<String> mInterfaces = new HashSet<>();
@@ -108,14 +116,16 @@
private WifiPermissionsUtil mWifiPermissionsUtil;
private WifiPermissionsWrapper mPermissionsWrapper;
private Looper mLooper;
+ private Handler mHandler;
private WifiAwareNetworkFactory mNetworkFactory;
public INetworkManagementService mNwService;
// internal debug flag to override API check
/* package */ boolean mAllowNdpResponderFromAnyOverride = false;
- public WifiAwareDataPathStateManager(WifiAwareStateManager mgr) {
+ public WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock) {
mMgr = mgr;
+ mClock = clock;
}
/**
@@ -131,6 +141,7 @@
mWifiPermissionsUtil = wifiPermissionsUtil;
mPermissionsWrapper = permissionsWrapper;
mLooper = looper;
+ mHandler = new Handler(mLooper);
sNetworkCapabilitiesFilter.clearAll();
sNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);
@@ -282,8 +293,7 @@
Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state="
+ nnri.state);
mNetworkRequestsCache.remove(networkSpecifier);
- mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
- mMgr.endDataPath(ndpId);
+ declareUnfullfillableAndEndDp(nnri, ndpId);
return;
}
@@ -428,7 +438,7 @@
nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
nnri.ndpId = ndpId;
- nnri.startTimestamp = SystemClock.elapsedRealtime();
+ nnri.startTimestamp = mClock.getElapsedSinceBootMillis();
mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk,
nnri.networkSpecifier.passphrase,
NetworkInformationData.buildTlv(nnri.networkSpecifier.port,
@@ -565,8 +575,7 @@
Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
+ ": can't configure network - "
+ e);
- mMgr.endDataPath(ndpId);
- nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
+ declareUnfullfillableAndEndDp(nnri, ndpId);
return networkSpecifier;
}
} else {
@@ -633,6 +642,7 @@
if (!mNiWrapper.configureAgentProperties(nnri, nnri.equivalentRequests, ndpId,
networkInfo, networkCapabilities, linkProperties)) {
+ declareUnfullfillableAndEndDp(nnri, ndpId);
return networkSpecifier;
}
@@ -641,12 +651,9 @@
new NetworkInfo(ConnectivityManager.TYPE_NONE, 0, NETWORK_TAG, ""),
networkCapabilities, linkProperties, NETWORK_FACTORY_SCORE_AVAIL,
nnri);
- nnri.networkAgent.sendNetworkInfo(networkInfo);
-
- mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, networkSpecifier.isOutOfBand(),
- nnri.startTimestamp);
- nnri.startTimestamp = SystemClock.elapsedRealtime(); // update time-stamp for duration
- mAwareMetrics.recordNdpCreation(nnri.uid, mNetworkRequestsCache);
+ nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis();
+ handleAddressValidation(nnri, linkProperties, networkInfo, ndpId,
+ networkSpecifier.isOutOfBand());
} else {
if (VDBG) {
Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
@@ -661,6 +668,38 @@
return networkSpecifier;
}
+ private void handleAddressValidation(AwareNetworkRequestInformation nnri,
+ LinkProperties linkProperties, NetworkInfo networkInfo, int ndpId,
+ boolean isOutOfBand) {
+ if (mNiWrapper.isAddressUsable(linkProperties)) {
+ mNiWrapper.sendAgentNetworkInfo(nnri.networkAgent, networkInfo);
+
+ mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, nnri.startTimestamp);
+ nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); // update time-stamp
+ mAwareMetrics.recordNdpCreation(nnri.uid, mNetworkRequestsCache);
+ } else {
+ if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp
+ > ADDRESS_VALIDATION_TIMEOUT_MS) {
+ Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable");
+
+ declareUnfullfillableAndEndDp(nnri, ndpId);
+ return;
+ }
+ if (mDbg) {
+ Log.d(TAG, "Failed address validation");
+ }
+ mHandler.postDelayed(() -> {
+ handleAddressValidation(nnri, linkProperties, networkInfo, ndpId, isOutOfBand);
+ }, ADDRESS_VALIDATION_RETRY_INTERVAL_MS);
+ }
+ }
+
+ private void declareUnfullfillableAndEndDp(AwareNetworkRequestInformation nnri, int ndpId) {
+ mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
+ mMgr.endDataPath(ndpId);
+ nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
+ }
+
/**
* Notification (unsolicited/asynchronous) from the firmware that the specified data-path has
* been terminated.
@@ -906,7 +945,7 @@
null);
nnri.state =
AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
- nnri.startTimestamp = SystemClock.elapsedRealtime();
+ nnri.startTimestamp = mClock.getElapsedSinceBootMillis();
} else {
nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST;
}
@@ -979,7 +1018,11 @@
}
}
- private class WifiAwareNetworkAgent extends NetworkAgent {
+ /**
+ * Network agent for Wi-Fi Aware.
+ */
+ @VisibleForTesting
+ public class WifiAwareNetworkAgent extends NetworkAgent {
private NetworkInfo mNetworkInfo;
private AwareNetworkRequestInformation mAwareNetworkRequestInfo;
@@ -1140,6 +1183,7 @@
public WifiAwareNetworkSpecifier networkSpecifier;
public List<NanDataPathChannelInfo> channelInfo;
public long startTimestamp = 0; // request is made (initiator) / get request (responder)
+ public long startValidationTimestamp = 0; // NDP created and starting to validate IPv6 addr
public WifiAwareNetworkAgent networkAgent;
@@ -1492,6 +1536,36 @@
return true;
}
+
+ /**
+ * Tries binding to the input address to check whether it is configured (and therefore
+ * usable).
+ */
+ public boolean isAddressUsable(LinkProperties linkProperties) {
+ InetAddress address = linkProperties.getLinkAddresses().get(0).getAddress();
+ DatagramSocket testDatagramSocket = null;
+ try {
+ testDatagramSocket = new DatagramSocket(0, address);
+ } catch (SocketException e) {
+ if (mDbg) {
+ Log.d(TAG, "Can't create socket on address " + address + " -- " + e);
+ }
+ return false;
+ } finally {
+ if (testDatagramSocket != null) {
+ testDatagramSocket.close();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Send updated network information to the agent.
+ */
+ public void sendAgentNetworkInfo(WifiAwareNetworkAgent networkAgent,
+ NetworkInfo networkInfo) {
+ networkAgent.sendNetworkInfo(networkInfo);
+ }
}
/**
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
index 23ecc75..e6e961d 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
@@ -43,6 +43,7 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
+import com.android.server.wifi.Clock;
import com.android.server.wifi.FrameworkFacade;
import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -104,7 +105,7 @@
mStateManager = awareStateManager;
mShellCommand = awareShellCommand;
mStateManager.start(mContext, handlerThread.getLooper(), awareMetrics, wifiPermissionsUtil,
- permissionsWrapper);
+ permissionsWrapper, new Clock());
frameworkFacade.registerContentObserver(mContext,
Settings.Global.getUriFor(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED), true,
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index ac1ed6a..36cabd6 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -52,6 +52,7 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
+import com.android.server.wifi.Clock;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -378,7 +379,8 @@
* @param looper Thread looper on which to run the handler.
*/
public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
- WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper) {
+ WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
+ Clock clock) {
Log.i(TAG, "start()");
mContext = context;
@@ -388,7 +390,7 @@
mSm.setDbg(VVDBG);
mSm.start();
- mDataPathMgr = new WifiAwareDataPathStateManager(this);
+ mDataPathMgr = new WifiAwareDataPathStateManager(this, clock);
mDataPathMgr.start(mContext, mSm.getHandler().getLooper(), awareMetrics,
wifiPermissionsUtil, permissionsWrapper);
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index d239057..e874ed1 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -338,7 +338,7 @@
return -1;
}
- String mccMnc = mTelephonyManager.getNetworkOperator();
+ String mccMnc = mTelephonyManager.getSimOperator();
if (mccMnc == null || mccMnc.length() < IMSIParameter.MCC_MNC_LENGTH - 1) {
return -1;
}
@@ -399,7 +399,7 @@
* {@code null} otherwise.
*/
public PasspointConfiguration createEphemeralPasspointConfigForCarrier(int eapMethod) {
- String mccMnc = mTelephonyManager.getNetworkOperator();
+ String mccMnc = mTelephonyManager.getSimOperator();
if (mccMnc == null || mccMnc.length() < IMSIParameter.MCC_MNC_LENGTH - 1) {
Log.e(TAG, "invalid length of mccmnc");
return null;
@@ -418,7 +418,7 @@
PasspointConfiguration config = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn(domain);
- homeSp.setFriendlyName(mTelephonyManager.getNetworkOperatorName());
+ homeSp.setFriendlyName(mTelephonyManager.getSimOperatorName());
config.setHomeSp(homeSp);
Credential credential = new Credential();
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
index df17389..fe882f6 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
@@ -33,6 +33,7 @@
import com.android.server.wifi.WifiConfigManager;
import com.android.server.wifi.WifiNetworkSelector;
import com.android.server.wifi.util.ScanResultUtil;
+import com.android.server.wifi.util.TelephonyUtil;
import java.util.ArrayList;
import java.util.List;
@@ -96,11 +97,11 @@
mPasspointManager.sweepCache();
// Creates an ephemeral Passpoint profile if it finds a matching Passpoint AP for MCC/MNC
- // of the current carrier on the device.
- if (mWifiConfigManager.isSimPresent()
+ // of the current MNO carrier on the device.
+ if ((TelephonyUtil.getCarrierType(mTelephonyManager) == TelephonyUtil.CARRIER_MNO_TYPE)
&& mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()
&& !mPasspointManager.hasCarrierProvider(
- mTelephonyManager.getNetworkOperator())) {
+ mTelephonyManager.getSimOperator())) {
int eapMethod = mPasspointManager.findEapMethodFromNAIRealmMatchedWithCarrier(
scanDetails);
if (isCarrierEapMethod(eapMethod)) {
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java
index 664824a..bf9e6d3 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java
@@ -29,6 +29,7 @@
import android.net.wifi.hotspot2.ProvisioningCallback;
import android.net.wifi.hotspot2.omadm.PpsMoParser;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -81,12 +82,12 @@
private final WfaKeyStore mWfaKeyStore;
private final PasspointObjectFactory mObjectFactory;
private final SystemInfo mSystemInfo;
- private RedirectListener mRedirectListener;
private int mCurrentSessionId = 0;
private int mCallingUid;
private boolean mVerboseLoggingEnabled = false;
private WifiManager mWifiManager;
private PasspointManager mPasspointManager;
+ private Looper mLooper;
PasspointProvisioner(Context context, WifiNative wifiNative,
PasspointObjectFactory objectFactory, PasspointManager passpointManager) {
@@ -107,12 +108,12 @@
* @param looper Looper on which the Provisioning state machine will run
*/
public void init(Looper looper) {
+ mLooper = looper;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- mProvisioningStateMachine.start(new Handler(looper));
+ mProvisioningStateMachine.start(new Handler(mLooper));
mOsuNetworkConnection.init(mProvisioningStateMachine.getHandler());
// Offload the heavy load job to another thread
mProvisioningStateMachine.getHandler().post(() -> {
- mRedirectListener = RedirectListener.createInstance(looper);
mWfaKeyStore.load();
mOsuServerConnection.init(mObjectFactory.getSSLContext(TLS_VERSION),
mObjectFactory.getTrustManagerImpl(mWfaKeyStore.get()));
@@ -142,10 +143,6 @@
*/
public boolean startSubscriptionProvisioning(int callingUid, OsuProvider provider,
IProvisioningCallback callback) {
- if (mRedirectListener == null) {
- Log.e(TAG, "RedirectListener is not possible to run");
- return false;
- }
mCallingUid = callingUid;
Log.v(TAG, "Provisioning started with " + provider.toString());
@@ -181,12 +178,20 @@
private String mSessionId;
private String mWebUrl;
private PasspointConfiguration mPasspointConfiguration;
+ private RedirectListener mRedirectListener;
+ private HandlerThread mRedirectHandlerThread;
+ private Handler mRedirectStartStopHandler;
/**
* Initializes and starts the state machine with a handler to handle incoming events
*/
public void start(Handler handler) {
mHandler = handler;
+ if (mRedirectHandlerThread == null) {
+ mRedirectHandlerThread = new HandlerThread("RedirectListenerHandler");
+ mRedirectHandlerThread.start();
+ mRedirectStartStopHandler = new Handler(mRedirectHandlerThread.getLooper());
+ }
}
/**
@@ -216,9 +221,17 @@
}
resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED);
}
+ mProvisioningCallback = callback;
+ mRedirectListener = RedirectListener.createInstance(mLooper);
+
+ if (mRedirectListener == null) {
+ resetStateMachineForFailure(
+ ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER);
+ return;
+ }
+
if (!mOsuServerConnection.canValidateServer()) {
Log.w(TAG, "Provisioning is not possible");
- mProvisioningCallback = callback;
resetStateMachineForFailure(
ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
return;
@@ -228,12 +241,10 @@
serverUrl = new URL(provider.getServerUri().toString());
} catch (MalformedURLException e) {
Log.e(TAG, "Invalid Server URL");
- mProvisioningCallback = callback;
resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID);
return;
}
mServerUrl = serverUrl;
- mProvisioningCallback = callback;
mOsuProvider = provider;
if (mOsuProvider.getOsuSsid() == null) {
// Find a best matching OsuProvider that has an OSU SSID from current scanResults
@@ -376,7 +387,7 @@
invokeProvisioningCallback(PROVISIONING_STATUS,
ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED);
- mRedirectListener.stopServer();
+ mRedirectListener.stopServer(mRedirectStartStopHandler);
secondSoapExchange();
}
@@ -395,7 +406,7 @@
resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED);
return;
}
- mRedirectListener.stopServer();
+ mRedirectListener.stopServer(mRedirectStartStopHandler);
resetStateMachineForFailure(
ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER);
}
@@ -754,7 +765,7 @@
}
mProvisioningStateMachine.handleTimeOutForRedirectResponse();
}
- })) {
+ }, mRedirectStartStopHandler)) {
Log.e(TAG, "fails to start redirect listener");
resetStateMachineForFailure(
ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER);
@@ -944,12 +955,15 @@
}
private void resetStateMachine() {
- mRedirectListener.stopServer();
+ if (mRedirectListener != null) {
+ mRedirectListener.stopServer(mRedirectStartStopHandler);
+ }
mOsuNetworkConnection.setEventCallback(null);
mOsuNetworkConnection.disconnectIfNeeded();
mOsuServerConnection.setEventCallback(null);
mOsuServerConnection.cleanup();
mPasspointConfiguration = null;
+ mProvisioningCallback = null;
changeState(STATE_INIT);
}
diff --git a/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java b/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java
index 03c3ebe..103aecb 100644
--- a/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java
+++ b/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java
@@ -17,9 +17,7 @@
package com.android.server.wifi.hotspot2.soap;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.Looper;
import android.util.Log;
@@ -42,15 +40,13 @@
* redirect server no longer needed.
*/
public class RedirectListener extends NanoHTTPD {
- // 4 minutes for the maximum wait time.
+ // 10 minutes for the maximum wait time.
@VisibleForTesting
- static final int USER_TIMEOUT_MILLIS = 4 * 60 * 1000;
+ static final int USER_TIMEOUT_MILLIS = 10 * 60 * 1000;
private static final String TAG = "PasspointRedirectListener";
-
private final String mPath;
private final URL mServerUrl;
- private final Handler mStartStopHandler;
private final Handler mHandler;
private Runnable mTimeOutTask;
private RedirectCallback mRedirectCallback;
@@ -72,7 +68,7 @@
}
@VisibleForTesting
- /* package */ RedirectListener(Looper looper, @Nullable Looper startStopLooper, int port)
+ /* package */ RedirectListener(Looper looper, int port)
throws IOException {
super(InetAddress.getLocalHost().getHostAddress(), port);
@@ -82,12 +78,6 @@
mServerUrl = new URL("http", getHostname(), port, mPath);
mHandler = new Handler(looper);
mTimeOutTask = () -> mRedirectCallback.onRedirectTimedOut();
- if (startStopLooper == null) {
- HandlerThread redirectHandlerThread = new HandlerThread("RedirectListenerHandler");
- redirectHandlerThread.start();
- startStopLooper = redirectHandlerThread.getLooper();
- }
- mStartStopHandler = new Handler(startStopLooper);
}
/**
@@ -99,8 +89,14 @@
public static RedirectListener createInstance(@NonNull Looper looper) {
RedirectListener redirectListener;
try {
- redirectListener = new RedirectListener(looper, null,
- new ServerSocket(0, 1, InetAddress.getLocalHost()).getLocalPort());
+ ServerSocket serverSocket = new ServerSocket(0, 1, InetAddress.getLocalHost());
+ redirectListener = new RedirectListener(looper, serverSocket.getLocalPort());
+ redirectListener.setServerSocketFactory(() -> {
+ // Close current server socket so that new server socket is able to bind the port
+ // in the start() of NanoHTTPD.
+ serverSocket.close();
+ return new ServerSocket();
+ });
} catch (IOException e) {
Log.e(TAG, "fails to create an instance: " + e);
return null;
@@ -112,21 +108,26 @@
* Start redirect listener
*
* @param callback to be notified when the redirect request is received or timed out.
- * @return {@code true} in success, {@code false} if the {@code callback} is {@code null} or the
- * server is already running.
+ * @param startHandler handler on which the start code is executed.
+ * @return {@code true} in success, {@code false} if the {@code callback} and {@code
+ * startHandler} are {@code null} or the server is already running.
*/
- public boolean startServer(@NonNull RedirectCallback callback) {
+ public boolean startServer(@NonNull RedirectCallback callback, @NonNull Handler startHandler) {
if (callback == null) {
return false;
}
+ if (startHandler == null) {
+ return false;
+ }
+
if (isAlive()) {
Log.e(TAG, "redirect listener is already running");
return false;
}
mRedirectCallback = callback;
- mStartStopHandler.post(() -> {
+ startHandler.post(() -> {
try {
start();
} catch (IOException e) {
@@ -139,13 +140,18 @@
/**
* Stop redirect listener
+ *
+ * @param stopHandler handler on which the stop code is executed.
*/
- public void stopServer() {
+ public void stopServer(@NonNull Handler stopHandler) {
if (mHandler.hasCallbacks(mTimeOutTask)) {
mHandler.removeCallbacks(mTimeOutTask);
}
+ if (stopHandler == null) {
+ return;
+ }
if (isServerAlive()) {
- mStartStopHandler.post(() -> stop());
+ stopHandler.post(() -> stop());
}
}
diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
index 7e0eaee..12adea1 100644
--- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
+++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
@@ -55,6 +55,7 @@
import android.util.Log;
import android.util.SparseIntArray;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.WakeupMessage;
import com.android.server.wifi.Clock;
import com.android.server.wifi.FrameworkFacade;
@@ -89,8 +90,6 @@
private WifiPermissionsUtil mWifiPermissionsUtil;
private ActivityManager mActivityManager;
private PowerManager mPowerManager;
- private LocationManager mLocationManager;
- private FrameworkFacade mFrameworkFacade;
private long mBackgroundProcessExecGapMs;
private RttServiceSynchronized mRttServiceSynchronized;
@@ -99,7 +98,10 @@
/* package */ static final String HAL_RANGING_TIMEOUT_TAG = TAG + " HAL Ranging Timeout";
- private static final long HAL_RANGING_TIMEOUT_MS = 5_000; // 5 sec
+ @VisibleForTesting
+ public static final long HAL_RANGING_TIMEOUT_MS = 5_000; // 5 sec
+ @VisibleForTesting
+ public static final long HAL_AWARE_RANGING_TIMEOUT_MS = 10_000; // 10 sec
// Default value for RTT background throttling interval.
private static final long DEFAULT_BACKGROUND_PROCESS_EXEC_GAP_MS = 1_800_000; // 30 min
@@ -230,12 +232,10 @@
mRttNative = rttNative;
mRttMetrics = rttMetrics;
mWifiPermissionsUtil = wifiPermissionsUtil;
- mFrameworkFacade = frameworkFacade;
mRttServiceSynchronized = new RttServiceSynchronized(looper, rttNative);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mPowerManager = mContext.getSystemService(PowerManager.class);
- mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
mContext.registerReceiver(new BroadcastReceiver() {
@@ -829,8 +829,14 @@
nextRequest.cmdId = mNextCommandId++;
if (mRttNative.rangeRequest(nextRequest.cmdId, nextRequest.request,
nextRequest.isCalledFromPrivilegedContext)) {
- mRangingTimeoutMessage.schedule(
- mClock.getElapsedSinceBootMillis() + HAL_RANGING_TIMEOUT_MS);
+ long timeout = HAL_RANGING_TIMEOUT_MS;
+ for (ResponderConfig responderConfig : nextRequest.request.mRttPeers) {
+ if (responderConfig.responderType == ResponderConfig.RESPONDER_AWARE) {
+ timeout = HAL_AWARE_RANGING_TIMEOUT_MS;
+ break;
+ }
+ }
+ mRangingTimeoutMessage.schedule(mClock.getElapsedSinceBootMillis() + timeout);
} else {
Log.w(TAG, "RttServiceSynchronized.startRanging: native rangeRequest call failed");
try {
diff --git a/service/java/com/android/server/wifi/util/DataIntegrityChecker.java b/service/java/com/android/server/wifi/util/DataIntegrityChecker.java
index b005529..38ecb07 100644
--- a/service/java/com/android/server/wifi/util/DataIntegrityChecker.java
+++ b/service/java/com/android/server/wifi/util/DataIntegrityChecker.java
@@ -17,8 +17,10 @@
package com.android.server.wifi.util;
import android.annotation.NonNull;
+import android.os.SystemProperties;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
+import android.text.TextUtils;
import android.util.Log;
import java.io.File;
@@ -61,7 +63,13 @@
private static final int GCM_TAG_LENGTH = 128;
private static final String KEY_STORE = "AndroidKeyStore";
- private File mIntegrityFile;
+ /**
+ * When KEYSTORE_FAILURE_RETURN_VALUE is true, all cryptographic operation failures will not
+ * enforce security and {@link #isOk(byte[])} always return true.
+ */
+ private static final boolean KEYSTORE_FAILURE_RETURN_VALUE = true;
+
+ private final File mIntegrityFile;
/**
* Construct a new integrity checker to update and check if/when a data file was altered
@@ -73,34 +81,37 @@
* path as the file for which integrity is performed on.
* @throws NullPointerException When integrity file is null or the empty string.
*/
- public DataIntegrityChecker(@NonNull String integrityFilename) throws NullPointerException {
- if (integrityFilename == null || integrityFilename.equals("")) {
+ public DataIntegrityChecker(@NonNull String integrityFilename) {
+ if (TextUtils.isEmpty(integrityFilename)) {
throw new NullPointerException("integrityFilename must not be null or the empty "
+ "string");
- } else {
- mIntegrityFile = new File(integrityFilename + FILE_SUFFIX);
}
+ mIntegrityFile = new File(integrityFilename + FILE_SUFFIX);
}
/**
- * Compute a digest of a byte array, encrypt it, and store the result
+ * Computes a digest of a byte array, encrypt it, and store the result
*
* Call this method immediately before storing the byte array
*
* @param data The data desired to ensure integrity
*/
public void update(byte[] data) {
- if (data == null || mIntegrityFile == null) {
+ if (data == null || data.length < 1) {
+ Log.e(TAG, "No data to update.");
+ reportException(new Exception("No data to update"));
return;
}
byte[] digest = getDigest(data);
- if (digest == null) {
+ if (digest == null || digest.length < 1) {
return;
}
String alias = mIntegrityFile.getName() + ALIAS_SUFFIX;
EncryptedData integrityData = encrypt(digest, alias);
if (integrityData != null) {
writeIntegrityData(integrityData, mIntegrityFile);
+ } else {
+ reportException(new Exception("integrityData null upon update"));
}
}
@@ -119,12 +130,12 @@
* @return true if the data was not altered since {@link #update(byte[])} was last called
*/
public boolean isOk(byte[] data) throws DigestException {
- if (data == null || mIntegrityFile == null) {
- return false;
+ if (data == null || data.length < 1) {
+ return KEYSTORE_FAILURE_RETURN_VALUE;
}
byte[] currentDigest = getDigest(data);
- if (currentDigest == null) {
- return false;
+ if (currentDigest == null || currentDigest.length < 1) {
+ return KEYSTORE_FAILURE_RETURN_VALUE;
}
EncryptedData encryptedData = readIntegrityData(mIntegrityFile);
if (encryptedData == null) {
@@ -132,16 +143,17 @@
}
byte[] storedDigest = decrypt(encryptedData);
if (storedDigest == null) {
- return false;
+ return KEYSTORE_FAILURE_RETURN_VALUE;
}
return constantTimeEquals(storedDigest, currentDigest);
}
- private static byte[] getDigest(byte[] data) {
+ private byte[] getDigest(byte[] data) {
try {
return MessageDigest.getInstance(DIGEST_ALGORITHM).digest(data);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "getDigest could not find algorithm: " + DIGEST_ALGORITHM);
+ reportException(e);
return null;
}
}
@@ -154,22 +166,29 @@
if (secretKeyReference != null) {
cipher.init(Cipher.ENCRYPT_MODE, secretKeyReference);
encryptedData = new EncryptedData(cipher.doFinal(data), cipher.getIV(), keyAlias);
+ } else {
+ reportException(new Exception("secretKeyReference is null."));
}
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "encrypt could not find the algorithm: " + CIPHER_ALGORITHM);
+ reportException(e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "encrypt had a padding exception");
+ reportException(e);
} catch (InvalidKeyException e) {
Log.e(TAG, "encrypt received an invalid key");
+ reportException(e);
} catch (BadPaddingException e) {
Log.e(TAG, "encrypt had a padding problem");
+ reportException(e);
} catch (IllegalBlockSizeException e) {
Log.e(TAG, "encrypt had an illegal block size");
+ reportException(e);
}
return encryptedData;
}
- private static byte[] decrypt(EncryptedData encryptedData) {
+ private byte[] decrypt(EncryptedData encryptedData) {
byte[] decryptedData = null;
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
@@ -181,21 +200,27 @@
}
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "decrypt could not find cipher algorithm " + CIPHER_ALGORITHM);
+ reportException(e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "decrypt could not find padding algorithm");
+ reportException(e);
} catch (IllegalBlockSizeException e) {
Log.e(TAG, "decrypt had a illegal block size");
+ reportException(e);
} catch (BadPaddingException e) {
Log.e(TAG, "decrypt had bad padding");
+ reportException(e);
} catch (InvalidKeyException e) {
Log.e(TAG, "decrypt had an invalid key");
+ reportException(e);
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, "decrypt had an invalid algorithm parameter");
+ reportException(e);
}
return decryptedData;
}
- private static SecretKey getOrCreateSecretKey(String keyAlias) {
+ private SecretKey getOrCreateSecretKey(String keyAlias) {
SecretKey secretKey = null;
try {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE);
@@ -205,6 +230,9 @@
.getEntry(keyAlias, null);
if (secretKeyEntry != null) {
secretKey = secretKeyEntry.getSecretKey();
+ } else {
+ reportException(new Exception("keystore contains the alias and the secret key "
+ + "entry was null"));
}
} else { // The key does not exist in key store. Create the key and store it.
KeyGenerator keyGenerator = KeyGenerator
@@ -221,49 +249,57 @@
}
} catch (CertificateException e) {
Log.e(TAG, "getOrCreateSecretKey had a certificate exception.");
+ reportException(e);
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, "getOrCreateSecretKey had an invalid algorithm parameter");
+ reportException(e);
} catch (IOException e) {
Log.e(TAG, "getOrCreateSecretKey had an IO exception.");
+ reportException(e);
} catch (KeyStoreException e) {
Log.e(TAG, "getOrCreateSecretKey cannot find the keystore: " + KEY_STORE);
+ reportException(e);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "getOrCreateSecretKey cannot find algorithm");
+ reportException(e);
} catch (NoSuchProviderException e) {
Log.e(TAG, "getOrCreateSecretKey cannot find crypto provider");
+ reportException(e);
} catch (UnrecoverableEntryException e) {
Log.e(TAG, "getOrCreateSecretKey had an unrecoverable entry exception.");
+ reportException(e);
}
return secretKey;
}
- private static void writeIntegrityData(EncryptedData encryptedData, File file) {
- try {
- FileOutputStream fos = new FileOutputStream(file);
- ObjectOutputStream oos = new ObjectOutputStream(fos);
+ private void writeIntegrityData(EncryptedData encryptedData, File file) {
+ try (FileOutputStream fos = new FileOutputStream(file);
+ ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(encryptedData);
- oos.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "writeIntegrityData could not find the integrity file");
+ reportException(e);
} catch (IOException e) {
Log.e(TAG, "writeIntegrityData had an IO exception");
+ reportException(e);
}
}
- private static EncryptedData readIntegrityData(File file) {
- EncryptedData encryptedData = null;
- try {
- FileInputStream fis = new FileInputStream(file);
- ObjectInputStream ois = new ObjectInputStream(fis);
- encryptedData = (EncryptedData) ois.readObject();
+ private EncryptedData readIntegrityData(File file) {
+ try (FileInputStream fis = new FileInputStream(file);
+ ObjectInputStream ois = new ObjectInputStream(fis)) {
+ return (EncryptedData) ois.readObject();
} catch (FileNotFoundException e) {
Log.e(TAG, "readIntegrityData could not find integrity file");
+ reportException(e);
} catch (IOException e) {
Log.e(TAG, "readIntegrityData had an IO exception");
+ reportException(e);
} catch (ClassNotFoundException e) {
Log.e(TAG, "readIntegrityData could not find the class EncryptedData");
+ reportException(e);
}
- return encryptedData;
+ return null;
}
private boolean constantTimeEquals(byte[] a, byte[] b) {
@@ -281,4 +317,15 @@
}
return (differenceAccumulator == 0);
}
+
+ /* TODO(b/128526030): Remove this error reporting code upon resolving the bug. */
+ private static final boolean REQUEST_BUG_REPORT = true;
+ private void reportException(Exception exception) {
+ Log.wtf(TAG, "An irrecoverable key store error was encountered. "
+ + "KEYSTORE_FAILURE_RETURN_VALUE is set to " + KEYSTORE_FAILURE_RETURN_VALUE);
+ if (REQUEST_BUG_REPORT) {
+ SystemProperties.set("dumpstate.options", "bugreportwifi");
+ SystemProperties.set("ctl.start", "bugreport");
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/util/TelephonyUtil.java
index 597aa71..09b790a 100644
--- a/service/java/com/android/server/wifi/util/TelephonyUtil.java
+++ b/service/java/com/android/server/wifi/util/TelephonyUtil.java
@@ -16,6 +16,7 @@
package com.android.server.wifi.util;
+import android.annotation.NonNull;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.telephony.ImsiEncryptionInfo;
@@ -25,6 +26,7 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.CarrierNetworkConfig;
import com.android.server.wifi.WifiNative;
import java.security.InvalidKeyException;
@@ -45,6 +47,10 @@
public static final String DEFAULT_EAP_PREFIX = "\0";
+ public static final int CARRIER_INVALID_TYPE = -1;
+ public static final int CARRIER_MNO_TYPE = 0; // Mobile Network Operator
+ public static final int CARRIER_MVNO_TYPE = 1; // Mobile Virtual Network Operator
+
private static final String THREE_GPP_NAI_REALM_FORMAT = "wlan.mnc%s.mcc%s.3gppnetwork.org";
// IMSI encryption method: RSA-OAEP with SHA-256 hash function
@@ -73,16 +79,22 @@
*
* @param tm TelephonyManager instance
* @param config WifiConfiguration that indicates what sort of authentication is necessary
+ * @param telephonyUtil TelephonyUtil instance
+ * @param carrierNetworkConfig CarrierNetworkConfig instance
* @return Pair<identify, encrypted identity> or null if the SIM is not available
* or config is invalid
*/
public static Pair<String, String> getSimIdentity(TelephonyManager tm,
- TelephonyUtil telephonyUtil,
- WifiConfiguration config) {
+ TelephonyUtil telephonyUtil,
+ WifiConfiguration config, CarrierNetworkConfig carrierNetworkConfig) {
if (tm == null) {
Log.e(TAG, "No valid TelephonyManager");
return null;
}
+ if (carrierNetworkConfig == null) {
+ Log.e(TAG, "No valid CarrierNetworkConfig");
+ return null;
+ }
String imsi = tm.getSubscriberId();
String mccMnc = "";
@@ -104,8 +116,12 @@
return null;
}
+ int base64EncodingFlag = carrierNetworkConfig.getBase64EncodingFlag();
+
String encryptedIdentity = buildEncryptedIdentity(telephonyUtil,
- getSimMethodForConfig(config), imsi, mccMnc, imsiEncryptionInfo);
+ getSimMethodForConfig(config), imsi, mccMnc, imsiEncryptionInfo,
+ base64EncodingFlag);
+
// In case of failure for encryption, set empty string
if (encryptedIdentity == null) encryptedIdentity = "";
return Pair.create(identity, encryptedIdentity);
@@ -116,15 +132,17 @@
* a Base64 encoded string.
*
* @param key The public key to use for encryption
+ * @param encodingFlag base64 encoding flag
* @return Base64 encoded string, or null if encryption failed
*/
@VisibleForTesting
- public String encryptDataUsingPublicKey(PublicKey key, byte[] data) {
+ public String encryptDataUsingPublicKey(PublicKey key, byte[] data, int encodingFlag) {
try {
Cipher cipher = Cipher.getInstance(IMSI_CIPHER_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(data);
- return Base64.encodeToString(encryptedBytes, 0, encryptedBytes.length, Base64.DEFAULT);
+
+ return Base64.encodeToString(encryptedBytes, 0, encryptedBytes.length, encodingFlag);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException e) {
Log.e(TAG, "Encryption failed: " + e.getMessage());
@@ -138,14 +156,16 @@
* "0" - EAP-AKA Identity
* "1" - EAP-SIM Identity
* "6" - EAP-AKA' Identity
+ *
* @param eapMethod EAP authentication method: EAP-SIM, EAP-AKA, EAP-AKA'
* @param imsi The IMSI retrieved from the SIM
* @param mccMnc The MCC MNC identifier retrieved from the SIM
* @param imsiEncryptionInfo The IMSI encryption info retrieved from the SIM
+ * @param base64EncodingFlag base64 encoding flag
*/
private static String buildEncryptedIdentity(TelephonyUtil telephonyUtil, int eapMethod,
- String imsi, String mccMnc,
- ImsiEncryptionInfo imsiEncryptionInfo) {
+ String imsi, String mccMnc,
+ ImsiEncryptionInfo imsiEncryptionInfo, int base64EncodingFlag) {
if (imsiEncryptionInfo == null) {
return null;
}
@@ -155,9 +175,10 @@
return null;
}
imsi = prefix + imsi;
+
// Build and return the encrypted identity.
String encryptedImsi = telephonyUtil.encryptDataUsingPublicKey(
- imsiEncryptionInfo.getPublicKey(), imsi.getBytes());
+ imsiEncryptionInfo.getPublicKey(), imsi.getBytes(), base64EncodingFlag);
if (encryptedImsi == null) {
Log.e(TAG, "Failed to encrypt IMSI");
return null;
@@ -621,4 +642,23 @@
return null;
}
}
+
+ /**
+ * Get the carrier type of current SIM.
+ *
+ * @param tm {@link TelephonyManager} instance
+ * @return carrier type of current active sim, {{@link #CARRIER_INVALID_TYPE}} if sim is not
+ * ready or {@code tm} is {@code null}
+ */
+ public static int getCarrierType(@NonNull TelephonyManager tm) {
+ if (tm == null || tm.getSimState() != TelephonyManager.SIM_STATE_READY) {
+ return CARRIER_INVALID_TYPE;
+ }
+
+ // If two APIs return the same carrier ID, then is considered as MNO, otherwise MVNO
+ if (tm.getCarrierIdFromSimMccMnc() == tm.getSimCarrierId()) {
+ return CARRIER_MNO_TYPE;
+ }
+ return CARRIER_MVNO_TYPE;
+ }
}
diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
index f68654f..eeacac0 100644
--- a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
+++ b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
@@ -482,4 +482,13 @@
android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, uid)
== PackageManager.PERMISSION_GRANTED;
}
+
+ /**
+ * Returns true if the |uid| holds NETWORK_CARRIER_PROVISIONING permission.
+ */
+ public boolean checkNetworkCarrierProvisioningPermission(int uid) {
+ return mWifiPermissionsWrapper.getUidPermission(
+ android.Manifest.permission.NETWORK_CARRIER_PROVISIONING, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
}
diff --git a/tests/wifitests/Android.mk b/tests/wifitests/Android.mk
index d14f303..24213cd 100644
--- a/tests/wifitests/Android.mk
+++ b/tests/wifitests/Android.mk
@@ -79,6 +79,8 @@
libbinder \
libbinderthreadstate \
libc++ \
+ ld-android \
+ libdl_android \
libcamera_client \
libcamera_metadata \
libcutils \
diff --git a/tests/wifitests/coverage.sh b/tests/wifitests/coverage.sh
index 33b9f30..f9ea1fb 100755
--- a/tests/wifitests/coverage.sh
+++ b/tests/wifitests/coverage.sh
@@ -40,12 +40,14 @@
MODULES-IN-external-jacoco \
FrameworksWifiTests
+APK_NAME="$(ls -t $(find $OUT -name FrameworksWifiTests.apk) | head -n 1)"
+
adb root
adb wait-for-device
adb shell rm -f $REMOTE_COVERAGE_OUTPUT_FILE
-adb install -r -g "$OUT/data/app/FrameworksWifiTests/FrameworksWifiTests.apk"
+adb install -r -g "$APK_NAME"
adb shell am instrument -e coverage true --no-hidden-api-checks -w 'com.android.server.wifi.test/com.android.server.wifi.CustomTestRunner'
diff --git a/tests/wifitests/runtests.sh b/tests/wifitests/runtests.sh
index 7b25183..6e83199 100755
--- a/tests/wifitests/runtests.sh
+++ b/tests/wifitests/runtests.sh
@@ -32,13 +32,14 @@
# NOTE Don't actually run the command above since this shell doesn't inherit functions from the
# caller.
$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode MODULES-IN-frameworks-opt-net-wifi-tests
+APK_NAME="$(ls -t $(find $OUT -name FrameworksWifiTests.apk) | head -n 1)"
set -x # print commands
adb root
adb wait-for-device
-adb install -r -g "$OUT/testcases/FrameworksWifiTests/arm64/FrameworksWifiTests.apk"
+adb install -r -g "$APK_NAME"
adb shell am instrument --no-hidden-api-checks -w "$@" \
'com.android.server.wifi.test/com.android.server.wifi.CustomTestRunner'
diff --git a/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java b/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
index 3f1478f..f52229c 100644
--- a/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
@@ -438,6 +438,22 @@
}
/**
+ * Verifies that SoftApStateChanged event isn't passed to WifiServiceImpl for LOHS,
+ * so the state change for LOHS doesn't affect Wifi Tethering indication.
+ */
+ @Test
+ public void doesntCallWifiServiceCallbackOnLOHSStateChanged() throws Exception {
+ enterSoftApActiveMode(new SoftApModeConfiguration(
+ WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null));
+
+ mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0);
+ mLooper.dispatchAll();
+
+ verify(mSoftApStateMachineCallback, never()).onStateChanged(anyInt(), anyInt());
+ verify(mSoftApStateMachineCallback, never()).onNumClientsChanged(anyInt());
+ }
+
+ /**
* Verifies that triggering a state change update will not crash if the callback to
* WifiServiceImpl is null.
*/
diff --git a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java
index 6e731e6..505e691 100644
--- a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java
@@ -80,14 +80,17 @@
*
* @param ssid The SSID of the carrier network
* @param eapType The EAP type of the carrier network
+ * @param encodingMethod base64 encoding method
* @return {@link PersistableBundle} containing carrier config
*/
- private PersistableBundle generateTestConfig(String ssid, int eapType) {
+ private PersistableBundle generateTestConfig(String ssid, int eapType, int encodingMethod) {
PersistableBundle bundle = new PersistableBundle();
String networkConfig =
new String(Base64.encode(ssid.getBytes(), Base64.DEFAULT)) + "," + eapType;
bundle.putStringArray(CarrierConfigManager.KEY_CARRIER_WIFI_STRING_ARRAY,
new String[] {networkConfig});
+ bundle.putInt(CarrierConfigManager.KEY_IMSI_ENCODING_METHOD_INT, encodingMethod);
+
return bundle;
}
@@ -103,7 +106,8 @@
.thenReturn(mSubscriptionManager);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID))
- .thenReturn(generateTestConfig(TEST_SSID, TEST_STANDARD_EAP_TYPE));
+ .thenReturn(generateTestConfig(TEST_SSID, TEST_STANDARD_EAP_TYPE,
+ CarrierNetworkConfig.ENCODING_METHOD_RFC_2045));
when(mSubscriptionManager.getActiveSubscriptionInfoList())
.thenReturn(Arrays.asList(new SubscriptionInfo[] {TEST_SUBSCRIPTION_INFO}));
when(mTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN))
@@ -135,6 +139,7 @@
assertTrue(mCarrierNetworkConfig.isCarrierNetwork(TEST_SSID));
assertEquals(TEST_INTERNAL_EAP_TYPE, mCarrierNetworkConfig.getNetworkEapType(TEST_SSID));
assertEquals(TEST_CARRIER_NAME, mCarrierNetworkConfig.getCarrierName(TEST_SSID));
+ assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag());
}
/**
@@ -198,7 +203,8 @@
when(mSubscriptionManager.getActiveSubscriptionInfoList())
.thenReturn(Arrays.asList(new SubscriptionInfo[] {updatedSubscriptionInfo}));
when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID))
- .thenReturn(generateTestConfig(updatedSsid, updatedStandardEapType));
+ .thenReturn(generateTestConfig(updatedSsid, updatedStandardEapType,
+ CarrierNetworkConfig.ENCODING_METHOD_RFC_2045));
mBroadcastReceiver.onReceive(mContext,
new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
@@ -206,11 +212,13 @@
assertFalse(mCarrierNetworkConfig.isCarrierNetwork(TEST_SSID));
assertEquals(-1, mCarrierNetworkConfig.getNetworkEapType(TEST_SSID));
assertEquals(null, mCarrierNetworkConfig.getCarrierName(TEST_SSID));
+ assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag());
// Verify that updated SSID is associated with a carrier network.
assertTrue(mCarrierNetworkConfig.isCarrierNetwork(updatedSsid));
assertEquals(updatedInternalEapType, mCarrierNetworkConfig.getNetworkEapType(updatedSsid));
assertEquals(updatedCarrierName, mCarrierNetworkConfig.getCarrierName(updatedSsid));
+ assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag());
}
/**
@@ -242,4 +250,36 @@
mContentObserver.onChange(false);
assertTrue(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable());
}
+
+ /**
+ * Verify that base64Encoding type should be {@link Base64#NO_WRAP} when carrier configuration
+ * defines RFC4648 for encoding method.
+ */
+ @Test
+ public void verifyBase64EncodingTypeWithRfc4648() {
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID))
+ .thenReturn(generateTestConfig(TEST_SSID, TEST_STANDARD_EAP_TYPE,
+ CarrierNetworkConfig.ENCODING_METHOD_RFC_4648));
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+ assertEquals(Base64.NO_WRAP, mCarrierNetworkConfig.getBase64EncodingFlag());
+ }
+
+ /**
+ * Verify that carrier network config is not generated when carrier configuration defines
+ * unsupported encoding method.
+ */
+ @Test
+ public void verifyBase64EncodingTypeWithUnsupportedEncodingMethod() {
+ String ssid = "invalid carrier AP";
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID))
+ .thenReturn(generateTestConfig(ssid, TEST_STANDARD_EAP_TYPE, 123));
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+
+ assertFalse(mCarrierNetworkConfig.isCarrierNetwork(ssid));
+ assertEquals(-1, mCarrierNetworkConfig.getNetworkEapType(ssid));
+ assertEquals(null, mCarrierNetworkConfig.getCarrierName(ssid));
+ assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag());
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java
index ef8ceb1..0c61e17 100644
--- a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java
@@ -122,8 +122,8 @@
private AddOrUpdateNetworkAnswer mAddOrUpdateNetworkAnswer;
- private void configureNewSsid(int networkId, ScanDetail scanDetail, boolean isEphemeral,
- boolean isSaved) {
+ private WifiConfiguration configureNewSsid(int networkId, ScanDetail scanDetail,
+ boolean isEphemeral, boolean isSaved) {
WifiConfiguration newConfig = ScanResultUtil.createNetworkFromScanResult(
scanDetail.getScanResult());
assertTrue("" + newConfig, WifiConfigurationUtil.validate(newConfig, true));
@@ -140,6 +140,7 @@
anyInt())).thenReturn(true);
when(mWifiConfigManager.getConfiguredNetwork(networkId)).thenReturn(newConfig);
mAddOrUpdateNetworkAnswer.addConfig(newConfig, networkId);
+ return newConfig;
}
/** Sets up test. */
@@ -334,4 +335,41 @@
verify(mConnectableListener, never()).onConnectable(any(), any(), anyInt());
assertNull(selected);
}
+
+ /**
+ * One carrier Wi-Fi networks visible and cert installed but ssid is blacklisted.
+ *
+ * Desired behavior: no networks connectable or selected
+ */
+ @Test
+ public void testAvailableButBlacklisted() {
+ String[] ssids = {CARRIER1_SSID};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3"};
+ int[] freqs = {2470};
+ String[] caps = {"[WPA2-EAP-CCMP]"};
+ int[] levels = {10};
+
+ when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true);
+
+ List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssids, bssids,
+ freqs, caps, levels, mClock);
+ WifiConfiguration blacklisted =
+ configureNewSsid(CARRIER1_NET_ID, scanDetails.get(0), true, false);
+ blacklisted.getNetworkSelectionStatus()
+ .setNetworkSelectionStatus(
+ WifiConfiguration.NetworkSelectionStatus
+ .NETWORK_SELECTION_PERMANENTLY_DISABLED);
+ when(mWifiConfigManager.getConfiguredNetwork(eq(blacklisted.configKey())))
+ .thenReturn(blacklisted);
+ when(mWifiConfigManager.tryEnableNetwork(CARRIER1_NET_ID))
+ .thenReturn(false);
+
+ WifiConfiguration selected = mDut.evaluateNetworks(scanDetails, null, null, false, false,
+ mConnectableListener);
+ verify(mWifiConfigManager).getConfiguredNetwork(eq(blacklisted.configKey()));
+
+ verify(mConnectableListener, never()).onConnectable(any(), any(), anyInt());
+ assertNull(selected);
+ }
+
}
diff --git a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkNotifierTest.java
index 34995a7..91a9a5d 100644
--- a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkNotifierTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkNotifierTest.java
@@ -51,6 +51,7 @@
import androidx.test.filters.SmallTest;
+import com.android.server.wifi.nano.WifiMetricsProto;
import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
import org.junit.Before;
@@ -72,6 +73,7 @@
private static final String TEST_SSID_2 = "Test SSID 2";
private static final int MIN_RSSI_LEVEL = -127;
private static final String CARRIER_NET_NOTIFIER_TAG = CarrierNetworkNotifier.TAG;
+ private static final int TEST_NETWORK_ID = 42;
@Mock private Context mContext;
@Mock private Resources mResources;
@@ -127,6 +129,8 @@
observerCaptor.capture());
mContentObserver = observerCaptor.getValue();
mNotificationController.handleScreenStateChanged(true);
+ when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt()))
+ .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
}
/**
@@ -686,6 +690,9 @@
mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK));
+ verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER);
+
ArgumentCaptor<Message> connectMessageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mClientModeImpl).sendMessage(connectMessageCaptor.capture());
Message connectMessage = connectMessageCaptor.getValue();
diff --git a/tests/wifitests/src/com/android/server/wifi/CellularLinkLayerStatsCollectorTest.java b/tests/wifitests/src/com/android/server/wifi/CellularLinkLayerStatsCollectorTest.java
new file mode 100644
index 0000000..8b1647f
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/CellularLinkLayerStatsCollectorTest.java
@@ -0,0 +1,319 @@
+/*
+ * 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 android.telephony.TelephonyManager.NETWORK_TYPE_CDMA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EVDO_0;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GSM;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_TD_SCDMA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.validateMockitoUsage;
+
+import android.content.Context;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoTdscdma;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthNr;
+import android.telephony.CellSignalStrengthTdscdma;
+import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.NetworkType;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.CellularLinkLayerStatsCollector}.
+ */
+@SmallTest
+public class CellularLinkLayerStatsCollectorTest {
+ private CellularLinkLayerStatsCollector mCollector;
+ private static final String TAG = "CellCollectorTest";
+ private static final int DBM_VAL = -110;
+ private static final int DB_VAL = -20;
+ private static final int DB_VAL_EVDO = 4;
+ private static final int SUBID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ MockitoSession mMockingSession = null;
+ @Mock Context mContext;
+ @Mock TelephonyManager mTelephonyManager;
+ @Mock SubscriptionManager mSubscriptionManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.TELEPHONY_SERVICE))
+ .thenReturn(mTelephonyManager);
+ when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE))
+ .thenReturn(mSubscriptionManager);
+ when(mTelephonyManager.createForSubscriptionId(anyInt()))
+ .thenReturn(mTelephonyManager);
+ mCollector = new CellularLinkLayerStatsCollector(mContext);
+ mMockingSession = mockitoSession().mockStatic(SubscriptionManager.class).startMocking();
+ when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(SUBID);
+ when(SubscriptionManager.getDefaultSubscriptionId()).thenReturn(SUBID);
+ }
+
+ @After
+ public void cleanUp() throws Exception {
+ validateMockitoUsage();
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+
+ private List<CellInfo> generateCellInfoList(@NetworkType int networkType) {
+ List<CellInfo> cil = new ArrayList<>();
+ int numCellInfo = 2;
+ for (int i = 0; i < numCellInfo; ++i) {
+ CellInfo ci;
+ if (networkType == NETWORK_TYPE_LTE) {
+ ci = new CellInfoLte();
+ } else if (networkType == NETWORK_TYPE_CDMA || networkType == NETWORK_TYPE_EVDO_0) {
+ ci = new CellInfoCdma();
+ } else if (networkType == NETWORK_TYPE_GSM) {
+ ci = new CellInfoGsm();
+ } else if (networkType == NETWORK_TYPE_TD_SCDMA) {
+ ci = new CellInfoTdscdma();
+ } else if (networkType == NETWORK_TYPE_UMTS) {
+ ci = new CellInfoWcdma();
+ } else if (networkType == NETWORK_TYPE_NR) {
+ // TODO: CellInfoNr() is not supported yet.
+ ci = new CellInfoLte();
+ } else {
+ ci = new CellInfoLte();
+ }
+ if (i == 0 && networkType != NETWORK_TYPE_UNKNOWN) {
+ ci.setRegistered(true);
+ } else {
+ ci.setRegistered(false);
+ }
+ cil.add(ci);
+ }
+ return cil;
+ }
+
+ private SignalStrength generateSignalStrength(int dBmVal, int dBVal,
+ @NetworkType int networkType) {
+ int dummy = 1000;
+ CellSignalStrengthLte mLte = new CellSignalStrengthLte();
+ CellSignalStrengthNr mNr = new CellSignalStrengthNr();
+ CellSignalStrengthGsm mGsm = new CellSignalStrengthGsm();
+ CellSignalStrengthCdma mCdma = new CellSignalStrengthCdma();
+ CellSignalStrengthTdscdma mTdscdma = new CellSignalStrengthTdscdma();
+ CellSignalStrengthWcdma mWcdma = new CellSignalStrengthWcdma();
+
+ if (networkType == NETWORK_TYPE_UNKNOWN) {
+ return new SignalStrength();
+ } else if (networkType == NETWORK_TYPE_LTE) {
+ mLte = new CellSignalStrengthLte(dummy, dBmVal, dBVal, dummy, dummy, dummy);
+ } else if (networkType == NETWORK_TYPE_CDMA) {
+ mCdma = new CellSignalStrengthCdma(dBmVal, dBVal, dBmVal, dummy,
+ SignalStrength.INVALID);
+ } else if (networkType == NETWORK_TYPE_EVDO_0) {
+ mCdma = new CellSignalStrengthCdma(dBmVal, dummy, dBmVal, dummy, dBVal);
+ } else if (networkType == NETWORK_TYPE_TD_SCDMA) {
+ mTdscdma = new CellSignalStrengthTdscdma(dummy, dummy, dBmVal);
+ } else if (networkType == NETWORK_TYPE_UMTS) {
+ mWcdma = new CellSignalStrengthWcdma(dummy, dummy, dBmVal, dBVal);
+ } else if (networkType == NETWORK_TYPE_GSM) {
+ mGsm = new CellSignalStrengthGsm(dBmVal, dummy, dummy);
+ } else if (networkType == NETWORK_TYPE_NR) {
+ mNr = new CellSignalStrengthNr(dBmVal, dummy, dBVal, dummy, dummy, dummy);
+ } else {
+ return null;
+ }
+ return new SignalStrength(mCdma, mGsm, mWcdma, mTdscdma, mLte, mNr);
+ }
+
+ private void testCollectorUpdate(@NetworkType int networkType, boolean isSignalStrengthEmpty,
+ CellularLinkLayerStats trueStats) throws Exception {
+ int dBmVal = DBM_VAL;
+ int dBVal;
+ if (networkType == NETWORK_TYPE_EVDO_0) {
+ dBVal = DB_VAL_EVDO;
+ } else {
+ dBVal = DB_VAL;
+ }
+
+ SignalStrength ss = null;
+ if (!isSignalStrengthEmpty) ss = generateSignalStrength(dBmVal, dBVal, networkType);
+ List<CellInfo> allList = generateCellInfoList(networkType);
+ when(mTelephonyManager.getSignalStrength()).thenReturn(ss);
+ when(mTelephonyManager.getAllCellInfo()).thenReturn(allList);
+ when(mTelephonyManager.getDataNetworkType()).thenReturn(networkType);
+
+ CellularLinkLayerStats mStats = mCollector.update();
+
+ assertEquals(SUBID, SubscriptionManager.getDefaultDataSubscriptionId());
+ assertEquals(SUBID, SubscriptionManager.getDefaultSubscriptionId());
+
+ assertEquals(trueStats.getSignalStrengthDbm(), mStats.getSignalStrengthDbm());
+ assertEquals(trueStats.getSignalStrengthDb(), mStats.getSignalStrengthDb());
+ assertEquals(trueStats.getDataNetworkType(), mStats.getDataNetworkType());
+ assertEquals(trueStats.getIsSameRegisteredCell(), mStats.getIsSameRegisteredCell());
+ }
+
+ @Test
+ public void testEmptySignalStrengthLte() throws Exception {
+ @NetworkType int networkType;
+ CellularLinkLayerStats trueStats = new CellularLinkLayerStats();
+
+ networkType = NETWORK_TYPE_LTE;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(SignalStrength.INVALID);
+ trueStats.setSignalStrengthDbm(SignalStrength.INVALID);
+ trueStats.setDataNetworkType(NETWORK_TYPE_UNKNOWN);
+ testCollectorUpdate(networkType, true, trueStats);
+ }
+
+ @Test
+ public void testRepeatCellInfoTypeTwice() throws Exception {
+ @NetworkType int networkType;
+ CellularLinkLayerStats trueStats = new CellularLinkLayerStats();
+
+ networkType = NETWORK_TYPE_LTE;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_LTE;
+ trueStats.setIsSameRegisteredCell(true);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_EVDO_0;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL_EVDO);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_EVDO_0;
+ trueStats.setIsSameRegisteredCell(true);
+ trueStats.setSignalStrengthDb(DB_VAL_EVDO);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_NR;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_NR;
+ trueStats.setIsSameRegisteredCell(true);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+ }
+
+ @Test
+ public void testLoopOverAllNetworksWithoutRepeat() throws Exception {
+ @NetworkType int networkType;
+ CellularLinkLayerStats trueStats = new CellularLinkLayerStats();
+
+ networkType = NETWORK_TYPE_UNKNOWN;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(SignalStrength.INVALID);
+ trueStats.setSignalStrengthDbm(SignalStrength.INVALID);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_LTE;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_CDMA;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_EVDO_0;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL_EVDO);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_TD_SCDMA;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(SignalStrength.INVALID);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_UMTS;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_GSM;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(SignalStrength.INVALID);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ networkType = NETWORK_TYPE_NR;
+ trueStats.setIsSameRegisteredCell(false);
+ trueStats.setSignalStrengthDb(DB_VAL);
+ trueStats.setSignalStrengthDbm(DBM_VAL);
+ trueStats.setDataNetworkType(networkType);
+ testCollectorUpdate(networkType, false, trueStats);
+
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/CellularLinkLayerStatsTest.java b/tests/wifitests/src/com/android/server/wifi/CellularLinkLayerStatsTest.java
new file mode 100644
index 0000000..712d653
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/CellularLinkLayerStatsTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.junit.Assert.assertEquals;
+
+import android.telephony.TelephonyManager;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.CellularLinkLayerStats}.
+ */
+@SmallTest
+public class CellularLinkLayerStatsTest {
+ private static final String TAG = "CellularStatsTest";
+
+ CellularLinkLayerStats mStats;
+
+ /**
+ * Sets up for unit test
+ */
+ @Before
+ public void setUp() throws Exception {
+ mStats = new CellularLinkLayerStats();
+ }
+
+ @After
+ public void cleanUp() throws Exception {
+ }
+
+ /**
+ * Test all set and get methods by checking if the inputs of set() match the output of get()
+ */
+ @Test
+ public void testAllSetGetMethods() throws Exception {
+ int dataNetworkType = TelephonyManager.NETWORK_TYPE_GSM;
+ mStats.setDataNetworkType(dataNetworkType);
+ assertEquals(dataNetworkType, mStats.getDataNetworkType());
+ int dbmVal = -100;
+ mStats.setSignalStrengthDbm(dbmVal);
+ assertEquals(dbmVal, mStats.getSignalStrengthDbm());
+ int dbVal = -20;
+ mStats.setSignalStrengthDb(dbVal);
+ assertEquals(dbVal, mStats.getSignalStrengthDb());
+ boolean isSameCell = true;
+ mStats.setIsSameRegisteredCell(isSameCell);
+ assertEquals(isSameCell, mStats.getIsSameRegisteredCell());
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index 86fb45f..5908bbc 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -140,6 +140,7 @@
? ClientModeImpl.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
: ClientModeImpl.NUM_LOG_RECS_VERBOSE);
private static final int FRAMEWORK_NETWORK_ID = 0;
+ private static final int PASSPOINT_NETWORK_ID = 1;
private static final int TEST_RSSI = -54;
private static final int TEST_NETWORK_ID = 54;
private static final int WPS_SUPPLICANT_NETWORK_ID = 5;
@@ -377,6 +378,7 @@
@Mock LinkProbeManager mLinkProbeManager;
@Mock PackageManager mPackageManager;
@Mock WifiLockManager mWifiLockManager;
+ @Mock AsyncChannel mNullAsyncChannel;
final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor =
ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class);
@@ -490,6 +492,7 @@
mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true);
mConnectedNetwork = spy(WifiConfigurationTestUtil.createOpenNetwork());
+ when(mNullAsyncChannel.sendMessageSynchronously(any())).thenReturn(null);
}
private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger) {
@@ -530,7 +533,7 @@
mBinderToken = Binder.clearCallingIdentity();
/* Send the BOOT_COMPLETED message to setup some CMI state. */
- mCmi.sendMessage(ClientModeImpl.CMD_BOOT_COMPLETED);
+ mCmi.handleBootCompleted();
mLooper.dispatchAll();
verify(mWifiNetworkFactory, atLeastOnce()).register();
@@ -560,7 +563,7 @@
public void createNew() throws Exception {
assertEquals("DefaultState", getCurrentState().getName());
- mCmi.sendMessage(ClientModeImpl.CMD_BOOT_COMPLETED);
+ mCmi.handleBootCompleted();
mLooper.dispatchAll();
assertEquals("DefaultState", getCurrentState().getName());
}
@@ -1027,6 +1030,39 @@
}
/**
+ * Tests that Passpoint fields in WifiInfo are reset when connecting to a non-Passpoint network
+ * during DisconnectedState.
+ * @throws Exception
+ */
+ @Test
+ public void testResetWifiInfoPasspointFields() throws Exception {
+ loadComponentsInStaMode();
+ WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork());
+ config.SSID = sWifiSsid.toString();
+ config.BSSID = sBSSID;
+ config.networkId = PASSPOINT_NETWORK_ID;
+ when(config.getOrCreateRandomizedMacAddress()).thenReturn(TEST_LOCAL_MAC_ADDRESS);
+ config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
+ setupAndStartConnectSequence(config);
+ validateSuccessfulConnectSequence(config);
+
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(PASSPOINT_NETWORK_ID, sWifiSsid, sBSSID,
+ SupplicantState.ASSOCIATING));
+ mLooper.dispatchAll();
+
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID,
+ SupplicantState.ASSOCIATING));
+ mLooper.dispatchAll();
+
+ WifiInfo wifiInfo = mCmi.getWifiInfo();
+ assertNotNull(wifiInfo);
+ assertNull(wifiInfo.getPasspointFqdn());
+ assertNull(wifiInfo.getPasspointProviderFriendlyName());
+ }
+
+ /**
* Tests the OSU information is set in WifiInfo for OSU AP connection.
*/
@Test
@@ -1056,6 +1092,40 @@
}
/**
+ * Tests that OSU fields in WifiInfo are reset when connecting to a non-OSU network during
+ * DisconnectedState.
+ * @throws Exception
+ */
+ @Test
+ public void testResetWifiInfoOsuFields() throws Exception {
+ loadComponentsInStaMode();
+ WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork());
+ osuConfig.SSID = sWifiSsid.toString();
+ osuConfig.BSSID = sBSSID;
+ osuConfig.osu = true;
+ osuConfig.networkId = PASSPOINT_NETWORK_ID;
+ osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME;
+ when(osuConfig.getOrCreateRandomizedMacAddress()).thenReturn(TEST_LOCAL_MAC_ADDRESS);
+ osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
+ setupAndStartConnectSequence(osuConfig);
+ validateSuccessfulConnectSequence(osuConfig);
+
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(PASSPOINT_NETWORK_ID, sWifiSsid, sBSSID,
+ SupplicantState.ASSOCIATING));
+ mLooper.dispatchAll();
+
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID,
+ SupplicantState.ASSOCIATING));
+ mLooper.dispatchAll();
+
+ WifiInfo wifiInfo = mCmi.getWifiInfo();
+ assertNotNull(wifiInfo);
+ assertFalse(wifiInfo.isOsuAp());
+ }
+
+ /**
* Verify that WifiStateTracker is called if wifi is disabled while connected.
*/
@Test
@@ -1173,6 +1243,30 @@
assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what);
}
+ /**
+ * Tests that manual connection to a network (from settings app) logs the correct nominator ID.
+ */
+ @Test
+ public void testManualConnectNominator() throws Exception {
+ initializeAndAddNetworkAndVerifySuccess();
+ Message msg = Message.obtain();
+ msg.what = WifiManager.CONNECT_NETWORK;
+ msg.arg1 = TEST_NETWORK_ID;
+ msg.obj = null;
+ msg.sendingUid = Process.SYSTEM_UID;
+
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = TEST_NETWORK_ID;
+
+ when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
+
+ mCmi.sendMessage(msg);
+ mLooper.dispatchAll();
+
+ verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
+ }
+
@Test
public void testDhcpFailure() throws Exception {
initializeAndAddNetworkAndVerifySuccess();
@@ -3311,38 +3405,56 @@
}
/**
- * Verifies the handling of disconnect initiated from API surface when connected to a network.
+ * Verify that a WifiIsUnusableEvent is logged and the current list of usability stats entries
+ * are labeled and saved when receiving an IP reachability lost message.
+ * @throws Exception
*/
@Test
- public void testExternalDisconnectWhenConnected() throws Exception {
+ public void verifyIpReachabilityLostMsgUpdatesWifiUsabilityMetrics() throws Exception {
connect();
- mCmi.disconnectCommandExternal(); // Simulate settings invoking this.
+ mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST);
mLooper.dispatchAll();
-
- verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
- verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_API);
- // verify that we temp blacklist the network.
- verify(mWifiConfigManager).updateNetworkSelectionStatus(0,
- WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER_DISCONNECT);
+ verify(mWifiMetrics).logWifiIsUnusableEvent(
+ WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
+ verify(mWifiMetrics).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
+ WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST);
}
/**
- * Verifies the handling of disconnect initiated internally when connected to a network.
+ * Verify that syncGetAllMatchingFqdnsForScanResults does not return null from a null message.
*/
@Test
- public void testInternalDisconnectWhenConnected() throws Exception {
- connect();
+ public void testSyncGetAllMatchingFqdnsForScanResult_doesNotReturnNull() {
+ assertNotNull(
+ mCmi.syncGetAllMatchingFqdnsForScanResults(null, mNullAsyncChannel));
+ }
- mCmi.disconnectCommandInternal(); // Internal stack initiated disconnect.
- mLooper.dispatchAll();
+ /**
+ * Verify that syncGetMatchingOsuProviders does not return null from a null message.
+ */
+ @Test
+ public void testSyncGetMatchingOsuProviders_doesNotReturnNull() {
+ assertNotNull(
+ mCmi.syncGetMatchingOsuProviders(null, mNullAsyncChannel));
+ }
- verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
- verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_GENERIC);
- // verify that we don't temp blacklist the network.
- verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(0,
- WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER_DISCONNECT);
+ /**
+ * Verify that syncGetMatchingPasspointConfigsForOsuProviders does not return null from a null
+ * message.
+ */
+ @Test
+ public void testSyncGetMatchingPasspointConfigsForOsuProviders_doesNotReturnNull() {
+ assertNotNull(
+ mCmi.syncGetMatchingPasspointConfigsForOsuProviders(null, mNullAsyncChannel));
+ }
+
+ /**
+ * Verify that syncGetWifiConfigsForPasspointProfiles does not return null from a null message.
+ */
+ @Test
+ public void testSyncGetWifiConfigsForPasspointProfiles_doesNotReturnNull() {
+ assertNotNull(
+ mCmi.syncGetWifiConfigsForPasspointProfiles(null, mNullAsyncChannel));
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionEvaluatorTest.java
index 4f494c0..fadfc6b 100644
--- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionEvaluatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionEvaluatorTest.java
@@ -125,7 +125,7 @@
int[] securities = {SECURITY_PSK};
boolean[] appInteractions = {true};
boolean[] meteredness = {true};
- int[] priorities = {0};
+ int[] priorities = {-1};
int[] uids = {TEST_UID};
String[] packageNames = {TEST_PACKAGE};
@@ -148,7 +148,7 @@
assertNotNull(candidate);
assertEquals(suggestionSsids[0] , candidate.SSID);
- validateConnectableNetworks(connectableNetworks, new String[] {scanSsids[0]});
+ validateConnectableNetworks(connectableNetworks, scanSsids[0]);
verifyAddToWifiConfigManager(suggestions[0].wifiConfiguration);
}
@@ -170,7 +170,7 @@
int[] securities = {SECURITY_PSK, SECURITY_PSK};
boolean[] appInteractions = {true, true};
boolean[] meteredness = {true, true};
- int[] priorities = {0, 1};
+ int[] priorities = {-1, -1};
int[] uids = {TEST_UID, TEST_UID};
String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE};
@@ -194,14 +194,60 @@
assertNotNull(candidate);
assertEquals(suggestionSsids[1] , candidate.SSID);
- validateConnectableNetworks(connectableNetworks, scanSsids);
+ validateConnectableNetworks(connectableNetworks, scanSsids[0], scanSsids[1]);
- verifyAddToWifiConfigManager(suggestions[0].wifiConfiguration,
+ verifyAddToWifiConfigManager(suggestions[1].wifiConfiguration,
suggestions[1].wifiConfiguration);
}
/**
* Ensure that we select the network suggestion corresponding to the scan result with
+ * higest priority.
+ * Expected candidate: suggestionSsids[0]
+ * Expected connectable Networks: {suggestionSsids[0], suggestionSsids[1]}
+ */
+ @Test
+ public void testSelectNetworkSuggestionForMultipleMatchHighPriorityWins() {
+ String[] scanSsids = {"test1", "test2"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] freqs = {2470, 2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-56, -45};
+ String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\""};
+ int[] securities = {SECURITY_PSK, SECURITY_PSK};
+ boolean[] appInteractions = {true, true};
+ boolean[] meteredness = {true, true};
+ int[] priorities = {5, 1};
+ int[] uids = {TEST_UID, TEST_UID};
+ String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE};
+
+ ScanDetail[] scanDetails =
+ buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock);
+ WifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, securities,
+ appInteractions, meteredness, priorities, uids, packageNames);
+ // Link the scan result with suggestions.
+ linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions);
+ // setup config manager interactions.
+ setupAddToWifiConfigManager(suggestions[0].wifiConfiguration,
+ suggestions[1].wifiConfiguration);
+
+ List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
+ WifiConfiguration candidate = mNetworkSuggestionEvaluator.evaluateNetworks(
+ Arrays.asList(scanDetails), null, null, true, false,
+ (ScanDetail scanDetail, WifiConfiguration configuration, int score) -> {
+ connectableNetworks.add(Pair.create(scanDetail, configuration));
+ });
+
+ assertNotNull(candidate);
+ assertEquals(suggestionSsids[0] , candidate.SSID);
+
+ validateConnectableNetworks(connectableNetworks, scanSsids[0]);
+
+ verifyAddToWifiConfigManager(suggestions[0].wifiConfiguration);
+ }
+
+ /**
+ * Ensure that we select the network suggestion corresponding to the scan result with
* highest RSSI. The lower RSSI scan result has multiple matching suggestions
* (should pick any one in the connectable networks).
*
@@ -221,7 +267,7 @@
int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
boolean[] appInteractions = {true, true, false};
boolean[] meteredness = {true, true, false};
- int[] priorities = {0, 1, 0};
+ int[] priorities = {-1, -1, -1};
int[] uids = {TEST_UID, TEST_UID, TEST_UID_OTHER};
String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE, TEST_PACKAGE_OTHER};
@@ -252,6 +298,66 @@
}
/**
+ * Ensure that we select the network suggestion with the higest priority among network
+ * suggestions from the same package. Among different packages, pick the suggestion
+ * corresponding to the scan result with highest RSSI.
+ *
+ * The suggestion[1] has higher priority than suggestion[0] even though it has lower RSSI than
+ * suggestion[0].
+ *
+ * Expected candidate: suggestionSsids[1]
+ * Expected connectable Networks: {suggestionSsids[1],
+ * (suggestionSsids[2],
+ * suggestionSsids[3]}
+ */
+ @Test
+ public void
+ testSelectNetworkSuggestionForMultipleMatchWithMultipleSuggestionsHighPriorityWins() {
+ String[] scanSsids = {"test1", "test2", "test3", "test4"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:fc:de:34:12",
+ "6c:fd:a1:11:11:98"};
+ int[] freqs = {2470, 2437, 2470, 2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]",
+ "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-23, -45, -56, -65};
+ String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\"",
+ "\"" + scanSsids[2] + "\"", "\"" + scanSsids[3] + "\""};
+ int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
+ boolean[] appInteractions = {true, true, false, false};
+ boolean[] meteredness = {true, true, false, false};
+ int[] priorities = {0, 5, -1, -1};
+ int[] uids = {TEST_UID, TEST_UID, TEST_UID_OTHER, TEST_UID_OTHER};
+ String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE, TEST_PACKAGE_OTHER,
+ TEST_PACKAGE_OTHER};
+
+ ScanDetail[] scanDetails =
+ buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock);
+ WifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, securities,
+ appInteractions, meteredness, priorities, uids, packageNames);
+ // Link the scan result with suggestions.
+ linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions);
+ // setup config manager interactions.
+ setupAddToWifiConfigManager(suggestions[0].wifiConfiguration,
+ suggestions[1].wifiConfiguration, suggestions[2].wifiConfiguration,
+ suggestions[3].wifiConfiguration);
+
+ List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
+ WifiConfiguration candidate = mNetworkSuggestionEvaluator.evaluateNetworks(
+ Arrays.asList(scanDetails), null, null, true, false,
+ (ScanDetail scanDetail, WifiConfiguration configuration, int score) -> {
+ connectableNetworks.add(Pair.create(scanDetail, configuration));
+ });
+
+ assertNotNull(candidate);
+ assertEquals(suggestionSsids[1] , candidate.SSID);
+
+ validateConnectableNetworks(connectableNetworks, scanSsids[1], scanSsids[2], scanSsids[3]);
+
+ verifyAddToWifiConfigManager(suggestions[1].wifiConfiguration,
+ suggestions[2].wifiConfiguration, suggestions[3].wifiConfiguration);
+ }
+
+ /**
* Ensure that we select the only matching network suggestion, but return null because
* we failed the {@link WifiConfigManager} interactions.
* Expected candidate: null.
@@ -268,7 +374,7 @@
int[] securities = {SECURITY_PSK};
boolean[] appInteractions = {true};
boolean[] meteredness = {true};
- int[] priorities = {0};
+ int[] priorities = {-1};
int[] uids = {TEST_UID};
String[] packageNames = {TEST_PACKAGE};
@@ -292,7 +398,7 @@
assertNull(candidate);
assertTrue(connectableNetworks.isEmpty());
- verify(mWifiConfigManager, times(suggestionSsids.length))
+ verify(mWifiConfigManager, times(scanSsids.length))
.wasEphemeralNetworkDeleted(anyString());
verify(mWifiConfigManager).getConfiguredNetwork(eq(
suggestions[0].wifiConfiguration.configKey()));
@@ -319,7 +425,7 @@
int[] securities = {SECURITY_PSK};
boolean[] appInteractions = {true};
boolean[] meteredness = {true};
- int[] priorities = {0};
+ int[] priorities = {-1};
int[] uids = {TEST_UID};
String[] packageNames = {TEST_PACKAGE};
@@ -346,7 +452,7 @@
validateConnectableNetworks(connectableNetworks, new String[] {scanSsids[0]});
// check for any saved networks.
- verify(mWifiConfigManager, times(suggestionSsids.length))
+ verify(mWifiConfigManager, times(scanSsids.length))
.wasEphemeralNetworkDeleted(anyString());
verify(mWifiConfigManager).getConfiguredNetwork(candidate.configKey());
// Verify we did not try to add any new networks or other interactions with
@@ -371,7 +477,7 @@
int[] securities = {SECURITY_PSK};
boolean[] appInteractions = {true};
boolean[] meteredness = {true};
- int[] priorities = {0};
+ int[] priorities = {-1};
int[] uids = {TEST_UID};
String[] packageNames = {TEST_PACKAGE};
@@ -396,7 +502,7 @@
assertNull(candidate);
assertTrue(connectableNetworks.isEmpty());
- verify(mWifiConfigManager, times(suggestionSsids.length))
+ verify(mWifiConfigManager, times(scanSsids.length))
.wasEphemeralNetworkDeleted(anyString());
// Verify we did not try to add any new networks or other interactions with
// WifiConfigManager.
@@ -421,7 +527,7 @@
int[] securities = {SECURITY_PSK};
boolean[] appInteractions = {true};
boolean[] meteredness = {true};
- int[] priorities = {0};
+ int[] priorities = {-1};
int[] uids = {TEST_UID};
String[] packageNames = {TEST_PACKAGE};
@@ -450,7 +556,7 @@
assertNull(candidate);
assertTrue(connectableNetworks.isEmpty());
- verify(mWifiConfigManager, times(suggestionSsids.length))
+ verify(mWifiConfigManager, times(scanSsids.length))
.wasEphemeralNetworkDeleted(anyString());
verify(mWifiConfigManager).getConfiguredNetwork(eq(
suggestions[0].wifiConfiguration.configKey()));
@@ -479,7 +585,7 @@
int[] securities = {SECURITY_PSK};
boolean[] appInteractions = {true};
boolean[] meteredness = {true};
- int[] priorities = {0};
+ int[] priorities = {-1};
int[] uids = {TEST_UID};
String[] packageNames = {TEST_PACKAGE};
@@ -512,7 +618,7 @@
validateConnectableNetworks(connectableNetworks, new String[] {scanSsids[0]});
- verify(mWifiConfigManager, times(suggestionSsids.length))
+ verify(mWifiConfigManager, times(scanSsids.length))
.wasEphemeralNetworkDeleted(anyString());
verify(mWifiConfigManager).getConfiguredNetwork(eq(
suggestions[0].wifiConfiguration.configKey()));
@@ -555,7 +661,7 @@
private void verifyAddToWifiConfigManager(WifiConfiguration...candidates) {
// check for any saved networks.
- verify(mWifiConfigManager, times(candidates.length)).getConfiguredNetwork(anyString());
+ verify(mWifiConfigManager, atLeast(candidates.length)).getConfiguredNetwork(anyString());
ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor =
ArgumentCaptor.forClass(WifiConfiguration.class);
@@ -675,8 +781,8 @@
}
private void validateConnectableNetworks(List<Pair<ScanDetail, WifiConfiguration>> actual,
- String[] expectedSsids) {
- Set<String> expectedSsidSet = new HashSet<String>(Arrays.asList(expectedSsids));
+ String...expectedSsids) {
+ Set<String> expectedSsidSet = new HashSet<>(Arrays.asList(expectedSsids));
assertEquals(expectedSsidSet.size(), actual.size());
for (Pair<ScanDetail, WifiConfiguration> candidate : actual) {
diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
index e165dcf..5e1e728 100644
--- a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
@@ -51,6 +51,7 @@
import androidx.test.filters.SmallTest;
+import com.android.server.wifi.nano.WifiMetricsProto;
import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
import org.junit.Before;
@@ -72,6 +73,7 @@
private static final String TEST_SSID_2 = "Test SSID 2";
private static final int MIN_RSSI_LEVEL = -127;
private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG;
+ private static final int TEST_NETWORK_ID = 42;
@Mock private Context mContext;
@Mock private Resources mResources;
@@ -126,6 +128,8 @@
observerCaptor.capture());
mContentObserver = observerCaptor.getValue();
mNotificationController.handleScreenStateChanged(true);
+ when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt()))
+ .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
}
/**
@@ -681,6 +685,9 @@
mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK));
+ verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE);
+
ArgumentCaptor<Message> connectMessageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mClientModeImpl).sendMessage(connectMessageCaptor.capture());
Message connectMessage = connectMessageCaptor.getValue();
diff --git a/tests/wifitests/src/com/android/server/wifi/ScoredNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/ScoredNetworkEvaluatorTest.java
index 4643876..d1de03c 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScoredNetworkEvaluatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScoredNetworkEvaluatorTest.java
@@ -75,6 +75,7 @@
@Mock private WifiPermissionsUtil mWifiPermissionsUtil;
@Mock private OnConnectableListener mOnConnectableListener;
@Captor private ArgumentCaptor<NetworkKey[]> mNetworkKeyArrayCaptor;
+ @Captor private ArgumentCaptor<WifiConfiguration> mWifiConfigCaptor;
private WifiNetworkScoreCache mScoreCache;
private ScoredNetworkEvaluator mScoredNetworkEvaluator;
@@ -272,6 +273,51 @@
}
/**
+ * When we have created a new ephemeral network, make sure that mOnConnectableListener
+ * is called.
+ */
+ @Test
+ public void testEvaluateNetworks_newEphemeralNetworkMustBeReportedAsConnectable() {
+ String[] ssids = {"\"test1\"", "\"test2\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] freqs = {2470, 2437};
+ String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"};
+ int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10};
+ Integer[] scores = {null, 120};
+ boolean[] meteredHints = {false, false};
+
+ List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
+ ssids, bssids, freqs, caps, levels, mClock);
+ WifiNetworkSelectorTestUtil.configureScoreCache(mScoreCache,
+ scanDetails, scores, meteredHints);
+
+ ScanResult scanResult = scanDetails.get(1).getScanResult();
+ WifiConfiguration ephemeralNetworkConfig = WifiNetworkSelectorTestUtil
+ .setupEphemeralNetwork(mWifiConfigManager, 1, scanDetails.get(1), meteredHints[1]);
+
+ // No saved networks.
+ when(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(any(ScanDetail.class)))
+ .thenReturn(null);
+
+ // But when we create one, this is should be it.
+ when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt()))
+ .thenReturn(new NetworkUpdateResult(1));
+
+ // Untrusted networks allowed.
+ WifiConfiguration candidate = mScoredNetworkEvaluator.evaluateNetworks(scanDetails,
+ null, null, false, true, mOnConnectableListener);
+
+ WifiConfigurationTestUtil.assertConfigurationEqual(ephemeralNetworkConfig, candidate);
+ WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
+ scanResult, candidate);
+ assertEquals(meteredHints[1], candidate.meteredHint);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
+ }
+
+ /**
* When no saved networks available, choose the available ephemeral networks
* if untrusted networks are allowed.
*/
@@ -306,6 +352,10 @@
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanResult, candidate);
assertEquals(meteredHints[1], candidate.meteredHint);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -346,6 +396,10 @@
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanResults[1], candidate);
assertEquals(meteredHints[1], candidate.meteredHint);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -411,6 +465,10 @@
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanDetails.get(0).getScanResult(), candidate);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -443,6 +501,10 @@
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanDetails.get(1).getScanResult(), candidate);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -476,6 +538,10 @@
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanDetails.get(0).getScanResult(), candidate);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -529,6 +595,10 @@
WifiConfigurationTestUtil.assertConfigurationEqual(ephemeralNetworkConfig, candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
ephemeralScanResult, candidate);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -601,6 +671,10 @@
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanResults[1], candidate);
assertEquals(meteredHints[1], candidate.meteredHint);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
}
/**
@@ -633,5 +707,10 @@
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanDetails.get(1).getScanResult(), candidate);
+ verify(mOnConnectableListener, atLeastOnce())
+ .onConnectable(any(), mWifiConfigCaptor.capture(), anyInt());
+ assertTrue(mWifiConfigCaptor.getAllValues().stream()
+ .anyMatch(c -> c.networkId == candidate.networkId));
+
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 2fe8590..d218089 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -16,8 +16,6 @@
package com.android.server.wifi;
-import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX;
-
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -129,6 +127,7 @@
@Mock private RandomizedMacStoreData mRandomizedMacStoreData;
@Mock private WifiConfigManager.OnSavedNetworkUpdateListener mWcmListener;
@Mock private FrameworkFacade mFrameworkFacade;
+ @Mock private CarrierNetworkConfig mCarrierNetworkConfig;
private MockResources mResources;
private InOrder mContextConfigStoreMockOrder;
@@ -207,6 +206,7 @@
when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
when(mWifiInjector.getWifiLastResortWatchdog().shouldIgnoreSsidUpdate())
.thenReturn(false);
+ when(mWifiInjector.getCarrierNetworkConfig()).thenReturn(mCarrierNetworkConfig);
createWifiConfigManager();
mWifiConfigManager.setOnSavedNetworkUpdateListener(mWcmListener);
ArgumentCaptor<ContentObserver> observerCaptor =
@@ -358,7 +358,7 @@
WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
Map<String, String> randomizedMacAddressMapping = new HashMap<>();
final String randMac = "12:23:34:45:56:67";
- randomizedMacAddressMapping.put(openNetwork.configKey(), randMac);
+ randomizedMacAddressMapping.put(openNetwork.getSsidAndSecurityTypeString(), randMac);
assertNotEquals(randMac, openNetwork.getRandomizedMacAddress());
when(mRandomizedMacStoreData.getMacMapping()).thenReturn(randomizedMacAddressMapping);
@@ -3318,6 +3318,81 @@
}
/**
+ * Verifies that the store read after bootup received after
+ * a previous user unlock and user switch via {@link WifiConfigManager#handleUserSwitch(int)}
+ * results in a user store read.
+ */
+ @Test
+ public void testHandleBootupAfterPreviousUserUnlockAndSwitch() throws Exception {
+ int user1 = TEST_DEFAULT_USER;
+ int user2 = TEST_DEFAULT_USER + 1;
+ setupUserProfiles(user2);
+
+ // Unlock the user1 (default user) for the first time and ensure that we don't read the data
+ // (need to wait for loadFromStore invocation).
+ mWifiConfigManager.handleUserUnlock(user1);
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
+ .switchUserStoresAndRead(any(List.class));
+
+ // Switch from user1 to user2 and ensure that we don't read or write any data
+ // (need to wait for loadFromStore invocation).
+ mWifiConfigManager.handleUserSwitch(user2);
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
+ .switchUserStoresAndRead(any(List.class));
+
+ // Now load from the store.
+ assertTrue(mWifiConfigManager.loadFromStore());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore).read();
+
+ // Unlock the user2 and ensure that we read from the user store.
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
+ mWifiConfigManager.handleUserUnlock(user2);
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore)
+ .switchUserStoresAndRead(any(List.class));
+ }
+
+ /**
+ * Verifies that the store read after bootup received after
+ * a user switch and unlock of a previous user via {@link WifiConfigManager#
+ * handleUserSwitch(int)} results in a user store read.
+ */
+ @Test
+ public void testHandleBootupAfterUserSwitchAndPreviousUserUnlock() throws Exception {
+ int user1 = TEST_DEFAULT_USER;
+ int user2 = TEST_DEFAULT_USER + 1;
+ setupUserProfiles(user2);
+
+ // Switch from user1 to user2 and ensure that we don't read or write any data
+ // (need to wait for loadFromStore invocation).
+ mWifiConfigManager.handleUserSwitch(user2);
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
+ .switchUserStoresAndRead(any(List.class));
+
+ // Unlock the user1 for the first time and ensure that we don't read the data
+ mWifiConfigManager.handleUserUnlock(user1);
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
+ .switchUserStoresAndRead(any(List.class));
+
+ // Now load from the store.
+ assertTrue(mWifiConfigManager.loadFromStore());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore).read();
+
+ // Unlock the user2 and ensure that we read from the user store.
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
+ mWifiConfigManager.handleUserUnlock(user2);
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore)
+ .switchUserStoresAndRead(any(List.class));
+ }
+
+ /**
* Verifies the foreground user unlock via {@link WifiConfigManager#handleUserUnlock(int)} does
* not always result in a store read unless the user had switched or just booted up.
*/
@@ -4980,7 +5055,7 @@
NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP,
retrievedDisableTime);
verifyUpdateNetworkStatus(retrievedNetwork, WifiConfiguration.Status.ENABLED);
- } else if (reason < NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX) {
+ } else if (reason < NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) {
// For temporarily disabled networks, we need to ensure that the current status remains
// until the threshold is crossed.
assertEquals(temporaryDisableReasonCounter, retrievedDisableReasonCounter);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java
index 1cc0926..e0acd1f 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java
@@ -16,7 +16,7 @@
package com.android.server.wifi;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
@@ -31,6 +31,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Locale;
/**
@@ -196,4 +198,28 @@
mWifiCountryCode.setCountryCode(telephonyCountryCodeLower);
verify(mWifiNative).setCountryCode(any(), eq(telephonyCountryCodeUpper));
}
+ /**
+ * Verifies that dump() does not fail
+ */
+ @Test
+ public void dumpDoesNotFail() {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+
+ mWifiCountryCode = new WifiCountryCode(
+ null,
+ null,
+ false /* config_wifi_revert_country_code_on_cellular_loss */);
+
+ mWifiCountryCode.dump(null, pw, null);
+ String dumpCountryCodeStr = sw.toString();
+
+ assertTrue(dumpCountryCodeStr.contains("mDriverCountryCode"));
+ assertTrue(dumpCountryCodeStr.contains("mTelephonyCountryCode"));
+ assertTrue(dumpCountryCodeStr.contains("mDefaultCountryCode"));
+ assertTrue(dumpCountryCodeStr.contains("mTelephonyCountryTimestamp"));
+ assertTrue(dumpCountryCodeStr.contains("mDriverCountryTimestamp"));
+ assertTrue(dumpCountryCodeStr.contains("mReadyTimestamp"));
+ assertTrue(dumpCountryCodeStr.contains("mReady"));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
new file mode 100644
index 0000000..7079a2d
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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 org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.net.wifi.WifiEnterpriseConfig;
+import android.os.Process;
+import android.security.Credentials;
+import android.security.KeyStore;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.WifiConfigManager}.
+ */
+@SmallTest
+public class WifiKeyStoreTest {
+ @Mock private WifiEnterpriseConfig mWifiEnterpriseConfig;
+ @Mock private KeyStore mKeyStore;
+
+ private WifiKeyStore mWifiKeyStore;
+ private static final String USER_CERT_ALIAS = "aabbccddee";
+ private static final String [] USER_CA_CERT_ALIAS = {"aacccddd", "bbbqqqqmmm"};
+
+ /**
+ * Setup the mocks and an instance of WifiConfigManager before each test.
+ */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mWifiKeyStore = new WifiKeyStore(mKeyStore);
+
+ when(mWifiEnterpriseConfig.getClientCertificateAlias()).thenReturn(USER_CERT_ALIAS);
+ when(mWifiEnterpriseConfig.getCaCertificateAliases())
+ .thenReturn(USER_CA_CERT_ALIAS);
+ }
+
+ /**
+ * Called after each test
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ }
+
+ /**
+ * Verifies that keys and certs are removed when they were installed by an app.
+ */
+ @Test
+ public void testRemoveKeysForAppInstalledCerts() {
+ when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(true);
+ when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(true);
+ mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+
+ // Method calls the KeyStore#delete method 4 times, user key, user cert, and 2 CA cert
+ verify(mKeyStore).delete(Credentials.USER_PRIVATE_KEY + USER_CERT_ALIAS, Process.WIFI_UID);
+ verify(mKeyStore).delete(Credentials.USER_CERTIFICATE + USER_CERT_ALIAS, Process.WIFI_UID);
+ verify(mKeyStore).delete(Credentials.CA_CERTIFICATE + USER_CA_CERT_ALIAS[0],
+ Process.WIFI_UID);
+ verify(mKeyStore).delete(Credentials.CA_CERTIFICATE + USER_CA_CERT_ALIAS[1],
+ Process.WIFI_UID);
+ }
+
+ /**
+ * Verifies that keys and certs are removed when they were installed by an app and not removed
+ * when CA certs are installed by the user.
+ */
+ @Test
+ public void testRemoveKeysForMixedInstalledCerts1() {
+ when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(true);
+ when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false);
+ mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+
+ // Method calls the KeyStore#delete method 2 times: user key and user cert
+ verify(mKeyStore).delete(Credentials.USER_PRIVATE_KEY + USER_CERT_ALIAS, Process.WIFI_UID);
+ verify(mKeyStore).delete(Credentials.USER_CERTIFICATE + USER_CERT_ALIAS, Process.WIFI_UID);
+ verifyNoMoreInteractions(mKeyStore);
+ }
+
+ /**
+ * Verifies that keys and certs are not removed when they were installed by the user and
+ * removed when CA certs are installed by the app.
+ */
+ @Test
+ public void testRemoveKeysForMixedInstalledCerts2() {
+ when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false);
+ when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(true);
+ mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+
+ // Method calls the KeyStore#delete method 2 times: 2 CA certs
+ verify(mKeyStore).delete(Credentials.CA_CERTIFICATE + USER_CA_CERT_ALIAS[0],
+ Process.WIFI_UID);
+ verify(mKeyStore).delete(Credentials.CA_CERTIFICATE + USER_CA_CERT_ALIAS[1],
+ Process.WIFI_UID);
+ verifyNoMoreInteractions(mKeyStore);
+ }
+
+ /**
+ * Verifies that keys and certs are not removed when they were installed by the user.
+ */
+ @Test
+ public void testRemoveKeysForUserInstalledCerts() {
+ when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false);
+ when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false);
+ mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+ verifyNoMoreInteractions(mKeyStore);
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java
index 9284360..a51a7a8 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java
@@ -61,6 +61,7 @@
private ActivityManager.OnUidImportanceListener mUidImportanceListener;
WifiLockManager mWifiLockManager;
+ @Mock Clock mClock;
@Mock IBatteryStats mBatteryStats;
@Mock IBinder mBinder;
@Mock IBinder mBinder2;
@@ -72,6 +73,7 @@
@Mock ActivityManager mActivityManager;
@Mock WifiAsyncChannel mChannel;
@Mock WifiHandler mCmiHandler;
+ @Mock WifiMetrics mWifiMetrics;
TestLooper mLooper;
/**
@@ -93,7 +95,7 @@
when(mClientModeImpl.getHandler()).thenReturn(mCmiHandler);
mWifiLockManager = new WifiLockManager(mContext, mBatteryStats,
- mClientModeImpl, mFrameworkFacade, mLooper.getLooper());
+ mClientModeImpl, mFrameworkFacade, mLooper.getLooper(), mClock, mWifiMetrics);
connectAsyncChannel();
}
@@ -224,6 +226,8 @@
public void releaseWifiLockShouldSucceed() throws Exception {
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource);
releaseWifiLockSuccessful(mBinder);
+ verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode());
}
@@ -420,6 +424,8 @@
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
}
/**
@@ -447,15 +453,22 @@
// Release the first lock
releaseWifiLockSuccessful(mBinder);
+ verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
+
assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
// Release the second lock
releaseWifiLockSuccessful(mBinder2);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
}
/**
@@ -546,9 +559,12 @@
inOrder.verify(mClientModeImpl).setPowerSave(false);
releaseWifiLockSuccessful(mBinder);
+ verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics, never()).addWifiLockActiveSession(anyInt(), anyLong());
// Now attempting adding some other lock, WifiLockManager should retry setPowerSave()
when(mClientModeImpl.setPowerSave(true)).thenReturn(true);
@@ -557,6 +573,8 @@
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
}
/**
@@ -580,6 +598,8 @@
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
}
/**
@@ -602,6 +622,8 @@
inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
releaseWifiLockSuccessful(mBinder);
+ verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
@@ -610,6 +632,8 @@
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
}
/**
@@ -711,6 +735,7 @@
// Set screen on, and app foreground
mWifiLockManager.handleScreenStateChanged(true);
when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
+ when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
when(mClientModeImpl.syncGetSupportedFeatures(any()))
.thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
@@ -718,6 +743,7 @@
mBinder, mWorkSource);
verify(mClientModeImpl).setLowLatencyMode(true);
+ verify(mClientModeImpl).setPowerSave(false);
}
/**
@@ -736,6 +762,7 @@
mBinder, mWorkSource);
verify(mClientModeImpl).setPowerSave(false);
+ verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
}
/**
@@ -752,17 +779,22 @@
// Make sure setLowLatencyMode() is successful
when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
InOrder inOrder = inOrder(mClientModeImpl);
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "",
mBinder, mWorkSource);
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
releaseLowLatencyWifiLockSuccessful(mBinder);
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ anyLong());
}
/**
@@ -795,6 +827,34 @@
}
/**
+ * Test when acquire of low-latency lock succeeds in enable low latency
+ * but fails to disable power save, then low latency mode is reverted
+ */
+ @Test
+ public void testLatencyfail2DisablePowerSave() throws Exception {
+ InOrder inOrder = inOrder(mClientModeImpl);
+
+ // Set screen on, and app is foreground
+ mWifiLockManager.handleScreenStateChanged(true);
+ when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
+ when(mClientModeImpl.syncGetSupportedFeatures(any()))
+ .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+
+ // Succeed to setLowLatencyMode()
+ when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ // Fail to setPowerSave()
+ when(mClientModeImpl.setPowerSave(false)).thenReturn(false);
+
+ acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "",
+ mBinder, mWorkSource);
+ assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
+ mWifiLockManager.getStrongestLockMode());
+ inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
+ inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ }
+
+ /**
* Test when a low-latency lock is acquired (foreground app, screen-on),
* then, screen go off, then low-latency mode is turned off.
*/
@@ -808,6 +868,7 @@
// Make sure setLowLatencyMode() is successful
when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
InOrder inOrder = inOrder(mClientModeImpl);
@@ -816,11 +877,15 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
mWifiLockManager.handleScreenStateChanged(false);
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ anyLong());
}
/**
@@ -837,6 +902,7 @@
// Make sure setLowLatencyMode() is successful
when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
InOrder inOrder = inOrder(mClientModeImpl);
@@ -847,6 +913,7 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
/* App going to background */
mUidImportanceListener.onUidImportance(DEFAULT_TEST_UID_1,
@@ -855,6 +922,9 @@
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ anyLong());
}
/**
@@ -882,6 +952,7 @@
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
/* App going to foreground */
mUidImportanceListener.onUidImportance(DEFAULT_TEST_UID_1,
@@ -891,6 +962,7 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
}
/**
@@ -933,7 +1005,10 @@
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
}
/**
@@ -957,10 +1032,14 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
assertTrue(mWifiLockManager.forceLowLatencyMode(false));
assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ anyLong());
}
/**
@@ -969,6 +1048,7 @@
@Test
public void testForceLowLatencyScreenOff() throws Exception {
when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
mWifiLockManager.handleScreenStateChanged(false);
when(mClientModeImpl.syncGetSupportedFeatures(any()))
.thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
@@ -982,16 +1062,19 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
mWifiLockManager.handleScreenStateChanged(true);
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
mWifiLockManager.handleScreenStateChanged(false);
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
}
/**
@@ -1000,6 +1083,7 @@
@Test
public void testForceLowLatencyAcqRelLowLatency() throws Exception {
when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
mWifiLockManager.handleScreenStateChanged(true);
when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
when(mClientModeImpl.syncGetSupportedFeatures(any()))
@@ -1012,21 +1096,27 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
assertTrue(mWifiLockManager.forceLowLatencyMode(true));
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
releaseLowLatencyWifiLockSuccessful(mBinder);
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
assertTrue(mWifiLockManager.forceLowLatencyMode(false));
assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ anyLong());
}
/**
@@ -1035,6 +1125,7 @@
@Test
public void testForceLowLatencyTwice() throws Exception {
when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
when(mClientModeImpl.syncGetSupportedFeatures(any()))
.thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
mWifiLockManager.updateWifiClientConnected(true);
@@ -1045,11 +1136,13 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
assertTrue(mWifiLockManager.forceLowLatencyMode(true));
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean());
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
}
/**
@@ -1074,7 +1167,10 @@
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
}
/**
@@ -1094,11 +1190,15 @@
assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ inOrder.verify(mClientModeImpl).setPowerSave(false);
assertTrue(mWifiLockManager.forceHiPerfMode(true));
assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(false);
+ inOrder.verify(mClientModeImpl).setPowerSave(true);
+ verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ anyLong());
inOrder.verify(mClientModeImpl).setPowerSave(false);
}
@@ -1122,6 +1222,8 @@
assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF,
mWifiLockManager.getStrongestLockMode());
inOrder.verify(mClientModeImpl).setLowLatencyMode(true);
+ // Since setLowLatencyMode() failed, no call to setPowerSave()
+ inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean());
}
/**
@@ -1169,6 +1271,97 @@
}
/**
+ * Test that reporting of metrics for hi-perf lock acquistion is correct for both acquisition
+ * time and active time.
+ */
+ @Test
+ public void testHighPerfLockMetrics() throws Exception {
+ long acquireTime = 1000;
+ long activationTime = 2000;
+ long deactivationTime = 3000;
+ long releaseTime = 4000;
+
+ // Make sure setPowerSave() is successful
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
+
+ InOrder inOrder = inOrder(mWifiMetrics);
+
+ // Acquire the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(acquireTime);
+ assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "",
+ mBinder, mWorkSource));
+
+ // Activate the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(activationTime);
+ mWifiLockManager.updateWifiClientConnected(true);
+
+ // Deactivate the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(deactivationTime);
+ mWifiLockManager.updateWifiClientConnected(false);
+
+ inOrder.verify(mWifiMetrics).addWifiLockActiveSession(
+ eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ eq(deactivationTime - activationTime));
+
+ // Release the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(releaseTime);
+ releaseWifiLockSuccessful_noBatteryStats(mBinder);
+
+ inOrder.verify(mWifiMetrics).addWifiLockAcqSession(
+ eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ eq(releaseTime - acquireTime));
+ }
+
+ /**
+ * Test that reporting of metrics for low-latency lock acquistion is correct for
+ * both acquisition time and active time.
+ */
+ @Test
+ public void testLowLatencyLockMetrics() throws Exception {
+ long acquireTime = 1000;
+ long activationTime = 2000;
+ long deactivationTime = 3000;
+ long releaseTime = 4000;
+
+ // Make sure setLowLatencyMode()/setPowerSave() is successful
+ when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true);
+ when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true);
+
+ // Set condition for activation of low-latency (except connection to AP)
+ mWifiLockManager.handleScreenStateChanged(true);
+ when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
+ when(mClientModeImpl.syncGetSupportedFeatures(any()))
+ .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+
+ InOrder inOrder = inOrder(mWifiMetrics);
+
+ // Acquire the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(acquireTime);
+ assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "",
+ mBinder, mWorkSource));
+
+ // Activate the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(activationTime);
+ mWifiLockManager.updateWifiClientConnected(true);
+
+ // Deactivate the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(deactivationTime);
+ mWifiLockManager.updateWifiClientConnected(false);
+
+ inOrder.verify(mWifiMetrics).addWifiLockActiveSession(
+ eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ eq(deactivationTime - activationTime));
+
+ // Release the lock
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(releaseTime);
+ releaseWifiLockSuccessful_noBatteryStats(mBinder);
+
+ inOrder.verify(mWifiMetrics).addWifiLockAcqSession(
+ eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY),
+ eq(releaseTime - acquireTime));
+ }
+
+ /**
* Verfies that dump() does not fail when no locks are held.
*/
@Test
@@ -1194,7 +1387,8 @@
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TEST_WIFI_LOCK_TAG,
mBinder, mWorkSource);
releaseWifiLockSuccessful(mBinder);
-
+ verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF),
+ anyLong());
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TEST_WIFI_LOCK_TAG,
mBinder, mWorkSource);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 4dcaea1..33da966 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -62,6 +62,7 @@
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.Base64;
import android.util.Pair;
import android.util.SparseIntArray;
@@ -125,6 +126,7 @@
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;
@Mock Context mContext;
@Mock FrameworkFacade mFacade;
@Mock Clock mClock;
@@ -139,16 +141,19 @@
@Mock ExternalCallbackTracker<IOnWifiUsabilityStatsListener> mListenerTracker;
@Mock WifiP2pMetrics mWifiP2pMetrics;
@Mock DppMetrics mDppMetrics;
+ @Mock CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector;
+ @Mock CellularLinkLayerStats mCellularLinkLayerStats;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDecodedProto = null;
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
+ when(mCellularLinkLayerStatsCollector.update()).thenReturn(mCellularLinkLayerStats);
mTestLooper = new TestLooper();
mWifiMetrics = new WifiMetrics(mContext, mFacade, mClock, mTestLooper.getLooper(),
new WifiAwareMetrics(mClock), new RttMetrics(mClock), mWifiPowerMetrics,
- mWifiP2pMetrics, mDppMetrics);
+ mWifiP2pMetrics, mDppMetrics, mCellularLinkLayerStatsCollector);
mWifiMetrics.setWifiConfigManager(mWcm);
mWifiMetrics.setPasspointManager(mPpm);
mWifiMetrics.setScoringParams(mScoringParams);
@@ -1340,6 +1345,10 @@
when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
when(scanDetail.getScanResult()).thenReturn(scanResult);
+ 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);
@@ -1371,6 +1380,54 @@
mDecodedProto.connectionEvent[1].routerFingerprint.routerTechnology);
assertTrue(mDecodedProto.connectionEvent[0].useRandomizedMac);
assertFalse(mDecodedProto.connectionEvent[1].useRandomizedMac);
+ assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL,
+ mDecodedProto.connectionEvent[0].connectionNominator);
+ }
+
+ /**
+ * 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;
+ 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);
}
/**
@@ -2274,7 +2331,7 @@
return bitSet;
}
- private static final int NUM_UNUSABLE_EVENT = 4;
+ private static final int NUM_UNUSABLE_EVENT = 5;
private static final int NUM_UNUSABLE_EVENT_TIME_THROTTLE = 3;
/**
@@ -2287,7 +2344,8 @@
{WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, 60, 60, 50, 40, 30, 1000, -1, 51},
{WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, 55, 40, 30, 0, 0, 500, -1, 52},
{WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH, 60, 90, 30, 30, 0, 1000, -1, 53},
- {WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, 55, 55, 30, 15, 10, 1000, 4, 54}
+ {WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, 55, 55, 30, 15, 10, 1000, 4, 54},
+ {WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST, 50, 56, 28, 17, 12, 1000, -1, 45}
};
/**
@@ -2320,6 +2378,9 @@
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;
}
@@ -2690,6 +2751,16 @@
when(info.getBSSID()).thenReturn("Wifi");
when(info.getFrequency()).thenReturn(5745);
+ int signalStrengthDbm = -50;
+ int signalStrengthDb = -10;
+ boolean isSameRegisteredCell = true;
+ CellularLinkLayerStats cellularStats = new CellularLinkLayerStats();
+ cellularStats.setIsSameRegisteredCell(isSameRegisteredCell);
+ cellularStats.setDataNetworkType(TelephonyManager.NETWORK_TYPE_LTE);
+ cellularStats.setSignalStrengthDbm(signalStrengthDbm);
+ cellularStats.setSignalStrengthDb(signalStrengthDb);
+ when(mCellularLinkLayerStatsCollector.update()).thenReturn(cellularStats);
+
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
WifiLinkLayerStats stats2 = nextRandomStats(stats1);
mWifiMetrics.incrementWifiScoreCount(60);
@@ -2701,6 +2772,8 @@
mWifiMetrics.incrementWifiUsabilityScoreCount(3, 56, 15);
mWifiMetrics.logLinkProbeFailure(nextRandInt(), 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);
@@ -2741,6 +2814,17 @@
.stats[1].probeElapsedTimeSinceLastUpdateMs);
assertEquals(-1, mDecodedProto.wifiUsabilityStatsList[0]
.stats[0].probeElapsedTimeSinceLastUpdateMs);
+ assertEquals(WifiUsabilityStatsEntry.NETWORK_TYPE_LTE,
+ mDecodedProto.wifiUsabilityStatsList[0].stats[0].cellularDataNetworkType);
+ assertEquals(signalStrengthDbm,
+ mDecodedProto.wifiUsabilityStatsList[0].stats[0].cellularSignalStrengthDbm);
+ assertEquals(signalStrengthDb,
+ mDecodedProto.wifiUsabilityStatsList[0].stats[0].cellularSignalStrengthDb);
+ assertEquals(isSameRegisteredCell,
+ mDecodedProto.wifiUsabilityStatsList[0].stats[0].isSameRegisteredCell);
+ assertEquals(DEVICE_MOBILITY_STATE_HIGH_MVMT, mDecodedProto.wifiUsabilityStatsList[1]
+ .stats[mDecodedProto.wifiUsabilityStatsList[1].stats.length - 1]
+ .deviceMobilityState);
}
/**
@@ -2840,17 +2924,21 @@
WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
- stats4.timeStampInMs = stats3.timeStampInMs - 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 2; i++) {
+ for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
stats3 = nextRandomStats(stats3);
}
- addBadWifiUsabilityStats(stats3);
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 2; i++) {
+ mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
+ mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
+ WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX);
+ for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
stats4 = nextRandomStats(stats4);
}
- addBadWifiUsabilityStats(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);
dumpProtoAndDeserialize();
assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
}
@@ -2875,17 +2963,21 @@
WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
- stats4.timeStampInMs = stats3.timeStampInMs + 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 2; i++) {
+ for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
stats3 = nextRandomStats(stats3);
}
- addBadWifiUsabilityStats(stats3);
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 2; i++) {
+ mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
+ mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
+ WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX);
+ for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
stats4 = nextRandomStats(stats4);
}
- addBadWifiUsabilityStats(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);
dumpProtoAndDeserialize();
assertEquals(4, mDecodedProto.wifiUsabilityStatsList.length);
}
@@ -3026,6 +3118,14 @@
WifiInfo info = mock(WifiInfo.class);
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
+
+ CellularLinkLayerStats cellularStats = new CellularLinkLayerStats();
+ cellularStats.setIsSameRegisteredCell(false);
+ cellularStats.setDataNetworkType(TelephonyManager.NETWORK_TYPE_UMTS);
+ cellularStats.setSignalStrengthDbm(-100);
+ cellularStats.setSignalStrengthDb(-20);
+ when(mCellularLinkLayerStatsCollector.update()).thenReturn(cellularStats);
+
WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
@@ -3039,6 +3139,10 @@
assertEquals(usabilityStats.getValue().getTimeStampMillis(), linkLayerStats.timeStampInMs);
assertEquals(usabilityStats.getValue().getTotalRoamScanTimeMillis(),
linkLayerStats.on_time_roam_scan);
+ assertEquals(usabilityStats.getValue().getCellularDataNetworkType(),
+ TelephonyManager.NETWORK_TYPE_UMTS);
+ assertEquals(usabilityStats.getValue().getCellularSignalStrengthDbm(), -100);
+ assertEquals(usabilityStats.getValue().getCellularSignalStrengthDb(), -20);
}
/**
@@ -3445,4 +3549,109 @@
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());
+ 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);
+
+ 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);
+ }
+
+ /**
+ * 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);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
index a5e28a2..c7a66e3 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
@@ -447,6 +447,8 @@
mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).registerObserver(mNetworkObserverCaptor1.capture());
mInOrder.verify(mNwManagementService).getInterfaceConfig(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
// Execute a teardown of the interface to ensure that the new iface removal works.
executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback1,
@@ -497,6 +499,8 @@
mInOrder.verify(mNwManagementService).clearInterfaceAddresses(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true);
mInOrder.verify(mNwManagementService).disableIpv6(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
// Execute a teardown of the interface to ensure that the new iface removal works.
executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback1,
@@ -706,6 +710,8 @@
mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).registerObserver(mNetworkObserverCaptor1.capture());
mInOrder.verify(mNwManagementService).getInterfaceConfig(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
// Step (c) - Iface up on old iface, ignored!
mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, true);
@@ -1163,6 +1169,8 @@
mInOrder.verify(mNwManagementService).clearInterfaceAddresses(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true);
mInOrder.verify(mNwManagementService).disableIpv6(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
// Now setup an AP interface.
assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1));
@@ -1186,6 +1194,8 @@
mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).registerObserver(mNetworkObserverCaptor1.capture());
mInOrder.verify(mNwManagementService).getInterfaceConfig(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
}
/**
@@ -1212,6 +1222,8 @@
mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).registerObserver(mNetworkObserverCaptor0.capture());
mInOrder.verify(mNwManagementService).getInterfaceConfig(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
// Now setup a STA interface.
assertEquals(IFACE_NAME_0,
@@ -1240,6 +1252,8 @@
mInOrder.verify(mNwManagementService).clearInterfaceAddresses(IFACE_NAME_0);
mInOrder.verify(mNwManagementService).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true);
mInOrder.verify(mNwManagementService).disableIpv6(IFACE_NAME_0);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0);
}
/**
@@ -1302,6 +1316,8 @@
mInOrder.verify(mNwManagementService).clearInterfaceAddresses(ifaceName);
mInOrder.verify(mNwManagementService).setInterfaceIpv6PrivacyExtensions(ifaceName, true);
mInOrder.verify(mNwManagementService).disableIpv6(ifaceName);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(ifaceName);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName);
}
private void executeAndValidateTeardownClientInterface(
@@ -1372,6 +1388,8 @@
mInOrder.verify(mNwManagementService).registerObserver(networkObserverCaptor.capture());
mInOrder.verify(mWifiMonitor).startMonitoring(ifaceName);
mInOrder.verify(mNwManagementService).getInterfaceConfig(ifaceName);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(ifaceName);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName);
}
private void executeAndValidateTeardownClientInterfaceForScan(
@@ -1442,6 +1460,8 @@
mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(ifaceName);
mInOrder.verify(mNwManagementService).registerObserver(networkObserverCaptor.capture());
mInOrder.verify(mNwManagementService).getInterfaceConfig(ifaceName);
+ mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(ifaceName);
+ mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName);
}
private void executeAndValidateTeardownSoftApInterface(
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
index 0091ae1..caecdf0 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
@@ -64,6 +64,7 @@
import com.android.internal.util.AsyncChannel;
import com.android.server.wifi.WifiNetworkFactory.AccessPoint;
+import com.android.server.wifi.nano.WifiMetricsProto;
import com.android.server.wifi.util.ScanResultUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -567,7 +568,7 @@
// Release the network request.
mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
// Verify that we did not trigger a disconnect because we've not yet connected.
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
// Re-enable connectivity manager .
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
@@ -1022,6 +1023,7 @@
assertNotNull(networkRequestUserSelectionCallback);
// Now trigger user selection to one of the network.
+ ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0];
mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork();
mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\"";
networkRequestUserSelectionCallback.select(mSelectedNetwork);
@@ -1032,20 +1034,9 @@
// Disable connectivity manager
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(true);
- ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor =
- ArgumentCaptor.forClass(WifiConfiguration.class);
- verify(mWifiConfigManager).addOrUpdateNetwork(
- wifiConfigurationCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_NAME_1));
- WifiConfiguration network = wifiConfigurationCaptor.getValue();
- assertNotNull(network);
- WifiConfiguration expectedWifiConfiguration =
- new WifiConfiguration(((WifiNetworkSpecifier) mNetworkRequest.networkCapabilities
- .getNetworkSpecifier()).wifiConfiguration);
- expectedWifiConfiguration.SSID = mSelectedNetwork.SSID;
- expectedWifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
- expectedWifiConfiguration.ephemeral = true;
- expectedWifiConfiguration.fromWifiNetworkSpecifier = true;
- WifiConfigurationTestUtil.assertConfigurationEqual(expectedWifiConfiguration, network);
+ validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID);
+ verify(mWifiMetrics).setNominatorForNetwork(anyInt(),
+ eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER));
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mClientModeImpl).sendMessage(messageCaptor.capture());
@@ -1102,7 +1093,7 @@
/**
* Verify handling of user selection to trigger connection to a network. Ensure we fill
- * up the BSSID field for connection to specific access points.
+ * up the BSSID field.
*/
@Test
public void
@@ -1142,21 +1133,67 @@
mLooper.dispatchAll();
// Verify WifiConfiguration params.
- ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor =
- ArgumentCaptor.forClass(WifiConfiguration.class);
- verify(mWifiConfigManager).addOrUpdateNetwork(
- wifiConfigurationCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_NAME_1));
- WifiConfiguration network = wifiConfigurationCaptor.getValue();
- assertNotNull(network);
- WifiConfiguration expectedWifiConfiguration =
- new WifiConfiguration(((WifiNetworkSpecifier) mNetworkRequest.networkCapabilities
- .getNetworkSpecifier()).wifiConfiguration);
- expectedWifiConfiguration.SSID = mSelectedNetwork.SSID;
- expectedWifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
- expectedWifiConfiguration.BSSID = matchingScanResult.BSSID;
- expectedWifiConfiguration.ephemeral = true;
- expectedWifiConfiguration.fromWifiNetworkSpecifier = true;
- WifiConfigurationTestUtil.assertConfigurationEqual(expectedWifiConfiguration, network);
+ validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID);
+ verify(mWifiMetrics).setNominatorForNetwork(anyInt(),
+ eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER));
+
+ // Verify connection message.
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mClientModeImpl).sendMessage(messageCaptor.capture());
+
+ Message message = messageCaptor.getValue();
+ assertNotNull(message);
+
+ assertEquals(WifiManager.CONNECT_NETWORK, message.what);
+ assertEquals(TEST_NETWORK_ID_1, message.arg1);
+ }
+
+ /**
+ * Verify handling of user selection to trigger connection to a network. Ensure we fill
+ * up the BSSID field with scan result for highest RSSI.
+ */
+ @Test
+ public void
+ testNetworkSpecifierHandleUserSelectionConnectToNetworkMultipleBssidMatches()
+ throws Exception {
+ setupScanData(SCAN_RESULT_TYPE_WPA_PSK,
+ TEST_SSID_1, TEST_SSID_1, TEST_SSID_1, TEST_SSID_4);
+
+ // Make a ssid pattern request which matches 3 scan results - 0, 1, 2.
+ PatternMatcher ssidPatternMatch =
+ new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL);
+ Pair<MacAddress, MacAddress> bssidPatternMatch =
+ Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
+ WifiConfiguration wifiConfiguration = new WifiConfiguration();
+ wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
+ WifiNetworkSpecifier specifier = new WifiNetworkSpecifier(
+ ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1,
+ TEST_PACKAGE_NAME_1);
+ mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier);
+ mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0);
+ mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback,
+ TEST_CALLBACK_IDENTIFIER);
+ verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(
+ mNetworkRequestUserSelectionCallback.capture());
+ verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS);
+
+ // Scan result 2 has the highest RSSI, so that should be picked.
+ ScanResult matchingScanResult = mTestScanDatas[0].getResults()[2];
+
+ // Now trigger user selection to the network.
+ mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult);
+ mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\"";
+ INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback =
+ mNetworkRequestUserSelectionCallback.getValue();
+ assertNotNull(networkRequestUserSelectionCallback);
+ networkRequestUserSelectionCallback.select(mSelectedNetwork);
+ mLooper.dispatchAll();
+
+ // Verify WifiConfiguration params.
+ validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID);
+ verify(mWifiMetrics).setNominatorForNetwork(anyInt(),
+ eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER));
// Verify connection message.
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
@@ -1355,6 +1392,66 @@
}
/**
+ * Verify that we ignore connection success events after the first one (may be triggered by a
+ * roam event)
+ */
+ @Test
+ public void testNetworkSpecifierDuplicateHandleConnectionSuccess() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection success indication.
+ assertNotNull(mSelectedNetwork);
+ mWifiNetworkFactory.handleConnectionAttemptEnded(
+ WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork);
+
+ // Verify that we sent the connection success callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+
+ verify(mWifiMetrics).incrementNetworkRequestApiNumConnectSuccess();
+
+ // Send second network connection success indication which should be ignored.
+ mWifiNetworkFactory.handleConnectionAttemptEnded(
+ WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork);
+ verifyNoMoreInteractions(mNetworkRequestMatchCallback);
+ }
+
+ /**
+ * Verify that we ignore any connection failure events after the first connection success (may
+ * be triggered by a disconnect).
+ * Note: The disconnect handling will be done via the NetworkAgent.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionFailureAfterSuccess() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection success indication.
+ assertNotNull(mSelectedNetwork);
+ mWifiNetworkFactory.handleConnectionAttemptEnded(
+ WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork);
+
+ // Verify that we sent the connection success callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+
+ verify(mWifiMetrics).incrementNetworkRequestApiNumConnectSuccess();
+
+ // Send a network connection failure indication which should be ignored (beyond the retry
+ // limit to trigger the failure handling).
+ for (int i = 0; i <= WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) {
+ mWifiNetworkFactory.handleConnectionAttemptEnded(
+ WifiMetrics.ConnectionEvent.FAILURE_DHCP, mSelectedNetwork);
+ mLooper.dispatchAll();
+ }
+ // Verify that we ignore the second connection failure callback.
+ verifyNoMoreInteractions(mNetworkRequestMatchCallback);
+ }
+
+ /**
* Verify handling of connection success to a different network.
*/
@Test
@@ -1405,7 +1502,7 @@
// Now release the network request.
mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
// Verify that we triggered a disconnect.
- verify(mClientModeImpl).disconnectCommandInternal();
+ verify(mClientModeImpl).disconnectCommand();
// Re-enable connectivity manager .
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
}
@@ -1580,12 +1677,12 @@
verify(mWifiConnectivityManager, times(1)).setSpecificNetworkRequestInProgress(true);
verify(mWifiScanner, times(2)).startScan(any(), any(), any());
// we shouldn't disconnect until the user accepts the next request.
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
// Remove the connected request1 & ensure we disconnect.
mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1);
mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
- verify(mClientModeImpl).disconnectCommandInternal();
+ verify(mClientModeImpl).disconnectCommand();
verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl,
mAlarmManager);
@@ -1630,7 +1727,7 @@
// We shouldn't explicitly disconnect, the new connection attempt will implicitly disconnect
// from the connected network.
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
// Remove the stale request1 & ensure nothing happens (because it was replaced by the
// second request)
@@ -1643,7 +1740,7 @@
// Now remove the rejected request2, ensure we disconnect & re-enable auto-join.
mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2);
mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
- verify(mClientModeImpl).disconnectCommandInternal();
+ verify(mClientModeImpl).disconnectCommand();
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl,
@@ -1679,12 +1776,12 @@
// we shouldn't disconnect/re-enable auto-join until the connected request is released.
verify(mWifiConnectivityManager, never()).setSpecificNetworkRequestInProgress(false);
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
// Remove the connected request1 & ensure we disconnect & ensure auto-join is re-enabled.
mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1);
mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
- verify(mClientModeImpl).disconnectCommandInternal();
+ verify(mClientModeImpl).disconnectCommand();
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl,
@@ -2358,18 +2455,23 @@
String caps = getScanResultCapsForType(scanResultType);
+ // Scan results have increasing RSSI.
scanResults[0].SSID = ssid1;
scanResults[0].BSSID = TEST_BSSID_1;
scanResults[0].capabilities = caps;
+ scanResults[0].level = -45;
scanResults[1].SSID = ssid2;
scanResults[1].BSSID = TEST_BSSID_2;
scanResults[1].capabilities = caps;
+ scanResults[1].level = -35;
scanResults[2].SSID = ssid3;
scanResults[2].BSSID = TEST_BSSID_3;
scanResults[2].capabilities = caps;
+ scanResults[2].level = -25;
scanResults[3].SSID = ssid4;
scanResults[3].BSSID = TEST_BSSID_4;
scanResults[3].capabilities = caps;
+ scanResults[3].level = -15;
}
private void validateScanResults(
@@ -2463,4 +2565,22 @@
assertTrue((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0);
assertTrue((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0);
}
+
+ private void validateConnectParams(String ssid, String bssid) {
+ ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor =
+ ArgumentCaptor.forClass(WifiConfiguration.class);
+ verify(mWifiConfigManager).addOrUpdateNetwork(
+ wifiConfigurationCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_NAME_1));
+ WifiConfiguration network = wifiConfigurationCaptor.getValue();
+ assertNotNull(network);
+ WifiConfiguration expectedWifiConfiguration =
+ new WifiConfiguration(((WifiNetworkSpecifier) mNetworkRequest.networkCapabilities
+ .getNetworkSpecifier()).wifiConfiguration);
+ expectedWifiConfiguration.SSID = ssid;
+ expectedWifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
+ expectedWifiConfiguration.BSSID = bssid;
+ expectedWifiConfiguration.ephemeral = true;
+ expectedWifiConfiguration.fromWifiNetworkSpecifier = true;
+ WifiConfigurationTestUtil.assertConfigurationEqual(expectedWifiConfiguration, network);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
index 9cefc2e..ec79e57 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
@@ -16,11 +16,14 @@
package com.android.server.wifi;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
+
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
import static com.android.server.wifi.WifiNetworkSelector.experimentIdFromIdentifier;
+import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -38,11 +41,12 @@
import com.android.internal.R;
import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
+import com.android.server.wifi.nano.WifiMetricsProto;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -61,6 +65,7 @@
private static final int RSSI_BUMP = 1;
private static final int DUMMY_EVALUATOR_ID_1 = -2; // lowest index
private static final int DUMMY_EVALUATOR_ID_2 = -1;
+ private static final HashSet<String> EMPTY_BLACKLIST = new HashSet<>();
/** Sets up test. */
@Before
@@ -81,7 +86,8 @@
mScoringParams,
mWifiConfigManager, mClock,
mLocalLog,
- mWifiMetrics);
+ mWifiMetrics,
+ mWifiNative);
mWifiNetworkSelector.registerNetworkEvaluator(mDummyEvaluator);
mDummyEvaluator.setEvaluatorToSelectCandidate(true);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime());
@@ -89,6 +95,7 @@
when(mWifiScoreCard.lookupBssid(any(), any())).thenReturn(mPerBssid);
mCompatibilityScorer = new CompatibilityScorer(mScoringParams);
mScoreCardBasedScorer = new ScoreCardBasedScorer(mScoringParams);
+ when(mWifiNative.getClientInterfaceName()).thenReturn("wlan0");
}
/** Cleans up test. */
@@ -179,6 +186,7 @@
@Mock private WifiScoreCard.PerBssid mPerBssid;
@Mock private WifiCandidates.CandidateScorer mCandidateScorer;
@Mock private WifiMetrics mWifiMetrics;
+ @Mock private WifiNative mWifiNative;
// For simulating the resources, we use a Spy on a MockResource
// (which is really more of a stub than a mock, in spite if its name).
@@ -699,6 +707,14 @@
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
+ ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class);
+ verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
+ nominatorIdCaptor.capture());
+ // unknown because DummyEvaluator does not have a nominator ID
+ // getValue() returns the argument from the *last* call
+ assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN,
+ nominatorIdCaptor.getValue().intValue());
+
WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
@@ -710,10 +726,66 @@
candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
+ verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
+ nominatorIdCaptor.capture());
+ // getValue() returns the argument from the *last* call
+ assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE,
+ nominatorIdCaptor.getValue().intValue());
WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate);
}
/**
+ * Tests when multiple evaluators nominate the same candidate, any one of the nominator IDs is
+ * acceptable.
+ */
+ @Test
+ public void testMultipleEvaluatorsSetsNominatorIdCorrectly() {
+ // first dummy evaluator is registered in setup, returns index 0
+ // register a second network evaluator that also returns index 0, but with a different ID
+ mWifiNetworkSelector.registerNetworkEvaluator(new DummyNetworkEvaluator(0,
+ WifiNetworkSelector.NetworkEvaluator.EVALUATOR_ID_SCORED));
+ // register a third network evaluator that also returns index 0, but with a different ID
+ mWifiNetworkSelector.registerNetworkEvaluator(new DummyNetworkEvaluator(0,
+ WifiNetworkSelector.NetworkEvaluator.EVALUATOR_ID_SAVED));
+
+ String[] ssids = {"\"test1\"", "\"test2\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] freqs = {2437, 5180};
+ String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"};
+ int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
+ int[] securities = {SECURITY_PSK, SECURITY_PSK};
+
+ ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
+ WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
+ freqs, caps, levels, securities, mWifiConfigManager, mClock);
+ List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
+ HashSet<String> blacklist = new HashSet<>();
+
+ // DummyEvaluator always selects the first network in the list.
+ WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0];
+ networkSelectorChoice.getNetworkSelectionStatus()
+ .setSeenInLastQualifiedNetworkSelection(true);
+
+ WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1];
+ userChoice.getNetworkSelectionStatus()
+ .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult());
+
+ WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
+ blacklist, mWifiInfo, false, true, false);
+
+ ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class);
+ verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
+ nominatorIdCaptor.capture());
+
+ for (int nominatorId : nominatorIdCaptor.getAllValues()) {
+ assertThat(nominatorId, is(oneOf(
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED)));
+ }
+ }
+
+ /**
* Wifi network selector doesn't recommend any network if the currently connected 2.4Ghz
* network is high quality and no 5GHz networks are available
*
@@ -1172,6 +1244,69 @@
}
/**
+ * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} for device that
+ * supports enhanced open networks, should filter out networks that are not open and not
+ * enhanced open after network selection is made.
+ *
+ * Expected behavior: return open and enhanced open networks only
+ */
+ @Test
+ public void getfilterOpenUnsavedNetworks_filtersForOpenAndOweNetworksOweSupported() {
+ String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
+ int[] freqs = {2437, 5180, 2414};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]", "[RSN-OWE-CCMP][ESS]"};
+ int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP,
+ mThresholdMinimumRssi2G + RSSI_BUMP};
+ mDummyEvaluator.setEvaluatorToSelectCandidate(false);
+ when(mWifiNative.getSupportedFeatureSet(anyString()))
+ .thenReturn(new Long(WIFI_FEATURE_OWE));
+
+ List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
+ ssids, bssids, freqs, caps, levels, mClock);
+ HashSet<String> blacklist = new HashSet<>();
+
+ mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
+ List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
+ expectedOpenUnsavedNetworks.add(scanDetails.get(1));
+ expectedOpenUnsavedNetworks.add(scanDetails.get(2));
+ assertEquals("Expect open unsaved networks",
+ expectedOpenUnsavedNetworks,
+ mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
+ }
+
+ /**
+ * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} for device that
+ * does not support enhanced open networks, should filter out both networks that are not open
+ * and enhanced open after network selection is made.
+ *
+ * Expected behavior: return open networks only
+ */
+ @Test
+ public void getfilterOpenUnsavedNetworks_filtersForOpenAndOweNetworksOweNotSupported() {
+ String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
+ int[] freqs = {2437, 5180, 2414};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]", "[RSN-OWE-CCMP][ESS]"};
+ int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP,
+ mThresholdMinimumRssi2G + RSSI_BUMP};
+ mDummyEvaluator.setEvaluatorToSelectCandidate(false);
+ when(mWifiNative.getSupportedFeatureSet(anyString()))
+ .thenReturn(new Long(~WIFI_FEATURE_OWE));
+
+ List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
+ ssids, bssids, freqs, caps, levels, mClock);
+ HashSet<String> blacklist = new HashSet<>();
+
+ mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
+ List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
+ expectedOpenUnsavedNetworks.add(scanDetails.get(1));
+ assertEquals("Expect open unsaved networks",
+ expectedOpenUnsavedNetworks,
+ mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
+ }
+
+ /**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
* out networks that are not EAP after network selection is made.
*
@@ -1359,8 +1494,12 @@
assertEquals(experimentId, mScoringParams.getExperimentIdentifier());
mWifiNetworkSelector.registerCandidateScorer(mCandidateScorer);
- test2GhzHighQuality5GhzAvailable(); // calls selectNetwork twice
- verify(mCandidateScorer, times(2)).scoreCandidates(any());
+
+ WifiConfiguration selected = mWifiNetworkSelector.selectNetwork(
+ setUpTwoNetworks(-35, -40),
+ EMPTY_BLACKLIST, mWifiInfo, false, true, true);
+
+ verify(mCandidateScorer).scoreCandidates(any());
}
/**
@@ -1370,15 +1509,16 @@
public void testCandidateScorerMetrics_onlyOneScorer() {
test2GhzHighQuality5GhzAvailable();
- verifyNoMoreInteractions(mWifiMetrics);
+ verify(mWifiMetrics, never()).logNetworkSelectionDecision(
+ anyInt(), anyInt(), anyBoolean(), anyInt());
}
/**
- * Tests that metrics are recorded for 2 scorers (legacy and legacy compatibility).
+ * Tests that metrics are recorded for 2 scorers (legacy and another).
*/
@Test
public void testCandidateScorerMetrics_twoScorers() {
- mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer);
+ mWifiNetworkSelector.registerCandidateScorer(mScoreCardBasedScorer);
// add a second NetworkEvaluator that returns the second network in the scan list
mWifiNetworkSelector.registerNetworkEvaluator(
@@ -1386,14 +1526,12 @@
test2GhzHighQuality5GhzAvailable();
- int compatibilityExpId = experimentIdFromIdentifier(mCompatibilityScorer.getIdentifier());
+ int registeredExpId = experimentIdFromIdentifier(mScoreCardBasedScorer.getIdentifier());
// Wanted 2 times since test2GhzHighQuality5GhzAvailable() calls
// WifiNetworkSelector.selectNetwork() twice
- verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(compatibilityExpId,
+ verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(registeredExpId,
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, true, 2);
-
- verifyNoMoreInteractions(mWifiMetrics);
}
/**
@@ -1418,8 +1556,6 @@
// WifiNetworkSelector.selectNetwork() twice
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, compatibilityExpId, true, 2);
-
- verifyNoMoreInteractions(mWifiMetrics);
}
private static final WifiCandidates.CandidateScorer NULL_SCORER =
@@ -1462,16 +1598,13 @@
// WifiNetworkSelector.selectNetwork() twice
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(nullScorerId,
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, false, 2);
-
- verifyNoMoreInteractions(mWifiMetrics);
}
/**
* Tests that metrics are recorded for 2 scorers (legacy and null) when the active
- * candidate scorer returns null.
+ * candidate scorer returns NONE.
*/
@Test
- @Ignore("TODO Until b/126273496 is resolved")
public void testCandidateScorerMetrics_twoScorers_nullActive() {
int nullScorerId = experimentIdFromIdentifier(NULL_SCORER.getIdentifier());
@@ -1485,16 +1618,31 @@
mWifiNetworkSelector.registerNetworkEvaluator(
new DummyNetworkEvaluator(1, DUMMY_EVALUATOR_ID_2));
- test2GhzHighQuality5GhzAvailable();
+ WifiConfiguration selected = mWifiNetworkSelector.selectNetwork(
+ setUpTwoNetworks(-35, -40),
+ EMPTY_BLACKLIST, mWifiInfo, false, true, true);
- // Wanted 2 times since test2GhzHighQuality5GhzAvailable() calls
- // WifiNetworkSelector.selectNetwork() twice
- verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(
+ assertNull(selected);
+
+ verify(mWifiMetrics).logNetworkSelectionDecision(
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, nullScorerId, false, 2);
-
+ verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(anyInt(), anyInt());
verifyNoMoreInteractions(mWifiMetrics);
}
+ private List<ScanDetail> setUpTwoNetworks(int rssiNetwork1, int rssiNetwork2) {
+ String[] ssids = {"\"test1\"", "\"test2\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] freqs = {5180, 2437};
+ String[] caps = {"[ESS]", "[ESS]"};
+ int[] levels = {rssiNetwork1, rssiNetwork2};
+ int[] securities = {SECURITY_NONE, SECURITY_NONE};
+ ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
+ WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
+ freqs, caps, levels, securities, mWifiConfigManager, mClock);
+ return scanDetailsAndConfigs.getScanDetails();
+ }
+
/**
* Tests that metrics are recorded for 3 scorers (legacy, compat, and null scorer).
*/
@@ -1522,8 +1670,6 @@
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, compatibilityExpId, true, 2);
-
- verifyNoMoreInteractions(mWifiMetrics);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
index dd78012..ca7c13e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
@@ -21,7 +21,6 @@
import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE;
import static android.app.AppOpsManager.OP_CHANGE_WIFI_STATE;
import static android.app.Notification.EXTRA_TEXT;
-import static android.app.Notification.EXTRA_TITLE;
import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION;
import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION;
@@ -198,9 +197,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
Set<WifiNetworkSuggestion> allNetworkSuggestions =
mWifiNetworkSuggestionsManager.getAllNetworkSuggestions();
@@ -241,9 +242,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
// Now remove all of them.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
@@ -283,9 +286,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
// Now remove all of them by sending an empty list.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
@@ -311,11 +316,13 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
Set<WifiNetworkSuggestion> allNetworkSuggestions =
mWifiNetworkSuggestionsManager.getAllNetworkSuggestions();
@@ -340,7 +347,8 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
// Modify the original suggestion.
networkSuggestion.wifiConfiguration.meteredOverride =
@@ -348,7 +356,8 @@
// Replace attempt should fail.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
}
/**
@@ -365,7 +374,8 @@
}
// The first add should succeed.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
List<WifiNetworkSuggestion> originalNetworkSuggestionsList = networkSuggestionList;
// Now add 3 more.
@@ -377,7 +387,8 @@
}
// The second add should fail.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
// Now remove 3 of the initially added ones.
networkSuggestionList = new ArrayList<>();
@@ -397,7 +408,8 @@
}
// This add should now succeed.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
}
/**
@@ -421,7 +433,8 @@
add(networkSuggestion2);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
// Remove should fail because the network list is different.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID,
mWifiNetworkSuggestionsManager.remove(networkSuggestionList2, TEST_PACKAGE_1));
@@ -431,6 +444,38 @@
* Verify a successful lookup of a single network suggestion matching the provided scan detail.
*/
@Test
+ public void
+ testGetNetworkSuggestionsForScanDetailSuccessWithOneMatchForCarrierProvisioningApp() {
+ WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
+ WifiConfigurationTestUtil.createOpenNetwork(), false, false, TEST_UID_1,
+ TEST_PACKAGE_1);
+ List<WifiNetworkSuggestion> networkSuggestionList1 =
+ new ArrayList<WifiNetworkSuggestion>() {{
+ add(networkSuggestion);
+ }};
+ // This app should be pre-approved. No need to explicitly call
+ // |setHasUserApprovedForApp(true, TEST_PACKAGE_1)|
+ when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
+ .thenReturn(true);
+ assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
+
+ ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration);
+
+ Set<WifiNetworkSuggestion> matchingNetworkSuggestions =
+ mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail);
+ Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions =
+ new HashSet<WifiNetworkSuggestion>() {{
+ add(networkSuggestion);
+ }};
+ assertEquals(expectedMatchingNetworkSuggestions, matchingNetworkSuggestions);
+ }
+
+ /**
+ * Verify a successful lookup of a single network suggestion matching the provided scan detail.
+ */
+ @Test
public void testGetNetworkSuggestionsForScanDetailSuccessWithOneMatch() {
WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
WifiConfigurationTestUtil.createOpenNetwork(), false, false, TEST_UID_1,
@@ -440,7 +485,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration);
@@ -478,9 +524,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -513,7 +561,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
Set<WifiNetworkSuggestion> matchingNetworkSuggestions =
@@ -552,9 +601,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -594,7 +645,8 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
Set<WifiNetworkSuggestion> matchingNetworkSuggestions =
@@ -636,9 +688,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -678,7 +732,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertFalse(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE_1));
ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration);
@@ -693,7 +748,8 @@
public void testGetNetworkSuggestionsForScanDetailFailureOnSuggestionRemoval() {
WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork();
WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
- wifiConfiguration, false, false, TEST_UID_1, TEST_PACKAGE_1);
+ wifiConfiguration, false, false, TEST_UID_1,
+ TEST_PACKAGE_1);
ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration);
List<WifiNetworkSuggestion> networkSuggestionList1 =
new ArrayList<WifiNetworkSuggestion>() {{
@@ -702,7 +758,8 @@
// add the suggestion & ensure lookup works.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
assertNotNull(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(
scanDetail));
@@ -726,7 +783,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Create a scan result corresponding to a different network.
@@ -753,7 +811,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Simulate connecting to the network.
@@ -786,7 +845,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Simulate connecting to the network.
@@ -811,22 +871,26 @@
public void testOnNetworkConnectionSuccessWithMultipleMatch() {
WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork();
WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion(
- wifiConfiguration, true, false, TEST_UID_1, TEST_PACKAGE_1);
+ wifiConfiguration, true, false, TEST_UID_1,
+ TEST_PACKAGE_1);
List<WifiNetworkSuggestion> networkSuggestionList1 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion1);
}};
WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion(
- wifiConfiguration, true, false, TEST_UID_2, TEST_PACKAGE_2);
+ wifiConfiguration, true, false, TEST_UID_2,
+ TEST_PACKAGE_2);
List<WifiNetworkSuggestion> networkSuggestionList2 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion2);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -869,22 +933,26 @@
WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork();
wifiConfiguration.BSSID = TEST_BSSID;
WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion(
- wifiConfiguration, true, false, TEST_UID_1, TEST_PACKAGE_1);
+ wifiConfiguration, true, false, TEST_UID_1,
+ TEST_PACKAGE_1);
List<WifiNetworkSuggestion> networkSuggestionList1 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion1);
}};
WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion(
- wifiConfiguration, true, false, TEST_UID_2, TEST_PACKAGE_2);
+ wifiConfiguration, true, false, TEST_UID_2,
+ TEST_PACKAGE_2);
List<WifiNetworkSuggestion> networkSuggestionList2 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion2);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -928,22 +996,26 @@
WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
wifiConfiguration2.BSSID = TEST_BSSID;
WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion(
- wifiConfiguration1, true, false, TEST_UID_1, TEST_PACKAGE_1);
+ wifiConfiguration1, true, false, TEST_UID_1,
+ TEST_PACKAGE_1);
List<WifiNetworkSuggestion> networkSuggestionList1 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion1);
}};
WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion(
- wifiConfiguration2, true, false, TEST_UID_2, TEST_PACKAGE_2);
+ wifiConfiguration2, true, false, TEST_UID_2,
+ TEST_PACKAGE_2);
List<WifiNetworkSuggestion> networkSuggestionList2 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion2);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -992,7 +1064,9 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
+ verify(mWifiPermissionsUtil).checkNetworkCarrierProvisioningPermission(TEST_UID_1);
assertFalse(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE_1));
// Simulate connecting to the network.
@@ -1021,7 +1095,9 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
+ verify(mWifiPermissionsUtil).checkNetworkCarrierProvisioningPermission(TEST_UID_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Simulate connecting to the network.
@@ -1050,7 +1126,9 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
+ verify(mWifiPermissionsUtil).checkNetworkCarrierProvisioningPermission(TEST_UID_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
doThrow(new SecurityException())
@@ -1082,7 +1160,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
// Verify config store interactions.
verify(mWifiConfigManager).saveToStore(true);
@@ -1123,7 +1202,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_PACKAGE_1));
@@ -1246,7 +1326,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Simulate connecting to the network.
@@ -1257,7 +1338,7 @@
// Now remove the network suggestion and ensure we did not trigger a disconnect.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_PACKAGE_1));
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
}
/**
@@ -1268,22 +1349,26 @@
public void testRemoveAppMatchingConnectionSuccessWithMultipleMatch() {
WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork();
WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion(
- wifiConfiguration, true, false, TEST_UID_1, TEST_PACKAGE_1);
+ wifiConfiguration, true, false, TEST_UID_1,
+ TEST_PACKAGE_1);
List<WifiNetworkSuggestion> networkSuggestionList1 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion1);
}};
WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion(
- wifiConfiguration, true, false, TEST_UID_2, TEST_PACKAGE_2);
+ wifiConfiguration, true, false, TEST_UID_2,
+ TEST_PACKAGE_2);
List<WifiNetworkSuggestion> networkSuggestionList2 =
new ArrayList<WifiNetworkSuggestion>() {{
add(networkSuggestion2);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2);
@@ -1293,11 +1378,11 @@
// Now remove one of the apps and ensure we did not trigger a disconnect.
mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1);
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
// Now remove the other app and ensure we trigger a disconnect.
mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_2);
- verify(mClientModeImpl).disconnectCommandInternal();
+ verify(mClientModeImpl).disconnectCommand();
}
/**
@@ -1314,7 +1399,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Simulate connecting to some other network.
@@ -1324,7 +1410,7 @@
// Now remove the app and ensure we did not trigger a disconnect.
mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1);
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
}
/**
@@ -1341,7 +1427,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
// Simulate failing connection to the network.
@@ -1356,7 +1443,7 @@
// Now remove the app and ensure we did not trigger a disconnect.
mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1);
- verify(mClientModeImpl, never()).disconnectCommandInternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
}
/**
@@ -1385,13 +1472,15 @@
// Watch app-ops changes on first add.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
mInorder.verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE),
eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture());
// Nothing happens on second add.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_1,
+ TEST_PACKAGE_1));
// Now remove first add, nothing happens.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
@@ -1419,7 +1508,8 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
Set<WifiNetworkSuggestion> allNetworkSuggestions =
mWifiNetworkSuggestionsManager.getAllNetworkSuggestions();
@@ -1436,7 +1526,8 @@
// allow change wifi state.
when(mAppOpsManager.unsafeCheckOpNoThrow(
- OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1))
+ OPSTR_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1))
.thenReturn(MODE_ALLOWED);
listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1);
mLooper.dispatchAll();
@@ -1445,7 +1536,8 @@
// disallow change wifi state & ensure we remove the app from database.
when(mAppOpsManager.unsafeCheckOpNoThrow(
- OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1))
+ OPSTR_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1))
.thenReturn(MODE_IGNORED);
listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1);
mLooper.dispatchAll();
@@ -1483,7 +1575,8 @@
// allow change wifi state.
when(mAppOpsManager.unsafeCheckOpNoThrow(
- OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1))
+ OPSTR_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1))
.thenReturn(MODE_ALLOWED);
listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1);
mLooper.dispatchAll();
@@ -1492,7 +1585,8 @@
// disallow change wifi state & ensure we remove all the suggestions for that app.
when(mAppOpsManager.unsafeCheckOpNoThrow(
- OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1))
+ OPSTR_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1))
.thenReturn(MODE_IGNORED);
listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1);
mLooper.dispatchAll();
@@ -1513,7 +1607,8 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
Set<WifiNetworkSuggestion> allNetworkSuggestions =
mWifiNetworkSuggestionsManager.getAllNetworkSuggestions();
@@ -1532,7 +1627,8 @@
doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(
eq(TEST_UID_1), eq(TEST_PACKAGE_1));
when(mAppOpsManager.unsafeCheckOpNoThrow(
- OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1))
+ OPSTR_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1))
.thenReturn(MODE_IGNORED);
listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1);
mLooper.dispatchAll();
@@ -1562,9 +1658,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
// Remove all suggestions from TEST_PACKAGE_1 & TEST_PACKAGE_2, we should continue to track.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
@@ -1624,9 +1722,11 @@
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+ TEST_PACKAGE_1));
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_PACKAGE_2));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+ TEST_PACKAGE_2));
// Remove all suggestions from TEST_PACKAGE_1 & TEST_PACKAGE_2, we should continue to track.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
@@ -1667,7 +1767,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
// Simulate finding the network in scan results.
mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(
@@ -1701,7 +1802,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
// Simulate finding the network in scan results.
mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(
@@ -1735,7 +1837,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE),
eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture());
@@ -1750,7 +1853,8 @@
NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1);
// Ensure we turn off CHANGE_WIFI_STATE app-ops.
verify(mAppOpsManager).setMode(
- OP_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1, MODE_IGNORED);
+ OP_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1, MODE_IGNORED);
// Cancel the notification.
verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
@@ -1760,7 +1864,8 @@
AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue();
assertNotNull(listener);
when(mAppOpsManager.unsafeCheckOpNoThrow(
- OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1))
+ OPSTR_CHANGE_WIFI_STATE, TEST_UID_1,
+ TEST_PACKAGE_1))
.thenReturn(MODE_IGNORED);
listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1);
mLooper.dispatchAll();
@@ -1768,7 +1873,8 @@
// Assuming the user re-enabled the app again & added the same suggestions back.
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
// We should resend the notification when the network is again found in scan results.
mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(
@@ -1791,7 +1897,8 @@
add(networkSuggestion);
}};
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
- mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1));
+ mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
+ TEST_PACKAGE_1));
// Simulate finding the network in scan results.
mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java
index d31b0a8..28aa180 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java
@@ -452,7 +452,7 @@
}
/**
- * Installing a MemoryStore after startup should issue reads
+ * Installing a MemoryStore after startup should issue reads.
*/
@Test
public void testReadAfterDelayedMemoryStoreInstallation() throws Exception {
@@ -461,4 +461,16 @@
verify(mMemoryStore).read(any(), any());
}
+ /**
+ * Calling clear should forget the state.
+ */
+ @Test
+ public void testClearReallyDoesClearTheState() throws Exception {
+ byte[] serialized = makeSerializedAccessPointExample();
+ assertNotEquals(0, serialized.length);
+ mWifiScoreCard.clear();
+ byte[] leftovers = mWifiScoreCard.getNetworkListByteArray(false);
+ assertEquals(0, leftovers.length);
+ }
+
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index ffc23a5..af6693e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -85,6 +85,7 @@
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.HomeSp;
+import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -235,6 +236,7 @@
@Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
@Mock WifiConfigManager mWifiConfigManager;
@Mock WifiScoreReport mWifiScoreReport;
+ @Mock WifiScoreCard mWifiScoreCard;
@Spy FakeWifiLog mLog;
@@ -360,6 +362,7 @@
when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager);
when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
when(mClientModeImpl.getWifiScoreReport()).thenReturn(mWifiScoreReport);
+ when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard);
when(mClientModeImpl.syncStartSubscriptionProvisioning(anyInt(),
any(OsuProvider.class), any(IProvisioningCallback.class), any())).thenReturn(true);
when(mPackageManager.hasSystemFeature(
@@ -2812,7 +2815,7 @@
doThrow(new SecurityException()).when(mAppOpsManager)
.noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
assertTrue(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME));
- verify(mClientModeImpl).disconnectCommandExternal();
+ verify(mClientModeImpl).disconnectCommand();
}
/**
@@ -2824,7 +2827,7 @@
public void testDisconnectWithChangeWifiStatePerm() throws Exception {
assertFalse(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME));
verifyCheckChangePermission(TEST_PACKAGE_NAME);
- verify(mClientModeImpl, never()).disconnectCommandExternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
}
/**
@@ -2843,7 +2846,7 @@
}
verifyCheckChangePermission(TEST_PACKAGE_NAME);
- verify(mClientModeImpl, never()).disconnectCommandExternal();
+ verify(mClientModeImpl, never()).disconnectCommand();
}
@Test
@@ -3259,6 +3262,7 @@
verify(mWifiConfigManager).clearDeletedEphemeralNetworks();
verify(mClientModeImpl).clearNetworkRequestUserApprovedAccessPoints();
verify(mWifiNetworkSuggestionsManager).clear();
+ verify(mWifiScoreCard).clear();
}
/**
@@ -3452,12 +3456,12 @@
public void testAddNetworkSuggestions() {
setupClientModeImplHandlerForRunWithScissors();
- when(mWifiNetworkSuggestionsManager.add(any(), anyString()))
+ when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString()))
.thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME));
- when(mWifiNetworkSuggestionsManager.add(any(), anyString()))
+ when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString()))
.thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE);
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE,
mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME));
@@ -3467,7 +3471,8 @@
assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME));
- verify(mWifiNetworkSuggestionsManager, times(2)).add(any(), eq(TEST_PACKAGE_NAME));
+ verify(mWifiNetworkSuggestionsManager, times(2)).add(
+ any(), eq(Binder.getCallingUid()), eq(TEST_PACKAGE_NAME));
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
index e7a61e5..f2cc45f 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
@@ -80,6 +80,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.util.AsyncChannel;
+import com.android.server.wifi.Clock;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -101,6 +102,7 @@
import java.util.HashSet;
import java.util.Set;
+
/**
* Unit test harness for WifiAwareDataPathStateManager class.
*/
@@ -111,6 +113,7 @@
private TestLooper mMockLooper;
private Handler mMockLooperHandler;
private WifiAwareStateManager mDut;
+ @Mock private Clock mClock;
@Mock private WifiAwareNativeManager mMockNativeManager;
@Spy private TestUtils.MonitoredWifiAwareNativeApi mMockNative =
new TestUtils.MonitoredWifiAwareNativeApi();
@@ -164,12 +167,13 @@
mDut = new WifiAwareStateManager();
mDut.setNative(mMockNativeManager, mMockNative);
mDut.start(mMockContext, mMockLooper.getLooper(), mAwareMetricsMock,
- mWifiPermissionsUtil, mPermissionsWrapperMock);
+ mWifiPermissionsUtil, mPermissionsWrapperMock, mClock);
mDut.startLate();
mMockLooper.dispatchAll();
when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), any(), any(),
any())).thenReturn(true);
+ when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(true);
when(mMockPowerManager.isDeviceIdleMode()).thenReturn(false);
when(mMockPowerManager.isInteractive()).thenReturn(true);
@@ -867,7 +871,7 @@
testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
buildTlv((1 << 16) - 1, (1 << 8) - 1, true), (1 << 16) - 1, (1 << 8) - 1,
- linkLocalIpv6Address);
+ linkLocalIpv6Address, 0);
}
/**
@@ -880,7 +884,7 @@
peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
- buildTlv(1 << 15, 1 << 7, true), 1 << 15, 1 << 7, linkLocalIpv6Address);
+ buildTlv(1 << 15, 1 << 7, true), 1 << 15, 1 << 7, linkLocalIpv6Address, 0);
}
/**
@@ -894,7 +898,7 @@
testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
buildTlv((1 << 15) - 1, (1 << 7) - 1, true), (1 << 15) - 1, (1 << 7) - 1,
- linkLocalIpv6Address);
+ linkLocalIpv6Address, 0);
}
/**
@@ -908,7 +912,38 @@
(byte) 0xfe, 0x7a, 0x2f, (byte) 0xa2};
testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
- testVector, 0, -1, "fe80::b3:e1ff:fe7a:2fa2");
+ testVector, 0, -1, "fe80::b3:e1ff:fe7a:2fa2", 0);
+ }
+
+ /**
+ * Verify that retrying address validation a 'small' number of times results in successful
+ * NDP setup.
+ */
+ @Test
+ public void testDataPathInitiatorAddressValidationRetrySuccess() throws Exception {
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ String linkLocalIpv6Address = MacAddress.fromBytes(
+ peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
+
+ testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
+ null, 0, -1, linkLocalIpv6Address,
+ WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS
+ / WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS - 1);
+ }
+
+ /**
+ * Verify that retrying address validation a 'large' number of times results in failure.
+ */
+ @Test
+ public void testDataPathInitiatorAddressValidationRetryFail() throws Exception {
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ String linkLocalIpv6Address = MacAddress.fromBytes(
+ peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
+
+ testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
+ null, 0, -1, linkLocalIpv6Address,
+ WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS
+ / WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS + 10);
}
/**
@@ -1254,13 +1289,13 @@
testDataPathInitiatorUtilityMore(useDirect, provideMac, providePmk, providePassphrase,
getConfirmation, immediateHalFailure, peerDataPathMac, null, 0, -1,
- linkLocalIpv6Address);
+ linkLocalIpv6Address, 0);
}
private void testDataPathInitiatorUtilityMore(boolean useDirect, boolean provideMac,
boolean providePmk, boolean providePassphrase, boolean getConfirmation,
boolean immediateHalFailure, byte[] peerDataPathMac, byte[] peerToken, int port,
- int transportProtocol, String ipv6Address)
+ int transportProtocol, String ipv6Address, int numAddrValidationRetries)
throws Exception {
final int clientId = 123;
final byte pubSubId = 58;
@@ -1275,7 +1310,7 @@
ArgumentCaptor<NetworkCapabilities> netCapCaptor = ArgumentCaptor.forClass(
NetworkCapabilities.class);
InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback,
- mMockNwMgt);
+ mMockNwMgt, mMockNetworkInterface);
InOrder inOrderM = inOrder(mAwareMetricsMock);
if (!providePmk) {
@@ -1332,20 +1367,56 @@
// (2) get confirmation OR timeout
if (getConfirmation) {
+ if (numAddrValidationRetries > 0) {
+ when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(false);
+ }
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
+
mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0, peerToken, null);
mMockLooper.dispatchAll();
inOrder.verify(mMockNwMgt).setInterfaceUp(anyString());
inOrder.verify(mMockNwMgt).enableIpv6(anyString());
+ inOrder.verify(mMockNetworkInterface).configureAgentProperties(any(), any(), anyInt(),
+ any(), any(), any());
inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), any(),
netCapCaptor.capture(), anyInt(), any(), anyInt());
- inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS),
- eq(useDirect), anyLong());
- inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any());
- WifiAwareNetworkInfo netInfo =
- (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo();
- assertEquals(ipv6Address, netInfo.getPeerIpv6Addr().getHostAddress());
- assertEquals(port, netInfo.getPort());
- assertEquals(transportProtocol, netInfo.getTransportProtocol());
+
+ inOrder.verify(mMockNetworkInterface).isAddressUsable(any());
+ boolean timedout = false;
+ for (int i = 0; i < numAddrValidationRetries; ++i) {
+ if (i == numAddrValidationRetries - 1) {
+ when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(true);
+ }
+
+ long currentTime = (i + 1L)
+ * WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime);
+ mMockLooper.moveTimeForward(
+ WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS + 1);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mMockNetworkInterface).isAddressUsable(any());
+
+ if (currentTime > WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS) {
+ timedout = true;
+ break;
+ }
+ }
+
+ if (timedout) {
+ verifyUnfullfillableDispatched(res.mReverseMessenger);
+ inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId));
+ mDut.onEndDataPathResponse(transactionId.getValue(), true, 0);
+ } else {
+ inOrder.verify(mMockNetworkInterface).sendAgentNetworkInfo(any(), any());
+ inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS),
+ eq(useDirect), anyLong());
+ inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any());
+ WifiAwareNetworkInfo netInfo =
+ (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo();
+ assertEquals(ipv6Address, netInfo.getPeerIpv6Addr().getHostAddress());
+ assertEquals(port, netInfo.getPort());
+ assertEquals(transportProtocol, netInfo.getTransportProtocol());
+ }
} else {
assertTrue(mAlarmManager.dispatch(
WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG));
@@ -1377,7 +1448,8 @@
inOrderM.verify(mAwareMetricsMock).recordNdpSessionDuration(anyLong());
}
- verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNwMgt);
+ verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNwMgt,
+ mMockNetworkInterface);
}
private void testDataPathResponderUtility(boolean useDirect, boolean provideMac,
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
index 8fd38cc..1204c4f 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
@@ -66,6 +66,7 @@
import java.util.List;
import java.util.Map;
+
/**
* Unit test harness for WifiAwareStateManager.
*/
@@ -151,7 +152,7 @@
mock(WifiAwareNativeManager.class), mock(WifiAwareNativeApi.class),
mock(WifiAwareNativeCallback.class));
verify(mAwareStateManagerMock).start(eq(mContextMock), any(), eq(mAwareMetricsMock),
- eq(mWifiPermissionsUtil), eq(mPermissionsWrapperMock));
+ eq(mWifiPermissionsUtil), eq(mPermissionsWrapperMock), any());
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
index 920341d..b4f93c1 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
@@ -73,6 +73,7 @@
import androidx.test.filters.SmallTest;
+import com.android.server.wifi.Clock;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -170,7 +171,7 @@
mDut = new WifiAwareStateManager();
mDut.setNative(mMockNativeManager, mMockNative);
mDut.start(mMockContext, mMockLooper.getLooper(), mAwareMetricsMock,
- mWifiPermissionsUtil, mPermissionsWrapperMock);
+ mWifiPermissionsUtil, mPermissionsWrapperMock, new Clock());
mDut.startLate();
mMockLooper.dispatchAll();
verify(mMockContext, times(3)).registerReceiver(bcastRxCaptor.capture(),
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
index 2442751..8503c45 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
@@ -1586,7 +1586,7 @@
try {
TelephonyManager telephonyManager = mock(TelephonyManager.class);
when(TelephonyManager.from(any(Context.class))).thenReturn(telephonyManager);
- when(telephonyManager.getNetworkOperator()).thenReturn("123456");
+ when(telephonyManager.getSimOperator()).thenReturn("123456");
PasspointManager passpointManager = new PasspointManager(mContext, mWifiNative,
mWifiKeyStore, mClock,
mSimAccessor, mObjectFactory, mWifiConfigManager, mWifiConfigStore,
@@ -1611,8 +1611,8 @@
TelephonyManager telephonyManager = mock(TelephonyManager.class);
String mccmnc = "123456";
when(TelephonyManager.from(any(Context.class))).thenReturn(telephonyManager);
- when(telephonyManager.getNetworkOperator()).thenReturn(mccmnc);
- when(telephonyManager.getNetworkOperatorName()).thenReturn("test");
+ when(telephonyManager.getSimOperator()).thenReturn(mccmnc);
+ when(telephonyManager.getSimOperatorName()).thenReturn("test");
PasspointManager passpointManager = new PasspointManager(mContext, mWifiNative,
mWifiKeyStore, mClock,
@@ -1693,7 +1693,7 @@
try {
TelephonyManager telephonyManager = mock(TelephonyManager.class);
when(TelephonyManager.from(any(Context.class))).thenReturn(telephonyManager);
- when(telephonyManager.getNetworkOperator()).thenReturn(TEST_MCC_MNC);
+ when(telephonyManager.getSimOperator()).thenReturn(TEST_MCC_MNC);
when(mWifiConfigManager.isSimPresent()).thenReturn(true);
List<ScanDetail> scanDetails = new ArrayList<>();
scanDetails.add(generateScanDetail(TEST_SSID, TEST_BSSID_STRING, TEST_HESSID,
@@ -1737,7 +1737,7 @@
try {
TelephonyManager telephonyManager = mock(TelephonyManager.class);
when(TelephonyManager.from(any(Context.class))).thenReturn(telephonyManager);
- when(telephonyManager.getNetworkOperator()).thenReturn(TEST_MCC_MNC);
+ when(telephonyManager.getSimOperator()).thenReturn(TEST_MCC_MNC);
when(mWifiConfigManager.isSimPresent()).thenReturn(true);
List<ScanDetail> scanDetails = new ArrayList<>();
scanDetails.add(generateScanDetail(TEST_SSID, TEST_BSSID_STRING, 0, 0, false));
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java
index 76a2e65..61d0c37 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java
@@ -145,7 +145,7 @@
mEvaluator = new PasspointNetworkEvaluator(mPasspointManager, mWifiConfigManager,
mLocalLog, mCarrierNetworkConfig, mTelephonyManager);
when(mWifiConfigManager.isSimPresent()).thenReturn(true);
- when(mTelephonyManager.getNetworkOperator()).thenReturn("123456");
+ when(mTelephonyManager.getSimOperator()).thenReturn("123456");
}
/**
@@ -412,6 +412,31 @@
}
/**
+ * Verify that it never creates an ephemeral Passpoint Configuration when the carrier is not
+ * MNO.
+ */
+ @Test
+ public void skipCreateEphemeralPasspointConfigurationForNonMNO() {
+ // Setup ScanDetail and match providers.
+ List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[]{
+ generateScanDetail(TEST_SSID1, TEST_BSSID1)});
+ when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+
+ // MVNO carrier is enabled.
+ when(mTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(1);
+ when(mTelephonyManager.getSimCarrierId()).thenReturn(20);
+ when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true);
+ when(mPasspointManager.hasCarrierProvider(anyString())).thenReturn(false);
+ when(mPasspointManager.findEapMethodFromNAIRealmMatchedWithCarrier(
+ any(List.class))).thenReturn(
+ EAPConstants.EAP_AKA);
+
+ assertEquals(null, mEvaluator.evaluateNetworks(
+ scanDetails, null, null, false, false, mOnConnectableListener));
+ verify(mPasspointManager, never()).createEphemeralPasspointConfigForCarrier(anyInt());
+ }
+
+ /**
* Verify that it never creates an ephemeral Passpoint Configuration when the profile for the
* carrier already exists.
*/
@@ -437,6 +462,11 @@
// Setup ScanDetail
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[]{
generateScanDetail(TEST_SSID1, TEST_BSSID1)});
+ when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+
+ // MNO carrier is enabled.
+ when(mTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(1);
+ when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true);
when(mPasspointManager.hasCarrierProvider(anyString())).thenReturn(false);
when(mPasspointManager.findEapMethodFromNAIRealmMatchedWithCarrier(
@@ -459,6 +489,11 @@
// Setup ScanDetail
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[]{
generateScanDetail(TEST_SSID1, TEST_BSSID1)});
+ when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+
+ // MNO carrier is enabled.
+ when(mTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(1);
+ when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true);
when(mPasspointManager.hasCarrierProvider(anyString())).thenReturn(false);
when(mPasspointManager.findEapMethodFromNAIRealmMatchedWithCarrier(
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java
index 0dcf522..c83023e 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java
@@ -199,12 +199,10 @@
mSession = ExtendedMockito.mockitoSession().mockStatic(
RedirectListener.class).mockStatic(PpsMoParser.class).mockStatic(
UpdateResponseMessage.class).startMocking();
-
- when(RedirectListener.createInstance(mLooper.getLooper())).thenReturn(
- mRedirectListener);
+ when(RedirectListener.createInstance(mLooper.getLooper())).thenReturn(mRedirectListener);
when(mRedirectListener.getServerUrl()).thenReturn(new URL(TEST_REDIRECT_URL));
when(mRedirectListener.startServer(
- any(RedirectListener.RedirectCallback.class))).thenReturn(true);
+ any(RedirectListener.RedirectCallback.class), any(Handler.class))).thenReturn(true);
when(mRedirectListener.isAlive()).thenReturn(true);
when(mWifiManager.isWifiEnabled()).thenReturn(true);
when(mObjectFactory.makeOsuNetworkConnection(any(Context.class)))
@@ -356,7 +354,8 @@
verify(mCallback).onProvisioningStatus(
ProvisioningCallback.OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE);
verify(mRedirectListener, atLeastOnce())
- .startServer(mOnRedirectReceivedArgumentCaptor.capture());
+ .startServer(mOnRedirectReceivedArgumentCaptor.capture(),
+ any(Handler.class));
mRedirectReceivedListener = mOnRedirectReceivedArgumentCaptor.getValue();
verifyNoMoreInteractions(mCallback);
} else if (step == STEP_WAIT_FOR_SECOND_SOAP_RESPONSE) {
@@ -368,7 +367,7 @@
mRedirectReceivedListener.onRedirectReceived();
mLooper.dispatchAll();
- verify(mRedirectListener, atLeastOnce()).stopServer();
+ verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class));
verify(mCallback).onProvisioningStatus(
ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED);
verify(mCallback).onProvisioningStatus(
@@ -520,6 +519,35 @@
}
/**
+ * Verifies existing provisioning flow is aborted when failing to create an instance of {@link
+ * RedirectListener}.
+ */
+ @Test
+ public void verifyRedirectStartFailure() throws RemoteException {
+ when(RedirectListener.createInstance(mLooper.getLooper())).thenReturn(null);
+ mPasspointProvisioner.init(mLooper.getLooper());
+ verify(mOsuNetworkConnection).init(mHandlerCaptor.capture());
+
+ mHandler = mHandlerCaptor.getValue();
+ assertEquals(mHandler.getLooper(), mLooper.getLooper());
+
+ mLooper.dispatchAll();
+
+ assertTrue(mPasspointProvisioner.startSubscriptionProvisioning(
+ TEST_UID, mOsuProvider, mCallback));
+
+ mLooper.dispatchAll();
+
+ // Since creating an instance of RedirectListener, directly move to FAILED_STATE
+ verify(mCallback).onProvisioningFailure(
+ ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER);
+
+ // Failure case, no more runnable posted
+ verifyNoMoreInteractions(mCallback);
+
+ }
+
+ /**
* Verifies that if connection attempt to OSU AP fails, corresponding error callback is invoked.
*/
@Test
@@ -775,7 +803,7 @@
mRedirectReceivedListener.onRedirectTimedOut();
mLooper.dispatchAll();
- verify(mRedirectListener, atLeastOnce()).stopServer();
+ verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class));
verify(mCallback).onProvisioningFailure(
ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER);
// No further runnable posted
@@ -794,7 +822,7 @@
mRedirectReceivedListener.onRedirectReceived();
mLooper.dispatchAll();
- verify(mRedirectListener, atLeastOnce()).stopServer();
+ verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class));
verify(mCallback).onProvisioningStatus(
ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED);
verify(mCallback).onProvisioningStatus(
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java
index 308bb47..d61a59d 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
+import android.os.Handler;
import android.os.Looper;
import android.os.test.TestLooper;
@@ -47,6 +48,7 @@
private RedirectListenerSpy mRedirectListener;
private URL mServerUrl;
private TestLooper mLooper = new TestLooper();
+ private Handler mHandler = new Handler(mLooper.getLooper());
@Mock RedirectListener.RedirectCallback mListener;
@Mock NanoHTTPD.IHTTPSession mIHTTPSession;
@@ -55,7 +57,7 @@
private class RedirectListenerSpy extends RedirectListener {
boolean mIsStart = false;
RedirectListenerSpy(Looper looper, int port) throws IOException {
- super(looper, looper, port);
+ super(looper, port);
}
@Override
@@ -80,20 +82,19 @@
@Before
public void setUp() throws Exception {
initMocks(this);
-
mRedirectListener = new RedirectListenerSpy(mLooper.getLooper(), TEST_PORT);
mServerUrl = mRedirectListener.getServerUrl();
}
private void verifyStartServer() {
- mRedirectListener.startServer(mListener);
+ mRedirectListener.startServer(mListener, mHandler);
mLooper.dispatchAll();
assertTrue(mRedirectListener.mIsStart);
}
private void verifyStopServer() {
- mRedirectListener.stopServer();
+ mRedirectListener.stopServer(mHandler);
mLooper.dispatchAll();
assertFalse(mRedirectListener.mIsStart);
diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java
index 19a5aa5..cd61aac 100644
--- a/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java
@@ -93,6 +93,7 @@
import java.util.Map;
import java.util.Set;
+
/**
* Unit test harness for the RttServiceImpl class.
*/
@@ -253,8 +254,12 @@
RangingRequest[] requests = new RangingRequest[numIter];
List<Pair<List<RttResult>, List<RangingResult>>> results = new ArrayList<>();
- for (int i = 0; i < numIter; ++i) {
- requests[i] = RttTestUtils.getDummyRangingRequest((byte) i);
+ for (int i = 0; i < numIter; ++i) { // even: MC, non-MC, Aware, odd: MC only
+ if (i % 2 == 0) {
+ requests[i] = RttTestUtils.getDummyRangingRequestMcOnly((byte) i);
+ } else {
+ requests[i] = RttTestUtils.getDummyRangingRequest((byte) i);
+ }
results.add(RttTestUtils.getDummyRangingResults(requests[i]));
}
@@ -267,7 +272,7 @@
for (int i = 0; i < numIter; ++i) {
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(i % 2 != 0, 0);
// (3) native calls back with result
mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).first);
@@ -324,7 +329,7 @@
// verify that requested with MAC address translated from the PeerHandle issued to Native
verify(mockNative).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture(), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
RangingRequest finalRequest = mRequestCaptor.getValue();
assertNotEquals("Request to native is not null", null, finalRequest);
@@ -398,7 +403,7 @@
if (i == 0) {
verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL);
} else {
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
}
// (4) on failed HAL: even if native calls back with result we shouldn't dispatch
@@ -443,7 +448,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) native calls back with result - should get a FAILED callback
when(mockPermissionUtil.checkCallersLocationPermission(eq(mPackageName),
@@ -494,7 +499,7 @@
// (3) verify first request and all odd requests issued to HAL
if (i == 0 || i % 2 == 1) {
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
}
// (4) trigger first death recipient (which will map to the even UID)
@@ -563,7 +568,7 @@
verify(mockIbinder).linkToDeath(mDeathRecipientCaptor.capture(), anyInt());
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (2) execute binder death
mDeathRecipientCaptor.getValue().binderDied();
@@ -613,7 +618,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) cancel the request
mDut.cancelRanging(worksourceCancel);
@@ -659,7 +664,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) cancel the request
mDut.cancelRanging(worksourceCancel);
@@ -697,7 +702,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) native calls back with result - but wrong ID
mDut.onRangingResults(mIntCaptor.getValue() + 1,
@@ -748,7 +753,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) return results with missing entries
mDut.onRangingResults(mIntCaptor.getValue(), results.first);
@@ -791,7 +796,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) return results with ALL results missing
mDut.onRangingResults(mIntCaptor.getValue(), new ArrayList<>());
@@ -844,7 +849,7 @@
// (2) verify that request issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(false));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) return results with missing entries
mDut.onRangingResults(mIntCaptor.getValue(), results.first);
@@ -886,7 +891,7 @@
// verify that request 1 issued to native
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true));
int cmdId1 = mIntCaptor.getValue();
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (2) time-out
mAlarmManager.dispatch(RttServiceImpl.HAL_RANGING_TIMEOUT_TAG);
@@ -896,7 +901,7 @@
verify(mockNative).rangeCancel(eq(cmdId1), any());
verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL);
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request2), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (3) send both result 1 and result 2
mDut.onRangingResults(cmdId1, result1.first);
@@ -955,7 +960,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, clock.time);
// (1.1) get result
mDut.onRangingResults(mIntCaptor.getValue(), result1.first);
@@ -977,7 +982,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request3), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, clock.time);
// (3.1) get result
mDut.onRangingResults(mIntCaptor.getValue(), result3.first);
@@ -995,7 +1000,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request4), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, clock.time);
// (4.1) get result
mDut.onRangingResults(mIntCaptor.getValue(), result4.first);
@@ -1086,7 +1091,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, clock.time);
// (1.1) get result
mDut.onRangingResults(mIntCaptor.getValue(), result1.first);
@@ -1102,7 +1107,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request2), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, clock.time);
// (2.1) get result
mDut.onRangingResults(mIntCaptor.getValue(), result2.first);
@@ -1171,7 +1176,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// 2. issue FLOOD LEVEL requests + 10 at various UIDs - no failure expected
for (int i = 0; i < RttServiceImpl.MAX_QUEUED_PER_UID + 10; ++i) {
@@ -1237,7 +1242,7 @@
mMockLooper.dispatchAll();
nativeInorder.verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// 2. issue FLOOD LEVEL requests + 10: should get 11 failures (10 extra + 1 original)
for (int i = 0; i < RttServiceImpl.MAX_QUEUED_PER_UID + 10; ++i) {
@@ -1257,7 +1262,7 @@
verifyWakeupCancelled();
nativeInorder.verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// 4. issue a request: don't expect a failure
mDut.startRanging(mockIbinder, mPackageName, useUids ? null : ws, request, mockCallback);
@@ -1337,7 +1342,7 @@
mMockLooper.dispatchAll();
verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true));
- verifyWakeupSet();
+ verifyWakeupSet(true, 0);
// (2) disable RTT: all requests should "fail"
if (failureMode == FAILURE_MODE_DISABLE_WIFI) {
@@ -1416,10 +1421,15 @@
mLocationModeReceiver.onReceive(mockContext, intent);
}
- private void verifyWakeupSet() {
- mInOrder.verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), anyLong(),
+ private void verifyWakeupSet(boolean useAwareTimeout, long baseTime) {
+ ArgumentCaptor<Long> longCaptor = ArgumentCaptor.forClass(Long.class);
+
+ mInOrder.verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), longCaptor.capture(),
eq(RttServiceImpl.HAL_RANGING_TIMEOUT_TAG), any(AlarmManager.OnAlarmListener.class),
any(Handler.class));
+
+ assertEquals(baseTime + (useAwareTimeout ? RttServiceImpl.HAL_AWARE_RANGING_TIMEOUT_MS
+ : RttServiceImpl.HAL_RANGING_TIMEOUT_MS), longCaptor.getValue().longValue());
}
private void verifyWakeupCancelled() {
diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java
index 8d3a5cb..c5385eb 100644
--- a/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java
+++ b/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java
@@ -78,6 +78,23 @@
}
/**
+ * Returns a dummy ranging request with 2 requests:
+ * - First: 802.11mc capable
+ */
+ public static RangingRequest getDummyRangingRequestMcOnly(byte lastMacByte) {
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+
+ ScanResult scan1 = new ScanResult();
+ scan1.BSSID = "00:01:02:03:04:" + String.format("%02d", lastMacByte);
+ scan1.setFlag(ScanResult.FLAG_80211mc_RESPONDER);
+ scan1.channelWidth = ScanResult.CHANNEL_WIDTH_40MHZ;
+
+ builder.addAccessPoint(scan1);
+
+ return builder.build();
+ }
+
+ /**
* Returns a dummy ranging request with 2 requests - neither of which support 802.11mc.
*/
public static RangingRequest getDummyRangingRequestNo80211mcSupport(byte lastMacByte) {
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
index 356b50f..c2c9744 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
@@ -73,6 +73,7 @@
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.test.BidirectionalAsyncChannel;
+import com.android.server.wifi.CellularLinkLayerStatsCollector;
import com.android.server.wifi.Clock;
import com.android.server.wifi.DppMetrics;
import com.android.server.wifi.FakeWifiLog;
@@ -132,7 +133,7 @@
TestLooper mLooper;
WifiScanningServiceImpl mWifiScanningServiceImpl;
@Mock WifiP2pMetrics mWifiP2pMetrics;
-
+ @Mock CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector;
@Before
public void setUp() throws Exception {
@@ -152,7 +153,7 @@
mLooper = new TestLooper();
mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, mLooper.getLooper(),
new WifiAwareMetrics(mClock), new RttMetrics(mClock), new WifiPowerMetrics(),
- mWifiP2pMetrics, mDppMetrics);
+ mWifiP2pMetrics, mDppMetrics, mCellularLinkLayerStatsCollector);
when(mWifiScannerImplFactory
.create(any(), any(), any()))
.thenReturn(mWifiScannerImpl);
diff --git a/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java b/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java
index 5e4f6cc..b707698 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.*;
+import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
@@ -38,6 +39,7 @@
* @throws Exception
*/
@Test
+ @Ignore
public void testIntegrityWithKnownDataAndKnownAlias() throws Exception {
File integrityFile = File.createTempFile("testIntegrityWithKnownDataAndKnownAlias",
".tmp");
@@ -56,6 +58,7 @@
* @throws Exception
*/
@Test
+ @Ignore
public void testIntegrityWithUnknownDataAndKnownAlias() throws Exception {
File integrityFile = File.createTempFile("testIntegrityWithUnknownDataAndKnownAlias",
".tmp");
@@ -72,6 +75,7 @@
* @throws Exception
*/
@Test(expected = DigestException.class)
+ @Ignore
public void testIntegrityWithoutUpdate() throws Exception {
File tmpFile = File.createTempFile("testIntegrityWithoutUpdate", ".tmp");
diff --git a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java
index 112add8..8c9dcbd 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java
@@ -17,7 +17,6 @@
package com.android.server.wifi.util;
import static org.junit.Assert.*;
-import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.Mockito.*;
import android.net.wifi.WifiConfiguration;
@@ -29,23 +28,41 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.server.wifi.CarrierNetworkConfig;
import com.android.server.wifi.WifiConfigurationTestUtil;
import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData;
import com.android.server.wifi.util.TelephonyUtil.SimAuthResponseData;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.security.PublicKey;
+import javax.crypto.Cipher;
+
/**
* Unit tests for {@link com.android.server.wifi.util.TelephonyUtil}.
*/
@SmallTest
public class TelephonyUtilTest {
+ private TelephonyUtil mTelephonyUtil;
+
+ @Mock
+ CarrierNetworkConfig mCarrierNetworkConfig;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mCarrierNetworkConfig.getBase64EncodingFlag()).thenReturn(Base64.DEFAULT);
+ mTelephonyUtil = new TelephonyUtil();
+ }
@Test
public void getSimIdentityEapSim() {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
final Pair<String, String> expectedIdentity = Pair.create(
"13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", "");
@@ -54,18 +71,17 @@
when(tm.getSimOperator()).thenReturn("321456");
when(tm.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null);
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM,
- WifiEnterpriseConfig.Phase2.NONE)));
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP,
- WifiEnterpriseConfig.Phase2.SIM)));
+ WifiEnterpriseConfig.Phase2.SIM), mCarrierNetworkConfig));
}
@Test
public void getSimIdentityEapAka() {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
final Pair<String, String> expectedIdentity = Pair.create(
"03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", "");
when(tm.getSubscriberId()).thenReturn("3214561234567890");
@@ -74,18 +90,17 @@
when(tm.getSimOperator()).thenReturn("321456");
when(tm.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null);
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA,
- WifiEnterpriseConfig.Phase2.NONE)));
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP,
- WifiEnterpriseConfig.Phase2.AKA)));
+ WifiEnterpriseConfig.Phase2.AKA), mCarrierNetworkConfig));
}
@Test
public void getSimIdentityEapAkaPrime() {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
final Pair<String, String> expectedIdentity = Pair.create(
"63214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", "");
@@ -94,76 +109,95 @@
when(tm.getSimOperator()).thenReturn("321456");
when(tm.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null);
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(
WifiEnterpriseConfig.Eap.AKA_PRIME,
- WifiEnterpriseConfig.Phase2.NONE)));
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP,
- WifiEnterpriseConfig.Phase2.AKA_PRIME)));
+ WifiEnterpriseConfig.Phase2.AKA_PRIME), mCarrierNetworkConfig));
}
/**
- * Verify that an expected identity is returned when using the encrypted IMSI.
- *
- * @throws Exception
+ * Verify that an expected identity is returned when using the encrypted IMSI encoded by
+ * RFC4648.
*/
@Test
- public void getEncryptedIdentityImsi() throws Exception {
+ public void getEncryptedIdentityImsiWithRfc4648() throws Exception {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
- String encryptedImsi = "EncryptedIMSI";
+ Cipher cipher = mock(Cipher.class);
+ PublicKey key = null;
+ int flag = Base64.NO_WRAP;
+ String imsi = "3214561234567890";
+ String encryptedImsi = Base64.encodeToString(imsi.getBytes(), 0, imsi.getBytes().length,
+ flag);
String encryptedIdentity = "\0" + encryptedImsi + "@wlan.mnc456.mcc321.3gppnetwork.org";
final Pair<String, String> expectedIdentity = Pair.create(
"03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", encryptedIdentity);
- PublicKey key = null;
- when(tm.getSubscriberId()).thenReturn("3214561234567890");
- when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
- when(tm.getSimOperator()).thenReturn("321456");
- ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456",
- TelephonyManager.KEY_TYPE_WLAN, null, key, null);
- when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN)))
- .thenReturn(info);
+ // static mocking
+ MockitoSession session = ExtendedMockito.mockitoSession().mockStatic(
+ Cipher.class).startMocking();
+ try {
+ when(Cipher.getInstance(anyString())).thenReturn(cipher);
+ when(cipher.doFinal(any(byte[].class))).thenReturn(imsi.getBytes());
+ when(tm.getSubscriberId()).thenReturn(imsi);
+ when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+ when(tm.getSimOperator()).thenReturn("321456");
+ ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456",
+ TelephonyManager.KEY_TYPE_WLAN, null, key, null);
+ when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN)))
+ .thenReturn(info);
+ when(mCarrierNetworkConfig.getBase64EncodingFlag()).thenReturn(flag);
- when(telephonyUtil.encryptDataUsingPublicKey(any(), any())).thenReturn(encryptedImsi);
-
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
- WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA,
- WifiEnterpriseConfig.Phase2.NONE)));
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
+ WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA,
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
+ } finally {
+ session.finishMocking();
+ }
}
/**
- * Verify that an expected identity is returned when using the encrypted IMSI with key
- * identifier.
- *
- * @throws Exception
+ * Verify that an expected identity is returned when using the encrypted IMSI encoded by RFC2045
+ * with key identifier.
*/
@Test
- public void getEncryptedIdentityKeyIdentifier() throws Exception {
+ public void getEncryptedIdentityKeyIdentifierWithRfc2045() throws Exception {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
+ Cipher cipher = mock(Cipher.class);
+ int flag = Base64.DEFAULT;
PublicKey key = null;
String keyIdentifier = "key=testKey";
- String encryptedImsi = "EncryptedIMSI";
+ String imsi = "3214561234567890";
+ String encryptedImsi = Base64.encodeToString(imsi.getBytes(), 0, imsi.getBytes().length,
+ flag);
String encryptedIdentity = "\0" + encryptedImsi + "@wlan.mnc456.mcc321.3gppnetwork.org,"
+ keyIdentifier;
final Pair<String, String> expectedIdentity = Pair.create(
"03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", encryptedIdentity);
- when(tm.getSubscriberId()).thenReturn("3214561234567890");
- when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
- when(tm.getSimOperator()).thenReturn("321456");
- ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456",
- TelephonyManager.KEY_TYPE_WLAN, keyIdentifier, key, null);
- when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN)))
- .thenReturn(info);
+ // static mocking
+ MockitoSession session = ExtendedMockito.mockitoSession().mockStatic(
+ Cipher.class).startMocking();
+ try {
+ when(Cipher.getInstance(anyString())).thenReturn(cipher);
+ when(cipher.doFinal(any(byte[].class))).thenReturn(imsi.getBytes());
+ when(tm.getSubscriberId()).thenReturn(imsi);
+ when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+ when(tm.getSimOperator()).thenReturn("321456");
+ ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456",
+ TelephonyManager.KEY_TYPE_WLAN, keyIdentifier, key, null);
+ when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN)))
+ .thenReturn(info);
+ when(mCarrierNetworkConfig.getBase64EncodingFlag()).thenReturn(flag);
- when(telephonyUtil.encryptDataUsingPublicKey(any(), any())).thenReturn(encryptedImsi);
-
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
- WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA,
- WifiEnterpriseConfig.Phase2.NONE)));
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
+ WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA,
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
+ } finally {
+ session.finishMocking();
+ }
}
/**
@@ -174,8 +208,6 @@
@Test
public void getEncryptedIdentityFailed() throws Exception {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
- PublicKey key = null;
String imsi = "3214561234567890";
final Pair<String, String> expectedIdentity = Pair.create(
"03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", "");
@@ -183,22 +215,17 @@
when(tm.getSubscriberId()).thenReturn("3214561234567890");
when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
when(tm.getSimOperator()).thenReturn("321456");
- ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456",
- TelephonyManager.KEY_TYPE_WLAN, null, key, null);
when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN)))
- .thenReturn(info);
- when(telephonyUtil.encryptDataUsingPublicKey(any(), aryEq(imsi.getBytes())))
.thenReturn(null);
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA,
- WifiEnterpriseConfig.Phase2.NONE)));
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
}
@Test
public void getSimIdentity2DigitMnc() {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
final Pair<String, String> expectedIdentity = Pair.create(
"1321560123456789@wlan.mnc056.mcc321.3gppnetwork.org", "");
@@ -207,15 +234,14 @@
when(tm.getSimOperator()).thenReturn("32156");
when(tm.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null);
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM,
- WifiEnterpriseConfig.Phase2.NONE)));
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
}
@Test
public void getSimIdentityUnknownMccMnc() {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
final Pair<String, String> expectedIdentity = Pair.create(
"13214560123456789@wlan.mnc456.mcc321.3gppnetwork.org", "");
@@ -224,36 +250,39 @@
when(tm.getSimOperator()).thenReturn(null);
when(tm.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null);
- assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM,
- WifiEnterpriseConfig.Phase2.NONE)));
+ WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig));
}
@Test
public void getSimIdentityWithNoTelephonyManager() {
assertEquals(null, TelephonyUtil.getSimIdentity(null, null,
WifiConfigurationTestUtil.createEapNetwork(
- WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)));
+ WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE),
+ mCarrierNetworkConfig));
}
@Test
public void getSimIdentityNonTelephonyConfig() {
TelephonyManager tm = mock(TelephonyManager.class);
- TelephonyUtil telephonyUtil = mock(TelephonyUtil.class);
when(tm.getSubscriberId()).thenReturn("321560123456789");
when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
when(tm.getSimOperator()).thenReturn("32156");
- assertEquals(null, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ assertEquals(null, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(
- WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.SIM)));
- assertEquals(null, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.SIM),
+ mCarrierNetworkConfig));
+ assertEquals(null, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(
- WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.MSCHAPV2)));
- assertEquals(null, TelephonyUtil.getSimIdentity(tm, telephonyUtil,
+ WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.MSCHAPV2),
+ mCarrierNetworkConfig));
+ assertEquals(null, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil,
WifiConfigurationTestUtil.createEapNetwork(
- WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE)));
+ WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE),
+ mCarrierNetworkConfig));
assertEquals(null, TelephonyUtil.getSimIdentity(
- tm, telephonyUtil, new WifiConfiguration()));
+ tm, mTelephonyUtil, new WifiConfiguration(), mCarrierNetworkConfig));
}
@Test