Merge "Don't bring down LOHS when disabling Tethering."
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 72f638a..2caf27f 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -2574,6 +2574,8 @@
wifiLockManager.handleScreenStateChanged(screenOn);
}
+ mSarManager.handleScreenStateChanged(screenOn);
+
if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn);
}
diff --git a/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java b/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java
index 0fae643..0c06488 100644
--- a/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java
+++ b/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java
@@ -23,7 +23,8 @@
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
/**
@@ -35,15 +36,18 @@
"DeletedEphemeralSSIDList";
private static final String XML_TAG_SSID_LIST = "SSIDList";
- private Set<String> mSsidList;
+ private final Clock mClock;
+ private Map<String, Long> mSsidToTimeMap;
- DeletedEphemeralSsidsStoreData() {}
+ DeletedEphemeralSsidsStoreData(Clock clock) {
+ mClock = clock;
+ }
@Override
public void serializeData(XmlSerializer out)
throws XmlPullParserException, IOException {
- if (mSsidList != null) {
- XmlUtil.writeNextValue(out, XML_TAG_SSID_LIST, mSsidList);
+ if (mSsidToTimeMap != null) {
+ XmlUtil.writeNextValue(out, XML_TAG_SSID_LIST, mSsidToTimeMap);
}
}
@@ -62,7 +66,17 @@
}
switch (valueName[0]) {
case XML_TAG_SSID_LIST:
- mSsidList = (Set<String>) value;
+ // Backwards compatibility, this used to be a set.
+ if (value instanceof Set) {
+ mSsidToTimeMap = new HashMap<>();
+ for (String ssid : (Set<String>) value) {
+ // Mark the deleted time as bootup time for existing entries from
+ // previous releases.
+ mSsidToTimeMap.put(ssid, mClock.getWallClockMillis());
+ }
+ } else if (value instanceof Map) {
+ mSsidToTimeMap = (Map<String, Long>) value;
+ }
break;
default:
throw new XmlPullParserException("Unknown tag under "
@@ -74,7 +88,7 @@
@Override
public void resetData() {
- mSsidList = null;
+ mSsidToTimeMap = null;
}
@Override
@@ -95,19 +109,19 @@
}
/**
- * An empty set will be returned for null SSID list.
+ * An empty map will be returned for null SSID list.
*
- * @return Set of SSIDs
+ * @return Map of SSIDs
*/
- public Set<String> getSsidList() {
- if (mSsidList == null) {
- return new HashSet<String>();
+ public Map<String, Long> getSsidToTimeMap() {
+ if (mSsidToTimeMap == null) {
+ return new HashMap<String, Long>();
}
- return mSsidList;
+ return mSsidToTimeMap;
}
- public void setSsidList(Set<String> ssidList) {
- mSsidList = ssidList;
+ public void setSsidToTimeMap(Map<String, Long> ssidMap) {
+ mSsidToTimeMap = ssidMap;
}
}
diff --git a/service/java/com/android/server/wifi/SarInfo.java b/service/java/com/android/server/wifi/SarInfo.java
index a62307e..7d58065 100644
--- a/service/java/com/android/server/wifi/SarInfo.java
+++ b/service/java/com/android/server/wifi/SarInfo.java
@@ -74,6 +74,7 @@
public boolean isWifiSapEnabled = false;
public boolean isWifiScanOnlyEnabled = false;
public boolean isVoiceCall = false;
+ public boolean isEarPieceActive = false;
public int attemptedSarScenario = RESET_SAR_SCENARIO;
private boolean mAllWifiDisabled = true;
@@ -82,6 +83,7 @@
private int mLastReportedSensorState = SAR_SENSOR_FREE_SPACE;
private boolean mLastReportedIsWifiSapEnabled = false;
private boolean mLastReportedIsVoiceCall = false;
+ private boolean mLastReportedIsEarPieceActive = false;
private int mLastReportedScenario = INITIAL_SAR_SCENARIO;
private long mLastReportedScenarioTs = 0;
@@ -113,7 +115,8 @@
/* Check if some change happened since last successful reporting */
if ((sensorState != mLastReportedSensorState)
|| (isWifiSapEnabled != mLastReportedIsWifiSapEnabled)
- || (isVoiceCall != mLastReportedIsVoiceCall)) {
+ || (isVoiceCall != mLastReportedIsVoiceCall)
+ || (isEarPieceActive != mLastReportedIsEarPieceActive)) {
return true;
} else {
return false;
@@ -129,6 +132,7 @@
mLastReportedSensorState = sensorState;
mLastReportedIsWifiSapEnabled = isWifiSapEnabled;
mLastReportedIsVoiceCall = isVoiceCall;
+ mLastReportedIsEarPieceActive = isEarPieceActive;
mLastReportedScenario = attemptedSarScenario;
mLastReportedScenarioTs = System.currentTimeMillis();
@@ -169,10 +173,12 @@
pw.println(" Wifi Client state is: " + isWifiClientEnabled);
pw.println(" Wifi Soft AP state is: " + isWifiSapEnabled);
pw.println(" Wifi ScanOnly state is: " + isWifiScanOnlyEnabled);
+ pw.println(" Earpiece state is : " + isEarPieceActive);
pw.println("Last reported values:");
pw.println(" Sensor state is: " + sensorStateToString(mLastReportedSensorState));
pw.println(" Soft AP state is: " + mLastReportedIsWifiSapEnabled);
pw.println(" Voice Call state is: " + mLastReportedIsVoiceCall);
+ pw.println(" Earpiece state is: " + mLastReportedIsEarPieceActive);
pw.println("Last reported scenario: " + mLastReportedScenario);
pw.println("Reported " + (System.currentTimeMillis() - mLastReportedScenarioTs) / 1000
+ " seconds ago");
diff --git a/service/java/com/android/server/wifi/SarManager.java b/service/java/com/android/server/wifi/SarManager.java
index 5227d23..a35f65f 100644
--- a/service/java/com/android/server/wifi/SarManager.java
+++ b/service/java/com/android/server/wifi/SarManager.java
@@ -20,12 +20,18 @@
import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK;
import static android.telephony.TelephonyManager.CALL_STATE_RINGING;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.media.AudioManager;
+import android.media.AudioSystem;
import android.net.wifi.WifiManager;
+import android.os.Handler;
import android.os.Looper;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
@@ -33,6 +39,7 @@
import android.util.Log;
import com.android.internal.R;
+import com.android.server.wifi.util.WifiHandler;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -49,6 +56,8 @@
* - It constructs the sar info and send it towards the HAL
*/
public class SarManager {
+ // Period for checking on voice steam active (in ms)
+ private static final int CHECK_VOICE_STREAM_INTERVAL_MS = 5000;
/* For Logging */
private static final String TAG = "WifiSarManager";
private boolean mVerboseLoggingEnabled = true;
@@ -66,6 +75,10 @@
private int mSarSensorEventNearHand;
private int mSarSensorEventNearHead;
+ // Device starts with screen on
+ private boolean mScreenOn = false;
+ private boolean mIsVoiceStreamCheckEnabled = false;
+
/**
* Other parameters passed in or created in the constructor.
*/
@@ -75,6 +88,7 @@
private final WifiNative mWifiNative;
private final SarSensorEventListener mSensorListener;
private final SensorManager mSensorManager;
+ private final Handler mHandler;
private final Looper mLooper;
private final WifiMetrics mWifiMetrics;
@@ -91,6 +105,7 @@
mTelephonyManager = telephonyManager;
mWifiNative = wifiNative;
mLooper = looper;
+ mHandler = new WifiHandler(TAG, looper);
mSensorManager = sensorManager;
mWifiMetrics = wifiMetrics;
mPhoneStateListener = new WifiPhoneStateListener(looper);
@@ -104,6 +119,80 @@
}
}
+ /**
+ * Notify SarManager of screen status change
+ */
+ public void handleScreenStateChanged(boolean screenOn) {
+ if (!mSupportSarVoiceCall) {
+ return;
+ }
+
+ if (mScreenOn == screenOn) {
+ return;
+ }
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "handleScreenStateChanged: screenOn = " + screenOn);
+ }
+
+ mScreenOn = screenOn;
+
+ // Only schedule a voice stream check if screen is turning on, and it is currently not
+ // scheduled
+ if (mScreenOn && !mIsVoiceStreamCheckEnabled) {
+ mHandler.post(() -> {
+ checkAudioDevice();
+ });
+
+ mIsVoiceStreamCheckEnabled = true;
+ }
+ }
+
+ private boolean isVoiceCallOnEarpiece() {
+ AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+
+ return (audioManager.getDevicesForStream(AudioManager.STREAM_VOICE_CALL)
+ == AudioManager.DEVICE_OUT_EARPIECE);
+ }
+
+ private boolean isVoiceCallStreamActive() {
+ return AudioSystem.isStreamActive(AudioManager.STREAM_VOICE_CALL, 0);
+ }
+
+ private void checkAudioDevice() {
+ // First Check if audio stream is on
+ boolean voiceStreamActive = isVoiceCallStreamActive();
+ boolean earPieceActive;
+
+ if (voiceStreamActive) {
+ // Check on the audio route
+ earPieceActive = isVoiceCallOnEarpiece();
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "EarPiece active = " + earPieceActive);
+ }
+ } else {
+ earPieceActive = false;
+ }
+
+ // If audio route has changed, update SAR
+ if (earPieceActive != mSarInfo.isEarPieceActive) {
+ mSarInfo.isEarPieceActive = earPieceActive;
+ updateSarScenario();
+ }
+
+ // Now should we proceed with the checks
+ if (!mScreenOn && !voiceStreamActive) {
+ // No need to continue checking
+ mIsVoiceStreamCheckEnabled = false;
+ } else {
+ // Schedule another check
+ mHandler.postDelayed(() -> {
+ checkAudioDevice();
+ }, CHECK_VOICE_STREAM_INTERVAL_MS);
+ }
+ }
+
private void readSarConfigs() {
mSupportSarTxPowerLimit = mContext.getResources().getBoolean(
R.bool.config_wifi_framework_enable_sar_tx_power_limit);
@@ -148,6 +237,7 @@
if (mSupportSarVoiceCall) {
/* Listen for Phone State changes */
registerPhoneStateListener();
+ registerVoiceStreamListener();
}
/* Only listen for SAR sensor if supported */
@@ -162,6 +252,56 @@
}
}
+ private void registerVoiceStreamListener() {
+ Log.i(TAG, "Registering for voice stream status");
+
+ // Register for listening to transitions of change of voice stream devices
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean voiceStreamActive = isVoiceCallStreamActive();
+ if (!voiceStreamActive) {
+ // No need to proceed, there is no voice call ongoing
+ return;
+ }
+
+ String action = intent.getAction();
+ int streamType =
+ intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ int device = intent.getIntExtra(
+ AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
+ int oldDevice = intent.getIntExtra(
+ AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
+
+ if (streamType == AudioManager.STREAM_VOICE_CALL) {
+ boolean earPieceActive = mSarInfo.isEarPieceActive;
+ if (device == AudioManager.DEVICE_OUT_EARPIECE) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Switching to earpiece : HEAD ON");
+ Log.d(TAG, "Old device = " + oldDevice);
+ }
+ earPieceActive = true;
+ } else if (oldDevice == AudioManager.DEVICE_OUT_EARPIECE) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Switching from earpiece : HEAD OFF");
+ Log.d(TAG, "New device = " + device);
+ }
+ earPieceActive = false;
+ }
+
+ if (earPieceActive != mSarInfo.isEarPieceActive) {
+ mSarInfo.isEarPieceActive = earPieceActive;
+ updateSarScenario();
+ }
+ }
+ }
+ }, filter, null, mHandler);
+ }
+
/**
* Register the phone state listener.
*/
@@ -280,6 +420,10 @@
/* Report change to HAL if needed */
if (mSarInfo.isVoiceCall != newIsVoiceCall) {
mSarInfo.isVoiceCall = newIsVoiceCall;
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Voice Call = " + newIsVoiceCall);
+ }
updateSarScenario();
}
}
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 61157bd..d32bb4b 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -229,6 +229,12 @@
private static final int WIFI_PNO_RECENCY_SORTING_ENABLED_DEFAULT = 0; // 0 = disabled:
/**
+ * Expiration timeout for deleted ephemeral ssids. (1 day)
+ */
+ @VisibleForTesting
+ public static final long DELETED_EPHEMERAL_SSID_EXPIRY_MS = (long) 1000 * 60 * 60 * 24;
+
+ /**
* General sorting algorithm of all networks for scanning purposes:
* Place the configurations in descending order of their |numAssociation| values. If networks
* have the same |numAssociation|, place the configurations with
@@ -279,11 +285,13 @@
private final Map<Integer, ScanDetailCache> mScanDetailCaches;
/**
* Framework keeps a list of ephemeral SSIDs that where deleted by user,
- * so as, framework knows not to autoconnect again those SSIDs based on scorer input.
- * The list is never cleared up.
+ * framework knows not to autoconnect again even if the app/scorer recommends it.
+ * The entries are deleted after 24 hours.
* The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field.
+ *
+ * The map stores the SSID and the wall clock time when the network was deleted.
*/
- private final Set<String> mDeletedEphemeralSSIDs;
+ private final Map<String, Long> mDeletedEphemeralSsidsToTimeMap;
/**
* Framework keeps a mapping from configKey to the randomized MAC address so that
@@ -393,7 +401,7 @@
mConfiguredNetworks = new ConfigurationMap(userManager);
mScanDetailCaches = new HashMap<>(16, 0.75f);
- mDeletedEphemeralSSIDs = new HashSet<>();
+ mDeletedEphemeralSsidsToTimeMap = new HashMap<>();
mRandomizedMacAddressMapping = new HashMap<>();
// Register store data for network list and deleted ephemeral SSIDs.
@@ -1199,7 +1207,7 @@
return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
}
- if (mDeletedEphemeralSSIDs.remove(config.SSID)) {
+ if (mDeletedEphemeralSsidsToTimeMap.remove(config.SSID) != null) {
if (mVerboseLoggingEnabled) {
Log.v(TAG, "Removed from ephemeral blacklist: " + config.SSID);
}
@@ -2674,21 +2682,34 @@
}
/**
- * Check if the provided ephemeral network was deleted by the user or not.
+ * Check if the provided ephemeral network was deleted by the user or not. This call also clears
+ * the SSID from the deleted ephemeral network map, if the duration has expired the
+ * timeout specified by {@link #DELETED_EPHEMERAL_SSID_EXPIRY_MS}.
*
* @param ssid caller must ensure that the SSID passed thru this API match
* the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
* @return true if network was deleted, false otherwise.
*/
public boolean wasEphemeralNetworkDeleted(String ssid) {
- return mDeletedEphemeralSSIDs.contains(ssid);
+ if (!mDeletedEphemeralSsidsToTimeMap.containsKey(ssid)) {
+ return false;
+ }
+ long deletedTimeInMs = mDeletedEphemeralSsidsToTimeMap.get(ssid);
+ long nowInMs = mClock.getWallClockMillis();
+ // Clear the ssid from the map if the age > |DELETED_EPHEMERAL_SSID_EXPIRY_MS|.
+ if (nowInMs - deletedTimeInMs > DELETED_EPHEMERAL_SSID_EXPIRY_MS) {
+ mDeletedEphemeralSsidsToTimeMap.remove(ssid);
+ return false;
+ }
+ return true;
}
/**
* Disable an ephemeral SSID for the purpose of network selection.
*
- * The only way to "un-disable it" is if the user create a network for that SSID and then
- * forget it.
+ * The network will be re-enabled when:
+ * a) The user creates a network for that SSID and then forgets.
+ * b) The time specified by {@link #DELETED_EPHEMERAL_SSID_EXPIRY_MS} expires after the disable.
*
* @param ssid caller must ensure that the SSID passed thru this API match
* the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
@@ -2706,8 +2727,10 @@
break;
}
}
- mDeletedEphemeralSSIDs.add(ssid);
- Log.d(TAG, "Forget ephemeral SSID " + ssid + " num=" + mDeletedEphemeralSSIDs.size());
+ // Store the ssid & the wall clock time at which the network was disabled.
+ mDeletedEphemeralSsidsToTimeMap.put(ssid, mClock.getWallClockMillis());
+ Log.d(TAG, "Forget ephemeral SSID " + ssid + " num="
+ + mDeletedEphemeralSsidsToTimeMap.size());
if (foundConfig != null) {
Log.d(TAG, "Found ephemeral config in disableEphemeralNetwork: "
+ foundConfig.networkId);
@@ -2720,7 +2743,7 @@
*/
@VisibleForTesting
public void clearDeletedEphemeralNetworks() {
- mDeletedEphemeralSSIDs.clear();
+ mDeletedEphemeralSsidsToTimeMap.clear();
}
/**
@@ -2887,7 +2910,7 @@
private void clearInternalData() {
localLog("clearInternalData: Clearing all internal data");
mConfiguredNetworks.clear();
- mDeletedEphemeralSSIDs.clear();
+ mDeletedEphemeralSsidsToTimeMap.clear();
mRandomizedMacAddressMapping.clear();
mScanDetailCaches.clear();
clearLastSelectedNetwork();
@@ -2918,7 +2941,7 @@
mConfiguredNetworks.remove(config.networkId);
}
}
- mDeletedEphemeralSSIDs.clear();
+ mDeletedEphemeralSsidsToTimeMap.clear();
mScanDetailCaches.clear();
clearLastSelectedNetwork();
return removedNetworkIds;
@@ -2951,12 +2974,14 @@
* Helper function to populate the internal (in-memory) data from the retrieved user store
* (file) data.
*
- * @param configurations list of configurations retrieved from store.
- * @param deletedEphemeralSSIDs list of ssid's representing the ephemeral networks deleted by
- * the user.
+ * @param configurations list of configurations retrieved from store.
+ * @param deletedEphemeralSsidsToTimeMap map of ssid's representing the ephemeral networks
+ * deleted by the user to the wall clock time at which
+ * it was deleted.
*/
private void loadInternalDataFromUserStore(
- List<WifiConfiguration> configurations, Set<String> deletedEphemeralSSIDs) {
+ List<WifiConfiguration> configurations,
+ Map<String, Long> deletedEphemeralSsidsToTimeMap) {
for (WifiConfiguration configuration : configurations) {
configuration.networkId = mNextNetworkId++;
if (mVerboseLoggingEnabled) {
@@ -2968,9 +2993,7 @@
Log.e(TAG, "Failed to add network to config map", e);
}
}
- for (String ssid : deletedEphemeralSSIDs) {
- mDeletedEphemeralSSIDs.add(ssid);
- }
+ mDeletedEphemeralSsidsToTimeMap.putAll(deletedEphemeralSsidsToTimeMap);
}
/**
@@ -2990,20 +3013,22 @@
* 1. Clears all existing internal data.
* 2. Sends out the networks changed broadcast after loading all the data.
*
- * @param sharedConfigurations list of network configurations retrieved from shared store.
- * @param userConfigurations list of network configurations retrieved from user store.
- * @param deletedEphemeralSSIDs list of ssid's representing the ephemeral networks deleted by
- * the user.
+ * @param sharedConfigurations list of network configurations retrieved from shared store.
+ * @param userConfigurations list of network configurations retrieved from user store.
+ * @param deletedEphemeralSsidsToTimeMap map of ssid's representing the ephemeral networks
+ * deleted by the user to the wall clock time at which
+ * it was deleted.
*/
private void loadInternalData(
List<WifiConfiguration> sharedConfigurations,
- List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSSIDs,
+ List<WifiConfiguration> userConfigurations,
+ Map<String, Long> deletedEphemeralSsidsToTimeMap,
Map<String, String> macAddressMapping) {
// Clear out all the existing in-memory lists and load the lists from what was retrieved
// from the config store.
clearInternalData();
loadInternalDataFromSharedStore(sharedConfigurations, macAddressMapping);
- loadInternalDataFromUserStore(userConfigurations, deletedEphemeralSSIDs);
+ loadInternalDataFromUserStore(userConfigurations, deletedEphemeralSsidsToTimeMap);
generateRandomizedMacAddresses();
if (mConfiguredNetworks.sizeForAllUsers() == 0) {
Log.w(TAG, "No stored networks found.");
@@ -3044,7 +3069,7 @@
}
loadInternalData(mNetworkListSharedStoreData.getConfigurations(),
mNetworkListUserStoreData.getConfigurations(),
- mDeletedEphemeralSsidsStoreData.getSsidList(),
+ mDeletedEphemeralSsidsStoreData.getSsidToTimeMap(),
mRandomizedMacStoreData.getMacMapping());
return true;
}
@@ -3073,7 +3098,7 @@
return false;
}
loadInternalDataFromUserStore(mNetworkListUserStoreData.getConfigurations(),
- mDeletedEphemeralSsidsStoreData.getSsidList());
+ mDeletedEphemeralSsidsStoreData.getSsidToTimeMap());
return true;
}
@@ -3134,7 +3159,7 @@
// Setup store data for write.
mNetworkListSharedStoreData.setConfigurations(sharedConfigurations);
mNetworkListUserStoreData.setConfigurations(userConfigurations);
- mDeletedEphemeralSsidsStoreData.setSsidList(mDeletedEphemeralSSIDs);
+ mDeletedEphemeralSsidsStoreData.setSsidToTimeMap(mDeletedEphemeralSsidsToTimeMap);
mRandomizedMacStoreData.setMacMapping(mRandomizedMacAddressMapping);
try {
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index d733553..d239239 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
+import static java.lang.Math.toIntExact;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -158,6 +160,7 @@
* Clock instance to retrieve timestamps for alarms.
*/
private final Clock mClock;
+ private final WifiMetrics mWifiMetrics;
/**
* Shared config store file instance. There is 1 shared store file:
* {@link #STORE_FILE_NAME_SHARED_GENERAL}.
@@ -202,15 +205,17 @@
* @param context context to use for retrieving the alarm manager.
* @param looper looper instance to post alarm timeouts to.
* @param clock clock instance to retrieve timestamps for alarms.
+ * @param wifiMetrics Metrics instance.
* @param sharedStore StoreFile instance pointing to the shared store file. This should
* be retrieved using {@link #createSharedFile()} method.
*/
- public WifiConfigStore(Context context, Looper looper, Clock clock,
+ public WifiConfigStore(Context context, Looper looper, Clock clock, WifiMetrics wifiMetrics,
StoreFile sharedStore) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mEventHandler = new Handler(looper);
mClock = clock;
+ mWifiMetrics = wifiMetrics;
mStoreDataList = new ArrayList<>();
// Initialize the store files.
@@ -447,7 +452,11 @@
}
}
long writeTime = mClock.getElapsedSinceBootMillis() - writeStartTime;
-
+ try {
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(toIntExact(writeTime));
+ } catch (ArithmeticException e) {
+ // Silently ignore on any overflow errors.
+ }
Log.d(TAG, "Writing to stores completed in " + writeTime + " ms.");
}
@@ -475,6 +484,11 @@
}
}
long readTime = mClock.getElapsedSinceBootMillis() - readStartTime;
+ try {
+ mWifiMetrics.noteWifiConfigStoreReadDuration(toIntExact(readTime));
+ } catch (ArithmeticException e) {
+ // Silently ignore on any overflow errors.
+ }
Log.d(TAG, "Reading from all stores completed in " + readTime + " ms.");
}
@@ -504,6 +518,7 @@
deserializeData(userDataBytes, userStoreFile);
}
long readTime = mClock.getElapsedSinceBootMillis() - readStartTime;
+ mWifiMetrics.noteWifiConfigStoreReadDuration(toIntExact(readTime));
Log.d(TAG, "Reading from user stores completed in " + readTime + " ms.");
}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 437ec0d..c03c46a 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -226,7 +226,7 @@
// New config store
mWifiKeyStore = new WifiKeyStore(mKeyStore);
mWifiConfigStore = new WifiConfigStore(
- mContext, clientModeImplLooper, mClock,
+ mContext, clientModeImplLooper, mClock, mWifiMetrics,
WifiConfigStore.createSharedFile());
// Config Manager
mWifiConfigManager = new WifiConfigManager(mContext, mClock,
@@ -234,7 +234,7 @@
mWifiKeyStore, mWifiConfigStore, mWifiPermissionsUtil,
mWifiPermissionsWrapper, new NetworkListSharedStoreData(mContext),
new NetworkListUserStoreData(mContext),
- new DeletedEphemeralSsidsStoreData(), new RandomizedMacStoreData(),
+ new DeletedEphemeralSsidsStoreData(mClock), new RandomizedMacStoreData(),
mFrameworkFacade, mWifiCoreHandlerThread.getLooper());
mWifiScoreCard = new WifiScoreCard(mClock, "TODO(b/112196799) seed me properly");
mWifiMetrics.setWifiConfigManager(mWifiConfigManager);
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index fe34b0e..86b933c 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
+import static java.lang.StrictMath.toIntExact;
+
import android.content.Context;
import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
import android.net.NetworkAgent;
@@ -67,6 +69,7 @@
import com.android.server.wifi.rtt.RttMetrics;
import com.android.server.wifi.util.ExternalCallbackTracker;
import com.android.server.wifi.util.InformationElementUtil;
+import com.android.server.wifi.util.MetricsUtils;
import com.android.server.wifi.util.ScanResultUtil;
import org.json.JSONArray;
@@ -145,6 +148,15 @@
public static final int MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD = 2;
public static final int NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD = 100;
public static final int MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS = 1000 * 3600; // 1 hour
+ // Histogram for WifiConfigStore IO duration times. Indicates the following 5 buckets (in ms):
+ // < 50
+ // [50, 100)
+ // [100, 150)
+ // [150, 200)
+ // [200, 300)
+ // >= 300
+ private static final int[] WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS =
+ {50, 100, 150, 200, 300};
private Clock mClock;
private boolean mScreenOn;
@@ -302,6 +314,12 @@
/** DPP */
private final DppMetrics mDppMetrics;
+ /** WifiConfigStore read duration histogram. */
+ private SparseIntArray mWifiConfigStoreReadDurationHistogram = new SparseIntArray();
+
+ /** WifiConfigStore write duration histogram. */
+ private SparseIntArray mWifiConfigStoreWriteDurationHistogram = new SparseIntArray();
+
class RouterFingerPrint {
private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto;
RouterFingerPrint() {
@@ -2522,6 +2540,11 @@
mWifiP2pMetrics.dump(pw);
pw.println("mDppMetrics:");
mDppMetrics.dump(pw);
+
+ pw.println("mWifiConfigStoreReadDurationHistogram:"
+ + mWifiConfigStoreReadDurationHistogram.toString());
+ pw.println("mWifiConfigStoreWriteDurationHistogram:"
+ + mWifiConfigStoreWriteDurationHistogram.toString());
}
}
}
@@ -2989,6 +3012,12 @@
.toArray(new DeviceMobilityStatePnoScanStats[0]);
mWifiLogProto.wifiP2PStats = mWifiP2pMetrics.consolidateProto();
mWifiLogProto.wifiDppLog = mDppMetrics.consolidateProto();
+ mWifiLogProto.wifiConfigStoreIo = new WifiMetricsProto.WifiConfigStoreIO();
+ mWifiLogProto.wifiConfigStoreIo.readDurations =
+ makeWifiConfigStoreIODurationBucketArray(mWifiConfigStoreReadDurationHistogram);
+ mWifiLogProto.wifiConfigStoreIo.writeDurations =
+ makeWifiConfigStoreIODurationBucketArray(
+ mWifiConfigStoreWriteDurationHistogram);
}
}
@@ -3020,6 +3049,27 @@
return array;
}
+ private WifiMetricsProto.WifiConfigStoreIO.DurationBucket[]
+ makeWifiConfigStoreIODurationBucketArray(SparseIntArray sia) {
+ MetricsUtils.GenericBucket[] genericBuckets =
+ MetricsUtils.linearHistogramToGenericBuckets(sia,
+ WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
+ WifiMetricsProto.WifiConfigStoreIO.DurationBucket[] array =
+ new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[genericBuckets.length];
+ try {
+ for (int i = 0; i < genericBuckets.length; i++) {
+ array[i] = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket();
+ array[i].rangeStartMs = toIntExact(genericBuckets[i].start);
+ array[i].rangeEndMs = toIntExact(genericBuckets[i].end);
+ array[i].count = genericBuckets[i].count;
+ }
+ } catch (ArithmeticException e) {
+ // Return empty array on any overflow errors.
+ array = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[0];
+ }
+ return array;
+ }
+
/**
* Clear all WifiMetrics, except for currentConnectionEvent and Open Network Notification
* feature enabled state, blacklist size.
@@ -3094,6 +3144,8 @@
android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
mProbeElapsedTimeMsSinceLastUpdate = -1;
mProbeMcsRateSinceLastUpdate = -1;
+ mWifiConfigStoreReadDurationHistogram.clear();
+ mWifiConfigStoreWriteDurationHistogram.clear();
}
}
@@ -4174,4 +4226,28 @@
}
// TODO(b/112029045): aggregate metrics
}
+
+ /**
+ * Update wifi config store read duration.
+ *
+ * @param timeMs Time it took to complete the operation, in milliseconds
+ */
+ public void noteWifiConfigStoreReadDuration(int timeMs) {
+ synchronized (mLock) {
+ MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreReadDurationHistogram,
+ WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
+ }
+ }
+
+ /**
+ * Update wifi config store write duration.
+ *
+ * @param timeMs Time it took to complete the operation, in milliseconds
+ */
+ public void noteWifiConfigStoreWriteDuration(int timeMs) {
+ synchronized (mLock) {
+ MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreWriteDurationHistogram,
+ WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index ee43845..38d36f8 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -701,22 +701,26 @@
// Disable Auto-join so that NetworkFactory can take control of the network connection.
mWifiConnectivityManager.setSpecificNetworkRequestInProgress(true);
+ // Copy over the credentials from the app's request and then copy the ssid from user
+ // selection.
+ 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()) {
- network.BSSID =
+ networkToConnect.BSSID =
mActiveSpecificNetworkRequestSpecifier.bssidPatternMatcher.first.toString();
}
-
// Mark the network ephemeral so that it's automatically removed at the end of connection.
- network.ephemeral = true;
- network.fromWifiNetworkSpecifier = true;
+ networkToConnect.ephemeral = true;
+ networkToConnect.fromWifiNetworkSpecifier = true;
// Store the user selected network.
- mUserSelectedNetwork = network;
+ mUserSelectedNetwork = networkToConnect;
// Trigger connection to the network.
- connectToNetwork(network);
+ connectToNetwork(networkToConnect);
}
private void handleConnectToNetworkUserSelection(WifiConfiguration network) {
@@ -729,7 +733,7 @@
handleConnectToNetworkUserSelectionInternal(network);
// Add the network to the approved access point map for the app.
- addNetworkToUserApprovedAccessPointMap(network);
+ addNetworkToUserApprovedAccessPointMap(mUserSelectedNetwork);
}
private void handleRejectUserSelection() {
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index 9f7a2ff..d273c8f 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -2324,7 +2324,7 @@
/* As long as no voice call is active (in case voice call is supported),
* no backoff is needed */
if (sarInfo.sarVoiceCallSupported) {
- return sarInfo.isVoiceCall;
+ return (sarInfo.isVoiceCall || sarInfo.isEarPieceActive);
} else {
return false;
}
@@ -2339,7 +2339,7 @@
* Otherwise, an exception is thrown.
*/
private int frameworkToHalTxPowerScenario_1_1(SarInfo sarInfo) {
- if (sarInfo.sarVoiceCallSupported && sarInfo.isVoiceCall) {
+ if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) {
return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL;
} else {
throw new IllegalArgumentException("bad scenario: voice call not active/supported");
@@ -2363,7 +2363,7 @@
if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) {
return true;
}
- if (sarInfo.sarVoiceCallSupported && sarInfo.isVoiceCall) {
+ if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) {
return true;
}
return false;
@@ -2412,7 +2412,7 @@
throw new IllegalArgumentException("bad scenario: Invalid sensor state");
}
} else if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) {
- if (sarInfo.isVoiceCall) {
+ if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) {
return android.hardware.wifi.V1_2.IWifiChip
.TxPowerScenario.ON_HEAD_CELL_ON;
} else if (sarInfo.isWifiSapEnabled) {
@@ -2423,7 +2423,7 @@
}
} else if (sarInfo.sarVoiceCallSupported) {
/* SAR Sensors and SoftAP not supported, act like V1_1 */
- if (sarInfo.isVoiceCall) {
+ if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) {
return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL;
} else {
throw new IllegalArgumentException("bad scenario: voice call not active");
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index fe17f4b..d9d3017 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -382,10 +382,18 @@
// potential transmission mechanism for port/transport-protocol information from
// Responder (alternative to confirm message)
- Pair<Integer, Integer> peerServerInfo = NetworkInformationData.parseTlv(message);
+ NetworkInformationData.ParsedResults peerServerInfo = NetworkInformationData.parseTlv(
+ message);
if (peerServerInfo != null) {
- nnriE.getValue().peerPort = peerServerInfo.first;
- nnriE.getValue().peerTransportProtocol = peerServerInfo.second;
+ if (peerServerInfo.port != 0) {
+ nnriE.getValue().peerPort = peerServerInfo.port;
+ }
+ if (peerServerInfo.transportProtocol != -1) {
+ nnriE.getValue().peerTransportProtocol = peerServerInfo.transportProtocol;
+ }
+ if (peerServerInfo.ipv6Override != null) {
+ nnriE.getValue().peerIpv6Override = peerServerInfo.ipv6Override;
+ }
}
return null; // ignore this for NDP set up flow: it is used to obtain app_info from Resp
@@ -561,24 +569,51 @@
}
}
- try {
- nnri.peerIpv6 = Inet6Address.getByAddress(null,
- MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress(),
- NetworkInterface.getByName(nnri.interfaceName));
- } catch (SocketException | UnknownHostException e) {
- Log.e(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e);
- nnri.peerIpv6 = null;
- }
// only relevant for the initiator
if (nnri.networkSpecifier.role
== WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
- Pair<Integer, Integer> peerServerInfo = NetworkInformationData.parseTlv(message);
+ NetworkInformationData.ParsedResults peerServerInfo =
+ NetworkInformationData.parseTlv(message);
if (peerServerInfo != null) {
- nnri.peerPort = peerServerInfo.first;
- nnri.peerTransportProtocol = peerServerInfo.second;
+ if (peerServerInfo.port != 0) {
+ nnri.peerPort = peerServerInfo.port;
+ }
+ if (peerServerInfo.transportProtocol != -1) {
+ nnri.peerTransportProtocol = peerServerInfo.transportProtocol;
+ }
+ if (peerServerInfo.ipv6Override != null) {
+ nnri.peerIpv6Override = peerServerInfo.ipv6Override;
+ }
}
}
+ try {
+ if (nnri.peerIpv6Override == null) {
+ nnri.peerIpv6 = Inet6Address.getByAddress(null,
+ MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress(),
+ NetworkInterface.getByName(nnri.interfaceName));
+ } else {
+ byte[] addr = new byte[16];
+
+ addr[0] = (byte) 0xfe;
+ addr[1] = (byte) 0x80;
+ addr[8] = nnri.peerIpv6Override[0];
+ addr[9] = nnri.peerIpv6Override[1];
+ addr[10] = nnri.peerIpv6Override[2];
+ addr[11] = nnri.peerIpv6Override[3];
+ addr[12] = nnri.peerIpv6Override[4];
+ addr[13] = nnri.peerIpv6Override[5];
+ addr[14] = nnri.peerIpv6Override[6];
+ addr[15] = nnri.peerIpv6Override[7];
+
+ nnri.peerIpv6 = Inet6Address.getByAddress(null, addr,
+ NetworkInterface.getByName(nnri.interfaceName));
+ }
+ } catch (SocketException | UnknownHostException e) {
+ Log.e(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e);
+ nnri.peerIpv6 = null;
+ }
+
if (nnri.peerIpv6 != null) {
networkCapabilities.setTransportInfo(
new WifiAwareNetworkInfo(nnri.peerIpv6, nnri.peerPort,
@@ -1078,6 +1113,7 @@
public Inet6Address peerIpv6;
public int peerPort = 0; // uninitialized (invalid) value
public int peerTransportProtocol = -1; // uninitialized (invalid) value
+ public byte[] peerIpv6Override = null;
public WifiAwareNetworkSpecifier networkSpecifier;
public List<NanDataPathChannelInfo> channelInfo;
public long startTimestamp = 0; // request is made (initiator) / get request (responder)
@@ -1479,12 +1515,27 @@
return tlvc.getArray();
}
+ static class ParsedResults {
+ ParsedResults(int port, int transportProtocol, byte[] ipv6Override) {
+ this.port = port;
+ this.transportProtocol = transportProtocol;
+ this.ipv6Override = ipv6Override;
+ }
+
+ public int port = 0;
+ public int transportProtocol = -1;
+ public byte[] ipv6Override = null;
+ }
+
/**
- * Parse the TLV and return <port, transportProtocol>.
+ * Parse the TLV and returns:
+ * - Null on parsing error
+ * - <port | 0, transport-protocol | -1, ipv6-override | null> otherwise
*/
- public static Pair<Integer, Integer> parseTlv(byte[] tlvs) {
+ public static ParsedResults parseTlv(byte[] tlvs) {
int port = 0;
int transportProtocol = -1;
+ byte[] ipv6Override = null;
try {
TlvBufferUtils.TlvIterable tlvi = new TlvBufferUtils.TlvIterable(1, 2, tlvs);
@@ -1492,17 +1543,21 @@
for (TlvBufferUtils.TlvElement tlve : tlvi) {
switch (tlve.type) {
case IPV6_LL_TYPE:
- Log.w(TAG,
- "NetworkInformationData: non-default IPv6 not supporting - "
- + "ignoring");
+ if (tlve.length != 8) { // 8 bytes in IPv6 address
+ Log.e(TAG, "NetworkInformationData: invalid IPv6 TLV -- length: "
+ + tlve.length);
+ return null;
+ }
+ ipv6Override = tlve.getRawData();
break;
case SERVICE_INFO_TYPE:
Pair<Integer, Integer> serviceInfo = parseServiceInfoTlv(
tlve.getRawData());
- if (serviceInfo != null) {
- port = serviceInfo.first;
- transportProtocol = serviceInfo.second;
+ if (serviceInfo == null) {
+ return null;
}
+ port = serviceInfo.first;
+ transportProtocol = serviceInfo.second;
break;
default:
Log.w(TAG,
@@ -1514,12 +1569,14 @@
Log.e(TAG, "NetworkInformationData: error parsing TLV -- " + e);
return null;
}
- if (port == 0 && transportProtocol == -1) {
- return null;
- }
- return Pair.create(port, transportProtocol);
+ return new ParsedResults(port, transportProtocol, ipv6Override);
}
+ /**
+ * Parse the Service Info TLV:
+ * - Returns null on error
+ * - Returns <port | 0, transport-protocol | -1> otherwise
+ */
private static Pair<Integer, Integer> parseServiceInfoTlv(byte[] tlv) {
int port = 0;
int transportProtocol = -1;
diff --git a/service/java/com/android/server/wifi/util/DataIntegrityChecker.java b/service/java/com/android/server/wifi/util/DataIntegrityChecker.java
index feda70d..b005529 100644
--- a/service/java/com/android/server/wifi/util/DataIntegrityChecker.java
+++ b/service/java/com/android/server/wifi/util/DataIntegrityChecker.java
@@ -150,14 +150,11 @@
EncryptedData encryptedData = null;
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
- SecretKey secretKeyReference;
- if (inKeyStore(keyAlias)) {
- secretKeyReference = getSecretKey(keyAlias);
- } else {
- secretKeyReference = createSecretKey(keyAlias);
+ SecretKey secretKeyReference = getOrCreateSecretKey(keyAlias);
+ if (secretKeyReference != null) {
+ cipher.init(Cipher.ENCRYPT_MODE, secretKeyReference);
+ encryptedData = new EncryptedData(cipher.doFinal(data), cipher.getIV(), keyAlias);
}
- cipher.init(Cipher.ENCRYPT_MODE, secretKeyReference);
- encryptedData = new EncryptedData(cipher.doFinal(data), cipher.getIV(), keyAlias);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "encrypt could not find the algorithm: " + CIPHER_ALGORITHM);
} catch (NoSuchPaddingException e) {
@@ -177,8 +174,11 @@
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, encryptedData.getIv());
- cipher.init(Cipher.DECRYPT_MODE, getSecretKey(encryptedData.getKeyAlias()), spec);
- decryptedData = cipher.doFinal(encryptedData.getEncryptedData());
+ SecretKey secretKeyReference = getOrCreateSecretKey(encryptedData.getKeyAlias());
+ if (secretKeyReference != null) {
+ cipher.init(Cipher.DECRYPT_MODE, secretKeyReference, spec);
+ decryptedData = cipher.doFinal(encryptedData.getEncryptedData());
+ }
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "decrypt could not find cipher algorithm " + CIPHER_ALGORITHM);
} catch (NoSuchPaddingException e) {
@@ -195,70 +195,48 @@
return decryptedData;
}
- private static SecretKey createSecretKey(String keyAlias) {
- SecretKey secretKey = null;
- try {
- KeyGenerator keyGenerator = KeyGenerator
- .getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE);
-
- KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(keyAlias,
- KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
- .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
- .build();
-
- keyGenerator.init(keyGenParameterSpec);
- secretKey = keyGenerator.generateKey();
- } catch (NoSuchAlgorithmException e) {
- Log.e(TAG, "createSecretKey cannot find algorithm");
- } catch (NoSuchProviderException e) {
- Log.e(TAG, "createSecretKey cannot find crypto provider");
- } catch (InvalidAlgorithmParameterException e) {
- Log.e(TAG, "createSecretKey had an invalid algorithm parameter");
- }
- return secretKey;
- }
-
- private static SecretKey getSecretKey(String keyAlias) {
+ private static SecretKey getOrCreateSecretKey(String keyAlias) {
SecretKey secretKey = null;
try {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE);
keyStore.load(null);
- KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
- .getEntry(keyAlias, null);
- secretKey = secretKeyEntry.getSecretKey();
+ if (keyStore.containsAlias(keyAlias)) { // The key exists in key store. Get the key.
+ KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
+ .getEntry(keyAlias, null);
+ if (secretKeyEntry != null) {
+ secretKey = secretKeyEntry.getSecretKey();
+ }
+ } else { // The key does not exist in key store. Create the key and store it.
+ KeyGenerator keyGenerator = KeyGenerator
+ .getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE);
+
+ KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(keyAlias,
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build();
+
+ keyGenerator.init(keyGenParameterSpec);
+ secretKey = keyGenerator.generateKey();
+ }
+ } catch (CertificateException e) {
+ Log.e(TAG, "getOrCreateSecretKey had a certificate exception.");
+ } catch (InvalidAlgorithmParameterException e) {
+ Log.e(TAG, "getOrCreateSecretKey had an invalid algorithm parameter");
} catch (IOException e) {
- Log.e(TAG, "getSecretKey had an IO exception");
- } catch (NoSuchAlgorithmException e) {
- Log.e(TAG, "getSecretKey could not find the algorithm");
- } catch (CertificateException e) {
- Log.e(TAG, "getSecretKey had a certificate exception");
+ Log.e(TAG, "getOrCreateSecretKey had an IO exception.");
} catch (KeyStoreException e) {
- Log.e(TAG, "getSecretKey had a key store exception");
+ Log.e(TAG, "getOrCreateSecretKey cannot find the keystore: " + KEY_STORE);
+ } catch (NoSuchAlgorithmException e) {
+ Log.e(TAG, "getOrCreateSecretKey cannot find algorithm");
+ } catch (NoSuchProviderException e) {
+ Log.e(TAG, "getOrCreateSecretKey cannot find crypto provider");
} catch (UnrecoverableEntryException e) {
- Log.e(TAG, "getSecretKey had an entry exception");
+ Log.e(TAG, "getOrCreateSecretKey had an unrecoverable entry exception.");
}
return secretKey;
}
- private static boolean inKeyStore(String keyAlias) {
- boolean ret = false;
- try {
- KeyStore ks = KeyStore.getInstance(KEY_STORE);
- ks.load(null);
- ret = ks.containsAlias(keyAlias);
- } catch (KeyStoreException e) {
- Log.e(TAG, "inKeyStore cannot find the keystore: " + KEY_STORE);
- } catch (IOException e) {
- Log.e(TAG, "inKeyStore had an IO exception.");
- } catch (NoSuchAlgorithmException e) {
- Log.e(TAG, "inKeyStore cannot find algorithm.");
- } catch (CertificateException e) {
- Log.e(TAG, "inKeyStore had a certificate exception.");
- }
- return ret;
- }
-
private static void writeIntegrityData(EncryptedData encryptedData, File file) {
try {
FileOutputStream fos = new FileOutputStream(file);
diff --git a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java
index 01c67e9..702aa99 100644
--- a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java
@@ -27,15 +27,16 @@
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
/**
* Unit tests for {@link com.android.server.wifi.DeletedEphemeralSsidsStoreData}.
@@ -44,18 +45,27 @@
public class DeletedEphemeralSsidsStoreDataTest {
private static final String TEST_SSID1 = "SSID 1";
private static final String TEST_SSID2 = "SSID 2";
- private static final String TEST_SSID_LIST_XML_STRING =
+ private static final long TEST_SSID1_TSTAMP = 6837367L;
+ private static final long TEST_SSID2_TSTAMP = 4567367L;
+
+ private static final String TEST_SSID_LIST_XML_STRING_MAP =
+ "<map name=\"SSIDList\">\n"
+ + "<long name=\"" + TEST_SSID1 + "\" value=\"" + TEST_SSID1_TSTAMP + "\" />\n"
+ + "<long name=\"" + TEST_SSID2 + "\" value=\"" + TEST_SSID2_TSTAMP + "\" />\n"
+ + "</map>\n";
+ private static final String TEST_SSID_LIST_XML_STRING_SET =
"<set name=\"SSIDList\">\n"
+ "<string>" + TEST_SSID1 + "</string>\n"
+ "<string>" + TEST_SSID2 + "</string>\n"
+ "</set>\n";
- private static final byte[] TEST_SSID_LIST_XML_BYTES =
- TEST_SSID_LIST_XML_STRING.getBytes(StandardCharsets.UTF_8);
+ @Mock Clock mClock;
private DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData;
@Before
public void setUp() throws Exception {
- mDeletedEphemeralSsidsStoreData = new DeletedEphemeralSsidsStoreData();
+ MockitoAnnotations.initMocks(this);
+
+ mDeletedEphemeralSsidsStoreData = new DeletedEphemeralSsidsStoreData(mClock);
}
/**
@@ -80,12 +90,12 @@
* @return SSID list
* @throws Exception
*/
- private Set<String> deserializeData(byte[] data) throws Exception {
+ private Map<String, Long> deserializeData(byte[] data) throws Exception {
final XmlPullParser in = Xml.newPullParser();
final ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
in.setInput(inputStream, StandardCharsets.UTF_8.name());
mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth());
- return mDeletedEphemeralSsidsStoreData.getSsidList();
+ return mDeletedEphemeralSsidsStoreData.getSsidToTimeMap();
}
/**
@@ -129,13 +139,13 @@
* @throws Exception
*/
@Test
- public void serializeSsidList() throws Exception {
- Set<String> ssidList = new HashSet<>();
- ssidList.add(TEST_SSID1);
- ssidList.add(TEST_SSID2);
- mDeletedEphemeralSsidsStoreData.setSsidList(ssidList);
+ public void serializeSsidToTimeMap() throws Exception {
+ Map<String, Long> ssidToTimeMap = new HashMap<>();
+ ssidToTimeMap.put(TEST_SSID1, TEST_SSID1_TSTAMP);
+ ssidToTimeMap.put(TEST_SSID2, TEST_SSID2_TSTAMP);
+ mDeletedEphemeralSsidsStoreData.setSsidToTimeMap(ssidToTimeMap);
byte[] actualData = serializeData();
- assertTrue(Arrays.equals(TEST_SSID_LIST_XML_BYTES, actualData));
+ assertEquals(TEST_SSID_LIST_XML_STRING_MAP, new String(actualData));
}
/**
@@ -145,10 +155,28 @@
* @throws Exception
*/
@Test
- public void deserializeSsidList() throws Exception {
- Set<String> ssidList = new HashSet<>();
- ssidList.add(TEST_SSID1);
- ssidList.add(TEST_SSID2);
- assertEquals(ssidList, deserializeData(TEST_SSID_LIST_XML_BYTES));
+ public void deserializeSsidToTimeMap() throws Exception {
+ Map<String, Long> ssidToTimeMap = new HashMap<>();
+ ssidToTimeMap.put(TEST_SSID1, TEST_SSID1_TSTAMP);
+ ssidToTimeMap.put(TEST_SSID2, TEST_SSID2_TSTAMP);
+ assertEquals(ssidToTimeMap, deserializeData(TEST_SSID_LIST_XML_STRING_MAP.getBytes()));
+ }
+
+ /**
+ * Verify that user store SSID list is deserialized correctly using the predefined test XML
+ * data.
+ * This simulates the config store migration from the previous set representation to the new
+ * map of ssid to timestamp representation.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void deserializeSsidToTimeMapFromSet() throws Exception {
+ long currentTimeMs = 67934838L;
+ when(mClock.getWallClockMillis()).thenReturn(currentTimeMs);
+ Map<String, Long> ssidToTimeMap = new HashMap<>();
+ ssidToTimeMap.put(TEST_SSID1, currentTimeMs);
+ ssidToTimeMap.put(TEST_SSID2, currentTimeMs);
+ assertEquals(ssidToTimeMap, deserializeData(TEST_SSID_LIST_XML_STRING_SET.getBytes()));
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
index aec4ca6..23edbd7 100644
--- a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
@@ -231,6 +231,21 @@
}
/**
+ * Test a change in earpiece status, shouldReport should return true
+ * Note: will need to report once before making the change to remove
+ * the effect of sensor state change.
+ */
+ @Test
+ public void testSarInfo_earpiece_wifi_enabled() throws Exception {
+ mSarInfo.isWifiClientEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.isEarPieceActive = true;
+ assertTrue(mSarInfo.shouldReport());
+ }
+
+ /**
* Test starting SAP, shouldReport should return true
* Note: will need to report once before starting SAP to remove
* the effect of sensor state change.
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index ce2fe4b..4ff61e2 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -79,6 +79,7 @@
@SmallTest
public class WifiConfigManagerTest {
+ private static final String TEST_SSID = "\"test_ssid\"";
private static final String TEST_BSSID = "0a:08:5c:67:89:00";
private static final long TEST_WALLCLOCK_CREATION_TIME_MILLIS = 9845637;
private static final long TEST_WALLCLOCK_UPDATE_TIME_MILLIS = 75455637;
@@ -192,8 +193,7 @@
.thenReturn(true);
when(mWifiConfigStore.areStoresPresent()).thenReturn(true);
- setupStoreDataForRead(new ArrayList<WifiConfiguration>(),
- new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForRead(new ArrayList<>(), new ArrayList<>(), new HashMap<>());
when(mDevicePolicyManagerInternal.isActiveAdminWithPolicy(anyInt(), anyInt()))
.thenReturn(false);
@@ -348,8 +348,7 @@
sharedConfigList.add(openNetwork);
// Setup xml storage
- setupStoreDataForRead(sharedConfigList, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
+ setupStoreDataForRead(sharedConfigList, new ArrayList<>(), new HashMap<>());
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
@@ -2665,6 +2664,8 @@
setupUserProfiles(user2);
int appId = 674;
+ long currentTimeMs = 67823;
+ when(mClock.getWallClockMillis()).thenReturn(currentTimeMs);
// Create 3 networks. 1 for user1, 1 for user2 and 1 shared.
final WifiConfiguration user1Network = WifiConfigurationTestUtil.createPskNetwork();
@@ -2688,7 +2689,13 @@
add(user1Network);
}
};
- setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>());
+ Map<String, Long> deletedSsidsToTimeMap = new HashMap<String, Long>() {
+ {
+ put(TEST_SSID, currentTimeMs);
+ }
+
+ };
+ setupStoreDataForRead(sharedNetworks, user1Networks, deletedSsidsToTimeMap);
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
@@ -2706,6 +2713,7 @@
}
assertTrue(sharedNetwork1Id != WifiConfiguration.INVALID_NETWORK_ID);
assertTrue(sharedNetwork2Id != WifiConfiguration.INVALID_NETWORK_ID);
+ assertTrue(mWifiConfigManager.wasEphemeralNetworkDeleted(TEST_SSID));
// Set up the user 2 store data that is loaded at user switch.
List<WifiConfiguration> user2Networks = new ArrayList<WifiConfiguration>() {
@@ -2713,7 +2721,7 @@
add(user2Network);
}
};
- setupStoreDataForUserRead(user2Networks, new HashSet<String>());
+ setupStoreDataForUserRead(user2Networks, new HashMap<>());
// Now switch the user to user 2 and ensure that shared network's IDs have not changed.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -2733,6 +2741,7 @@
}
assertEquals(sharedNetwork1Id, updatedSharedNetwork1Id);
assertEquals(sharedNetwork2Id, updatedSharedNetwork2Id);
+ assertFalse(mWifiConfigManager.wasEphemeralNetworkDeleted(TEST_SSID));
}
/**
@@ -2770,7 +2779,7 @@
add(user1Network);
}
};
- setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>());
+ setupStoreDataForRead(sharedNetworks, user1Networks, new HashMap<>());
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
@@ -2790,7 +2799,7 @@
add(user2Network);
}
};
- setupStoreDataForUserRead(user2Networks, new HashSet<String>());
+ setupStoreDataForUserRead(user2Networks, new HashMap<>());
// Now switch the user to user 2 and ensure that user 1's private network has been removed.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
@@ -2841,8 +2850,7 @@
add(sharedNetwork);
}
};
- setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
+ setupStoreDataForRead(sharedNetworks, new ArrayList<>(), new HashMap<>());
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
@@ -2852,7 +2860,7 @@
add(user2Network);
}
};
- setupStoreDataForUserRead(user2Networks, new HashSet<String>());
+ setupStoreDataForUserRead(user2Networks, new HashMap<>());
// Now switch the user to user 2 and ensure that no private network has been removed.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
@@ -2894,8 +2902,7 @@
add(user2Network);
}
};
- setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
+ setupStoreDataForRead(sharedNetworks, new ArrayList<>(), new HashMap<>());
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
@@ -2905,7 +2912,7 @@
add(user1Network);
}
};
- setupStoreDataForUserRead(userNetworks, new HashSet<String>());
+ setupStoreDataForUserRead(userNetworks, new HashMap<>());
mWifiConfigManager.handleUserUnlock(user1);
verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
// Capture the written data for the user 1 and ensure that it corresponds to what was
@@ -2976,15 +2983,14 @@
add(passpointConfig);
}
};
- setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
+ setupStoreDataForRead(sharedNetworks, new ArrayList<>(), new HashMap<>());
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
assertEquals(1, mWifiConfigManager.getConfiguredNetworks().size());
// Unlock the owner of the legacy Passpoint configuration, verify it is removed from
// the configured networks (migrated to PasspointManager).
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashMap<>());
mWifiConfigManager.handleUserUnlock(user1);
verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
Pair<List<WifiConfiguration>, List<WifiConfiguration>> writtenNetworkList =
@@ -3008,7 +3014,7 @@
// Set up the internal data first.
assertTrue(mWifiConfigManager.loadFromStore());
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
// user2 is unlocked and switched to foreground.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -3044,7 +3050,7 @@
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoresAndRead(any(List.class));
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
// Unlock the user2 and ensure that we read the data now.
mWifiConfigManager.handleUserUnlock(user2);
mContextConfigStoreMockOrder.verify(mWifiConfigStore)
@@ -3106,7 +3112,7 @@
add(user1Network);
}
};
- setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>());
+ setupStoreDataForRead(sharedNetworks, user1Networks, new HashMap<>());
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
@@ -3135,7 +3141,7 @@
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoresAndRead(any(List.class));
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
// Unlock the user1 (default user) for the first time and ensure that we read the data.
mWifiConfigManager.handleUserUnlock(user1);
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
@@ -3161,7 +3167,7 @@
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoresAndRead(any(List.class));
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashMap<>());
// Read from store now.
assertTrue(mWifiConfigManager.loadFromStore());
mContextConfigStoreMockOrder.verify(mWifiConfigStore)
@@ -3193,7 +3199,7 @@
mContextConfigStoreMockOrder.verify(mWifiConfigStore).read();
// Unlock the user2 and ensure that we read from the user store.
- setupStoreDataForUserRead(new ArrayList<>(), new HashSet<>());
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
mWifiConfigManager.handleUserUnlock(user2);
mContextConfigStoreMockOrder.verify(mWifiConfigStore)
.switchUserStoresAndRead(any(List.class));
@@ -3212,7 +3218,7 @@
// Set up the internal data first.
assertTrue(mWifiConfigManager.loadFromStore());
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
// user2 is unlocked and switched to foreground.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -3314,7 +3320,7 @@
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore).read();
- setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>());
// Now switch the user to user 2.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -4191,8 +4197,7 @@
add(peapSimNetwork);
}
};
- setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
+ setupStoreDataForRead(sharedNetworks, new ArrayList<>(), new HashMap<>());
// 1. Call resetSimNetworks with true(SIM is present).
mWifiConfigManager.resetSimNetworks(true);
@@ -4217,6 +4222,41 @@
assertFalse(retrievedPeapNetwork.enterpriseConfig.getAnonymousIdentity().isEmpty());
}
+ /**
+ * Verifies the deletion of ephemeral network using
+ * {@link WifiConfigManager#disableEphemeralNetwork(String)}.
+ */
+ @Test
+ public void testDisableEphemeralNetwork() throws Exception {
+ WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ ephemeralNetwork.ephemeral = true;
+ List<WifiConfiguration> networks = new ArrayList<>();
+ networks.add(ephemeralNetwork);
+
+ verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork);
+
+ List<WifiConfiguration> retrievedNetworks =
+ mWifiConfigManager.getConfiguredNetworksWithPasswords();
+ WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
+ networks, retrievedNetworks);
+
+ // Disable the ephemeral network.
+ long disableTimeMs = 546643L;
+ long currentTimeMs = disableTimeMs;
+ when(mClock.getWallClockMillis()).thenReturn(currentTimeMs);
+ mWifiConfigManager.disableEphemeralNetwork(ephemeralNetwork.SSID);
+
+ // Before the expiry of timeout.
+ currentTimeMs = disableTimeMs + WifiConfigManager.DELETED_EPHEMERAL_SSID_EXPIRY_MS - 1;
+ when(mClock.getWallClockMillis()).thenReturn(currentTimeMs);
+ assertTrue(mWifiConfigManager.wasEphemeralNetworkDeleted(ephemeralNetwork.SSID));
+
+ // After the expiry of timeout.
+ currentTimeMs = disableTimeMs + WifiConfigManager.DELETED_EPHEMERAL_SSID_EXPIRY_MS + 1;
+ when(mClock.getWallClockMillis()).thenReturn(currentTimeMs);
+ assertFalse(mWifiConfigManager.wasEphemeralNetworkDeleted(ephemeralNetwork.SSID));
+ }
+
private NetworkUpdateResult verifyAddOrUpdateNetworkWithProxySettingsAndPermissions(
boolean withNetworkSettings,
boolean withProfileOwnerPolicy,
@@ -4452,11 +4492,11 @@
* after WifiConfigStore#read.
*/
private void setupStoreDataForRead(List<WifiConfiguration> sharedConfigurations,
- List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSsids) {
+ List<WifiConfiguration> userConfigurations, Map<String, Long> deletedEphemeralSsids) {
when(mNetworkListSharedStoreData.getConfigurations())
.thenReturn(sharedConfigurations);
when(mNetworkListUserStoreData.getConfigurations()).thenReturn(userConfigurations);
- when(mDeletedEphemeralSsidsStoreData.getSsidList()).thenReturn(deletedEphemeralSsids);
+ when(mDeletedEphemeralSsidsStoreData.getSsidToTimeMap()).thenReturn(deletedEphemeralSsids);
}
/**
@@ -4464,9 +4504,9 @@
* after WifiConfigStore#switchUserStoresAndRead.
*/
private void setupStoreDataForUserRead(List<WifiConfiguration> userConfigurations,
- Set<String> deletedEphemeralSsids) {
+ Map<String, Long> deletedEphemeralSsids) {
when(mNetworkListUserStoreData.getConfigurations()).thenReturn(userConfigurations);
- when(mDeletedEphemeralSsidsStoreData.getSsidList()).thenReturn(deletedEphemeralSsids);
+ when(mDeletedEphemeralSsidsStoreData.getSsidToTimeMap()).thenReturn(deletedEphemeralSsids);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
index 6693d86..64e762b 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
@@ -46,10 +46,9 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
/**
* Unit tests for {@link com.android.server.wifi.WifiConfigStore}.
@@ -122,9 +121,9 @@
+ "</Network>\n"
+ "</NetworkList>\n"
+ "<DeletedEphemeralSSIDList>\n"
- + "<set name=\"SSIDList\">\n"
- + "<string>%s</string>\n"
- + "</set>\n"
+ + "<map name=\"SSIDList\">\n"
+ + "<long name=\"%s\" value=\"0\" />\n"
+ + "</map>\n"
+ "</DeletedEphemeralSSIDList>\n"
+ "</WifiConfigStoreData>\n";
@@ -147,6 +146,7 @@
private TestAlarmManager mAlarmManager;
private TestLooper mLooper;
@Mock private Clock mClock;
+ @Mock private WifiMetrics mWifiMetrics;
private MockStoreFile mSharedStore;
private MockStoreFile mUserStore;
private MockStoreFile mUserNetworkSuggestionsStore;
@@ -188,7 +188,8 @@
public void setUp() throws Exception {
setupMocks();
- mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mSharedStore);
+ mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mWifiMetrics,
+ mSharedStore);
// Enable verbose logging before tests.
mWifiConfigStore.enableVerboseLogging(true);
}
@@ -216,6 +217,8 @@
assertFalse(mSharedStore.isStoreWritten());
assertFalse(mUserStore.isStoreWritten());
assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());
+
+ verify(mWifiMetrics, never()).noteWifiConfigStoreWriteDuration(anyInt());
}
/**
@@ -236,6 +239,8 @@
assertTrue(mSharedStore.isStoreWritten());
assertTrue(mUserStore.isStoreWritten());
assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());
+
+ verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
}
/**
@@ -262,6 +267,8 @@
assertTrue(mSharedStore.isStoreWritten());
assertTrue(mUserStore.isStoreWritten());
assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());
+
+ verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
}
/**
@@ -366,6 +373,9 @@
mWifiConfigStore.read();
assertEquals(TEST_USER_DATA, mUserStoreData.getData());
assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData());
+
+ verify(mWifiMetrics, times(2)).noteWifiConfigStoreReadDuration(anyInt());
+ verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
}
/**
@@ -494,25 +504,25 @@
// Setup deleted ephemeral SSID list.
DeletedEphemeralSsidsStoreData deletedEphemeralSsids =
- new DeletedEphemeralSsidsStoreData();
+ new DeletedEphemeralSsidsStoreData(mClock);
mWifiConfigStore.registerStoreData(deletedEphemeralSsids);
- String testSsid = "Test SSID";
- Set<String> ssidList = new HashSet<>();
- ssidList.add(testSsid);
+ String testSsid = "\"Test SSID\"";
+ Map<String, Long> ssidMap = new HashMap<>();
+ ssidMap.put(testSsid, 0L);
// Setup user store XML bytes.
String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
openNetwork.configKey().replaceAll("\"", """),
openNetwork.SSID.replaceAll("\"", """),
openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName,
- openNetwork.getRandomizedMacAddress(), testSsid);
+ openNetwork.getRandomizedMacAddress(), testSsid.replaceAll("\"", """));
byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
mUserStore.storeRawDataToWrite(xmlBytes);
mWifiConfigStore.switchUserStoresAndRead(mUserStores);
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
userConfigs, networkList.getConfigurations());
- assertEquals(ssidList, deletedEphemeralSsids.getSsidList());
+ assertEquals(ssidMap, deletedEphemeralSsids.getSsidToTimeMap());
}
/**
@@ -540,25 +550,23 @@
// Setup deleted ephemeral SSID list store data.
DeletedEphemeralSsidsStoreData deletedEphemeralSsids =
- new DeletedEphemeralSsidsStoreData();
+ new DeletedEphemeralSsidsStoreData(mClock);
mWifiConfigStore.registerStoreData(deletedEphemeralSsids);
String testSsid = "Test SSID";
- Set<String> ssidList = new HashSet<>();
- ssidList.add(testSsid);
- deletedEphemeralSsids.setSsidList(ssidList);
+ Map<String, Long> ssidMap = new HashMap<>();
+ ssidMap.put(testSsid, 0L);
+ deletedEphemeralSsids.setSsidToTimeMap(ssidMap);
// Setup expected XML bytes.
String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
openNetwork.configKey().replaceAll("\"", """),
openNetwork.SSID.replaceAll("\"", """),
openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName,
- openNetwork.getRandomizedMacAddress(), testSsid);
- byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
+ openNetwork.getRandomizedMacAddress(), testSsid.replaceAll("\"", """));
mWifiConfigStore.write(true);
- assertEquals(xmlBytes.length, mUserStore.getStoreBytes().length);
// Verify the user store content.
- assertTrue(Arrays.equals(xmlBytes, mUserStore.getStoreBytes()));
+ assertEquals(xmlString, new String(mUserStore.getStoreBytes()));
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
index aeaba18..c114aa1 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
@@ -645,6 +645,8 @@
assertCommonConfigurationElementsEqual(expected, actual);
assertEquals(expected.networkId, actual.networkId);
assertEquals(expected.ephemeral, actual.ephemeral);
+ assertEquals(expected.fromWifiNetworkSuggestion, actual.fromWifiNetworkSuggestion);
+ assertEquals(expected.fromWifiNetworkSpecifier, actual.fromWifiNetworkSpecifier);
assertEquals(expected.trusted, actual.trusted);
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 570f821..c40e148 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -3048,4 +3048,77 @@
assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, statsList[1].triggerType);
}
+
+ /**
+ * Test the generation of 'WifiConfigStoreIODuration' read histograms.
+ */
+ @Test
+ public void testWifiConfigStoreReadDurationsHistogramGeneration() throws Exception {
+ mWifiMetrics.noteWifiConfigStoreReadDuration(10);
+ mWifiMetrics.noteWifiConfigStoreReadDuration(20);
+ mWifiMetrics.noteWifiConfigStoreReadDuration(100);
+ mWifiMetrics.noteWifiConfigStoreReadDuration(90);
+ mWifiMetrics.noteWifiConfigStoreReadDuration(130);
+ mWifiMetrics.noteWifiConfigStoreReadDuration(250);
+ mWifiMetrics.noteWifiConfigStoreReadDuration(600);
+
+ dumpProtoAndDeserialize();
+
+ assertEquals(5, mDecodedProto.wifiConfigStoreIo.readDurations.length);
+ assertEquals(0, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
+
+ assertEquals(Integer.MIN_VALUE,
+ mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeStartMs);
+ assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeEndMs);
+ assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[0].count);
+
+ assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeStartMs);
+ assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeEndMs);
+ assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[1].count);
+
+ assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeStartMs);
+ assertEquals(150, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeEndMs);
+ assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[2].count);
+
+ assertEquals(200, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeStartMs);
+ assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeEndMs);
+ assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[3].count);
+
+ assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeStartMs);
+ assertEquals(Integer.MAX_VALUE,
+ mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeEndMs);
+ assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[4].count);
+ }
+
+ /**
+ * Test the generation of 'WifiConfigStoreIODuration' write histograms.
+ */
+ @Test
+ public void testWifiConfigStoreWriteDurationsHistogramGeneration() throws Exception {
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(10);
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(40);
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(60);
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(90);
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(534);
+ mWifiMetrics.noteWifiConfigStoreWriteDuration(345);
+
+ dumpProtoAndDeserialize();
+
+ assertEquals(0, mDecodedProto.wifiConfigStoreIo.readDurations.length);
+ assertEquals(3, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
+
+ assertEquals(Integer.MIN_VALUE,
+ mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeStartMs);
+ assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeEndMs);
+ assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[0].count);
+
+ assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeStartMs);
+ assertEquals(100, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeEndMs);
+ assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[1].count);
+
+ assertEquals(300, mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeStartMs);
+ assertEquals(Integer.MAX_VALUE,
+ mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeEndMs);
+ assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[2].count);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
index a745ca1..975b430 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
@@ -69,6 +69,7 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -101,6 +102,7 @@
private static final String TEST_BSSID_4 = "45:34:34:56:ee:ff";
private static final String TEST_BSSID_1_2_OUI = "12:34:23:00:00:00";
private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
+ private static final String TEST_WPA_PRESHARED_KEY = "\"password123\"";
@Mock Context mContext;
@Mock ActivityManager mActivityManager;
@@ -971,8 +973,9 @@
assertNotNull(networkRequestUserSelectionCallback);
// Now trigger user selection to one of the network.
- WifiConfiguration selectedNetwork = WifiConfigurationTestUtil.createOpenNetwork();
- networkRequestUserSelectionCallback.select(selectedNetwork);
+ mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork();
+ mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\"";
+ networkRequestUserSelectionCallback.select(mSelectedNetwork);
mLooper.dispatchAll();
// Cancel periodic scans.
@@ -986,9 +989,14 @@
wifiConfigurationCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_NAME_1));
WifiConfiguration network = wifiConfigurationCaptor.getValue();
assertNotNull(network);
- WifiConfigurationTestUtil.assertConfigurationEqual(selectedNetwork, network);
- assertTrue(network.ephemeral);
- assertTrue(network.fromWifiNetworkSpecifier);
+ 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);
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mClientModeImpl).sendMessage(messageCaptor.capture());
@@ -1012,16 +1020,17 @@
mNetworkRequestUserSelectionCallback.getValue();
assertNotNull(networkRequestUserSelectionCallback);
- WifiConfiguration selectedNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork();
+ mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\"";
// Have a saved network with the same configuration.
- WifiConfiguration matchingSavedNetwork = new WifiConfiguration(selectedNetwork);
+ WifiConfiguration matchingSavedNetwork = new WifiConfiguration(mSelectedNetwork);
matchingSavedNetwork.networkId = TEST_NETWORK_ID_1;
- when(mWifiConfigManager.getConfiguredNetwork(selectedNetwork.configKey()))
+ when(mWifiConfigManager.getConfiguredNetwork(mSelectedNetwork.configKey()))
.thenReturn(matchingSavedNetwork);
// Now trigger user selection to one of the network.
- networkRequestUserSelectionCallback.select(selectedNetwork);
+ networkRequestUserSelectionCallback.select(mSelectedNetwork);
mLooper.dispatchAll();
// Cancel periodic scans.
@@ -1062,6 +1071,7 @@
MacAddress.BROADCAST_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);
@@ -1075,6 +1085,7 @@
// Now trigger user selection to the network.
mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult);
+ mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\"";
INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback =
mNetworkRequestUserSelectionCallback.getValue();
assertNotNull(networkRequestUserSelectionCallback);
@@ -1088,11 +1099,15 @@
wifiConfigurationCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_NAME_1));
WifiConfiguration network = wifiConfigurationCaptor.getValue();
assertNotNull(network);
- WifiConfiguration expectedWifiConfiguration = new WifiConfiguration(mSelectedNetwork);
+ 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);
- assertTrue(network.ephemeral);
- assertTrue(network.fromWifiNetworkSpecifier);
// Verify connection message.
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
@@ -1149,7 +1164,8 @@
// Fail the request after all the retries are exhausted.
verify(mNetworkRequestMatchCallback).onAbort();
// Verify that we sent the connection failure callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// Verify we reset the network request handling.
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
}
@@ -1176,7 +1192,8 @@
// Fail the request after all the retries are exhausted.
verify(mNetworkRequestMatchCallback).onAbort();
// Verify that we sent the connection failure callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// verify we canceled the timeout alarm.
mInOrder.verify(mAlarmManager).cancel(
mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
@@ -1207,7 +1224,8 @@
verify(mNetworkRequestMatchCallback).onAbort();
// Verify that we sent the connection failure callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// verify we canceled the timeout alarm.
mInOrder.verify(mAlarmManager).cancel(
mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
@@ -1230,8 +1248,7 @@
WifiMetrics.ConnectionEvent.FAILURE_DHCP, connectedNetwork);
// Verify that we did not send the connection failure callback.
- verify(mNetworkRequestMatchCallback, never())
- .onUserSelectionConnectFailure(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback, never()).onUserSelectionConnectFailure(any());
// verify we canceled the timeout alarm.
verify(mAlarmManager, never())
.cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
@@ -1251,7 +1268,8 @@
validateConnectionRetryAttempts();
// Verify that we sent the connection failure callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// verify we canceled the timeout alarm.
mInOrder.verify(mAlarmManager).cancel(
mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
@@ -1272,7 +1290,8 @@
WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork);
// Verify that we sent the connection success callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// verify we canceled the timeout alarm.
verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
}
@@ -1292,8 +1311,7 @@
WifiMetrics.ConnectionEvent.FAILURE_NONE, connectedNetwork);
// verify that we did not send out the success callback and did not stop the alarm timeout.
- verify(mNetworkRequestMatchCallback, never())
- .onUserSelectionConnectSuccess(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback, never()).onUserSelectionConnectSuccess(any());
verify(mAlarmManager, never())
.cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
@@ -1302,7 +1320,8 @@
WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork);
// Verify that we sent the connection success callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// verify we canceled the timeout alarm.
verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
}
@@ -1320,7 +1339,8 @@
WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork);
// Verify that we sent the connection success callback.
- verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(mSelectedNetwork);
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
+ argThat(new WifiConfigMatcher(mSelectedNetwork)));
// verify we canceled the timeout alarm.
verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
@@ -2163,6 +2183,7 @@
Pair<MacAddress, MacAddress> bssidPatternMatch =
Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createPskNetwork();
+ wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
WifiNetworkSpecifier specifier = new WifiNetworkSpecifier(
ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1,
TEST_PACKAGE_NAME_1);
@@ -2336,6 +2357,20 @@
WorkSource workSource = mWorkSourceArgumentCaptor.getValue();
assertNotNull(workSource);
assertEquals(TEST_UID_1, workSource.get(0));
+ }
+ class WifiConfigMatcher implements ArgumentMatcher<WifiConfiguration> {
+ private final WifiConfiguration mConfig;
+
+ WifiConfigMatcher(WifiConfiguration config) {
+ assertNotNull(config);
+ mConfig = config;
+ }
+
+ @Override
+ public boolean matches(WifiConfiguration otherConfig) {
+ if (otherConfig == null) return false;
+ return mConfig.configKey().equals(otherConfig.configKey());
+ }
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
index c2c8f7b..d05d797 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
@@ -2576,6 +2576,35 @@
}
/**
+ * Test the selectTxPowerScenario HIDL method invocation with no sensor support, but with
+ * SAP and voice call support.
+ * When earpiece is active, should result in cell with near head scenario
+ * Using IWifiChip 1.2 interface
+ */
+ @Test
+ public void testEarPieceScenarios_SelectTxPowerV1_2() throws RemoteException {
+ // Create a SAR info record (with sensor and SAP support)
+ SarInfo sarInfo = new SarInfo();
+ sarInfo.sarVoiceCallSupported = true;
+ sarInfo.sarSapSupported = true;
+ sarInfo.sarSensorSupported = false;
+
+ sarInfo.isEarPieceActive = true;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ // ON_HEAD_CELL_ON
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON));
+ verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
* Test the selectTxPowerScenario HIDL method invocation with sensor related scenarios
* to IWifiChip 1.2 interface
*/
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 c923633..069e865 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
@@ -74,7 +74,6 @@
import android.os.PowerManager;
import android.os.Process;
import android.os.test.TestLooper;
-import android.util.Pair;
import androidx.test.filters.SmallTest;
@@ -854,8 +853,13 @@
*/
@Test
public void testDataPathInitiatorNetInfoLargeValuesExp1() throws Exception {
- testDataPathInitiatorUtilityMore(false, true, true, false, true, false,
- buildTlv((1 << 16) - 1, (1 << 8) - 1, true), (1 << 16) - 1, (1 << 8) - 1);
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ String linkLocalIpv6Address = MacAddress.fromBytes(
+ peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
+
+ testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
+ buildTlv((1 << 16) - 1, (1 << 8) - 1, true), (1 << 16) - 1, (1 << 8) - 1,
+ linkLocalIpv6Address);
}
/**
@@ -863,8 +867,12 @@
*/
@Test
public void testDataPathInitiatorNetInfoLargeValuesExp2() throws Exception {
- testDataPathInitiatorUtilityMore(false, true, true, false, true, false,
- buildTlv(1 << 15, 1 << 7, true), 1 << 15, 1 << 7);
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ String linkLocalIpv6Address = MacAddress.fromBytes(
+ peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
+
+ testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
+ buildTlv(1 << 15, 1 << 7, true), 1 << 15, 1 << 7, linkLocalIpv6Address);
}
/**
@@ -872,8 +880,27 @@
*/
@Test
public void testDataPathInitiatorNetInfoLargeValuesExp3() throws Exception {
- testDataPathInitiatorUtilityMore(false, true, true, false, true, false,
- buildTlv((1 << 15) - 1, (1 << 7) - 1, true), (1 << 15) - 1, (1 << 7) - 1);
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ String linkLocalIpv6Address = MacAddress.fromBytes(
+ peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
+
+ testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
+ buildTlv((1 << 15) - 1, (1 << 7) - 1, true), (1 << 15) - 1, (1 << 7) - 1,
+ linkLocalIpv6Address);
+ }
+
+ /**
+ * Verify that an TLV configuration with an IPv6 override works correctly.
+ */
+ @Test
+ public void testDataPathInitiatorNetInfoIpv6Override() throws Exception {
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ final byte[] testVector =
+ new byte[]{0x00, 0x08, 0x00, 0x00, (byte) 0xb3, (byte) 0xe1, (byte) 0xff,
+ (byte) 0xfe, 0x7a, 0x2f, (byte) 0xa2};
+
+ testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac,
+ testVector, 0, -1, "fe80::b3:e1ff:fe7a:2fa2");
}
/**
@@ -1082,10 +1109,10 @@
new byte[]{0x01, 0x0d, 0x00, 0x50, 0x6f, (byte) 0x9a, 0x02, 0x00, 0x02, 0x00, 0x58,
0x1b, 0x01, 0x01, 0x00, 0x06};
- Pair<Integer, Integer> parsed =
+ WifiAwareDataPathStateManager.NetworkInformationData.ParsedResults parsed =
WifiAwareDataPathStateManager.NetworkInformationData.parseTlv(testVector);
- assertEquals(port, (int) parsed.first);
- assertEquals(transportProtocol, (int) parsed.second);
+ assertEquals(port, (int) parsed.port);
+ assertEquals(transportProtocol, (int) parsed.transportProtocol);
}
/*
@@ -1211,13 +1238,19 @@
private void testDataPathInitiatorUtility(boolean useDirect, boolean provideMac,
boolean providePmk, boolean providePassphrase, boolean getConfirmation,
boolean immediateHalFailure) throws Exception {
+ final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
+ String linkLocalIpv6Address = MacAddress.fromBytes(
+ peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress();
+
testDataPathInitiatorUtilityMore(useDirect, provideMac, providePmk, providePassphrase,
- getConfirmation, immediateHalFailure, null, 0, -1);
+ getConfirmation, immediateHalFailure, peerDataPathMac, null, 0, -1,
+ linkLocalIpv6Address);
}
private void testDataPathInitiatorUtilityMore(boolean useDirect, boolean provideMac,
boolean providePmk, boolean providePassphrase, boolean getConfirmation,
- boolean immediateHalFailure, byte[] peerToken, int port, int transportProtocol)
+ boolean immediateHalFailure, byte[] peerDataPathMac, byte[] peerToken, int port,
+ int transportProtocol, String ipv6Address)
throws Exception {
final int clientId = 123;
final byte pubSubId = 58;
@@ -1226,7 +1259,6 @@
final byte[] pmk = "01234567890123456789012345678901".getBytes();
final String passphrase = "some passphrase";
final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
- final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
@@ -1300,9 +1332,7 @@
inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any());
WifiAwareNetworkInfo netInfo =
(WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo();
- assertArrayEquals(MacAddress.fromBytes(
- peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getAddress(),
- netInfo.getPeerIpv6Addr().getAddress());
+ assertEquals(ipv6Address, netInfo.getPeerIpv6Addr().getHostAddress());
assertEquals(port, netInfo.getPort());
assertEquals(transportProtocol, netInfo.getTransportProtocol());
} else {