diff options
27 files changed, 746 insertions, 330 deletions
diff --git a/service/TEST_MAPPING b/service/TEST_MAPPING new file mode 100644 index 0000000000..faa68964c4 --- /dev/null +++ b/service/TEST_MAPPING @@ -0,0 +1,13 @@ +{ + "presubmit": [ + { + "name": "CtsBackupHostTestCases", + "options": [ + { + "include-filter": "android.cts.backup.OtherSoundsSettingsHostSideTest" + } + ] + } + ] +} + diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 292e902bc0..abb3141ca5 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -216,6 +216,8 @@ public class ClientModeImpl extends StateMachine { private final PasspointManager mPasspointManager; private final WifiDataStall mWifiDataStall; private final LinkProbeManager mLinkProbeManager; + @VisibleForTesting + protected static final long AGGRESSIVE_MAC_REFRESH_MS = 10 * 60 * 1000; //10 minutes private final McastLockManagerFilterController mMcastLockManagerFilterController; @@ -765,6 +767,8 @@ public class ClientModeImpl extends StateMachine { private final WrongPasswordNotifier mWrongPasswordNotifier; private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; private boolean mConnectedMacRandomzationSupported; + private MacAddress mAggressiveMac; + private long mLastAggressiveMacUpdateSinceBootInMs = -1; public ClientModeImpl(Context context, FrameworkFacade facade, Looper looper, UserManager userManager, WifiInjector wifiInjector, @@ -906,6 +910,7 @@ public class ClientModeImpl extends StateMachine { setLogRecSize(NUM_LOG_RECS_NORMAL); setLogOnlyTransitions(false); + considerUpdateAggressiveMac(); } @Override @@ -1144,6 +1149,16 @@ public class ClientModeImpl extends StateMachine { return mWifiNative.setScanningMacOui(mInterfaceName, ouiBytes); } + private void considerUpdateAggressiveMac() { + boolean shouldUpdateMac = mLastAggressiveMacUpdateSinceBootInMs == -1 + || mLastAggressiveMacUpdateSinceBootInMs + AGGRESSIVE_MAC_REFRESH_MS + < mClock.getElapsedSinceBootMillis(); + if (shouldUpdateMac) { + mAggressiveMac = MacAddress.createRandomUnicastAddress(); + mLastAggressiveMacUpdateSinceBootInMs = mClock.getElapsedSinceBootMillis(); + } + } + /** * Initiates connection to a network specified by the user/app. This method checks if the * requesting app holds the NETWORK_SETTINGS permission. @@ -3375,9 +3390,10 @@ public class ClientModeImpl extends StateMachine { Log.e(TAG, "No config to change MAC address to"); return; } + considerUpdateAggressiveMac(); MacAddress currentMac = MacAddress.fromString(mWifiNative.getMacAddress(mInterfaceName)); - MacAddress newMac = config.getOrCreateRandomizedMacAddress(); - mWifiConfigManager.setNetworkRandomizedMacAddress(config.networkId, newMac); + MacAddress newMac = mWifiConfigManager.shouldUseAggressiveMode(config) ? mAggressiveMac + : config.getRandomizedMacAddress(); if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) { Log.wtf(TAG, "Config generated an invalid MAC address"); } else if (currentMac.equals(newMac)) { @@ -3514,8 +3530,6 @@ public class ClientModeImpl extends StateMachine { break; case CMD_INITIALIZE: ok = mWifiNative.initialize(); - mPasspointManager.initializeProvisioner( - mWifiInjector.getWifiServiceHandlerThread().getLooper()); replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); break; case CMD_BOOT_COMPLETED: @@ -3525,6 +3539,8 @@ public class ClientModeImpl extends StateMachine { if (!mWifiConfigManager.loadFromStore()) { Log.e(TAG, "Failed to load from config store"); } + mPasspointManager.initializeProvisioner( + mWifiInjector.getWifiServiceHandlerThread().getLooper()); registerNetworkFactory(); break; case CMD_SCREEN_STATE_CHANGED: @@ -4054,7 +4070,8 @@ public class ClientModeImpl extends StateMachine { if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) { mWifiInjector.getWifiLastResortWatchdog() .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), mTargetRoamBSSID, + getTargetSsid(), + (mLastBssid == null) ? mTargetRoamBSSID : mLastBssid, WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); } break; @@ -4420,6 +4437,8 @@ public class ClientModeImpl extends StateMachine { mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( someBssid)); } + // Update last associated BSSID + mLastBssid = someBssid; } handleStatus = NOT_HANDLED; break; @@ -5009,7 +5028,8 @@ public class ClientModeImpl extends StateMachine { handleIPv4Failure(); mWifiInjector.getWifiLastResortWatchdog() .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), mTargetRoamBSSID, + getTargetSsid(), + (mLastBssid == null) ? mTargetRoamBSSID : mLastBssid, WifiLastResortWatchdog.FAILURE_CODE_DHCP); break; } @@ -5039,7 +5059,8 @@ public class ClientModeImpl extends StateMachine { WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); mWifiInjector.getWifiLastResortWatchdog() .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), mTargetRoamBSSID, + getTargetSsid(), + (mLastBssid == null) ? mTargetRoamBSSID : mLastBssid, WifiLastResortWatchdog.FAILURE_CODE_DHCP); transitionTo(mDisconnectingState); break; @@ -5377,6 +5398,12 @@ public class ClientModeImpl extends StateMachine { WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, WifiMetricsProto.ConnectionEvent.HLF_NONE, WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); + mWifiInjector.getWifiLastResortWatchdog() + .noteConnectionFailureAndTriggerIfNeeded( + getTargetSsid(), + (message.obj == null) + ? mTargetRoamBSSID : (String) message.obj, + WifiLastResortWatchdog.FAILURE_CODE_DHCP); handleStatus = NOT_HANDLED; break; case CMD_SET_HIGH_PERF_MODE: diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index b92dab78d3..dfc397cfec 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -48,6 +48,8 @@ import com.android.server.wifi.util.ApConfigUtil; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Locale; /** @@ -93,7 +95,9 @@ public class SoftApManager implements ActiveModeManager { private final SarManager mSarManager; - private long mStartTimestamp = -1; + private String mStartTimestamp; + + private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); /** * Listener for soft AP events. @@ -188,7 +192,7 @@ public class SoftApManager implements ActiveModeManager { pw.println("mApInterfaceName: " + mApInterfaceName); pw.println("mIfaceIsUp: " + mIfaceIsUp); pw.println("mMode: " + mMode); - pw.println("mCountryCode: " + mCountryCode); + pw.println("mSoftApCountryCode: " + mCountryCode); if (mApConfig != null) { pw.println("mApConfig.SSID: " + mApConfig.SSID); pw.println("mApConfig.apBand: " + mApConfig.apBand); @@ -247,6 +251,10 @@ public class SoftApManager implements ActiveModeManager { Log.e(TAG, "Unable to start soft AP without valid configuration"); return ERROR_GENERIC; } + + Log.d(TAG, "band " + config.apBand + " iface " + + mApInterfaceName + " country " + mCountryCode); + // Setup country code if (TextUtils.isEmpty(mCountryCode)) { if (config.apBand == WifiConfiguration.AP_BAND_5GHZ) { @@ -283,12 +291,13 @@ public class SoftApManager implements ActiveModeManager { if (localConfig.hiddenSSID) { Log.d(TAG, "SoftAP is a hidden network"); } + if (!mWifiNative.startSoftAp(mApInterfaceName, localConfig, mSoftApListener)) { Log.e(TAG, "Soft AP start failed"); return ERROR_GENERIC; } - mStartTimestamp = SystemClock.elapsedRealtime(); - Log.d(TAG, "Soft AP is started"); + mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis())); + Log.d(TAG, "Soft AP is started "); return SUCCESS; } diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 8da2d2cb4a..53d35c4b80 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -465,6 +465,17 @@ public class WifiConfigManager { } /** + * Determine if the framework should perform "aggressive" MAC randomization when connecting + * to the SSID in the input WifiConfiguration. + * @param config + * @return + */ + public boolean shouldUseAggressiveMode(WifiConfiguration config) { + // TODO: b/137795359 add logic for classifying network as safe for aggressive mode. + return false; + } + + /** * Enable/disable verbose logging in WifiConfigManager & its helper classes. */ public void enableVerboseLogging(int verbose) { @@ -1890,22 +1901,6 @@ public class WifiConfigManager { } /** - * Set randomized MAC address for the provided network. - * - * @param networkId network ID corresponding to the network. - * @param macAddress Randomized MAC address to be used for network connection. - * @return true if the network was found, false otherwise. - */ - public boolean setNetworkRandomizedMacAddress(int networkId, MacAddress macAddress) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.setRandomizedMacAddress(macAddress); - return true; - } - - /** * Clear the {@link NetworkSelectionStatus#mCandidate}, * {@link NetworkSelectionStatus#mCandidateScore} & * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network. diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 762b24b0a1..f71cd8c67f 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -21,7 +21,6 @@ import android.app.ActivityManager; import android.app.AlarmManager; import android.app.AppOpsManager; import android.content.Context; -import android.content.pm.PackageManager; import android.hardware.SystemSensorManager; import android.net.IpMemoryStore; import android.net.NetworkCapabilities; @@ -152,7 +151,7 @@ public class WifiInjector { private final DppMetrics mDppMetrics; private final DppManager mDppManager; private final LinkProbeManager mLinkProbeManager; - private final IpMemoryStore mIpMemoryStore; + private IpMemoryStore mIpMemoryStore; private final CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector; public WifiInjector(Context context) { @@ -337,14 +336,11 @@ public class WifiInjector { BatteryStatsService.getService()); mDppManager = new DppManager(mWifiCoreHandlerThread.getLooper(), mWifiNative, mWifiConfigManager, mContext, mDppMetrics); - mIpMemoryStore = IpMemoryStore.getMemoryStore(mContext); // Register the various network evaluators with the network selector. mWifiNetworkSelector.registerNetworkEvaluator(mSavedNetworkEvaluator); mWifiNetworkSelector.registerNetworkEvaluator(mNetworkSuggestionEvaluator); - if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)) { - mWifiNetworkSelector.registerNetworkEvaluator(mPasspointNetworkEvaluator); - } + mWifiNetworkSelector.registerNetworkEvaluator(mPasspointNetworkEvaluator); mWifiNetworkSelector.registerNetworkEvaluator(mCarrierNetworkEvaluator); mWifiNetworkSelector.registerNetworkEvaluator(mScoredNetworkEvaluator); @@ -746,6 +742,9 @@ public class WifiInjector { } public IpMemoryStore getIpMemoryStore() { + if (mIpMemoryStore == null) { + mIpMemoryStore = IpMemoryStore.getMemoryStore(mContext); + } return mIpMemoryStore; } diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java index e8a06881bd..e257eab8b1 100644 --- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java +++ b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java @@ -32,9 +32,11 @@ import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; /** * This Class is a Work-In-Progress, intended behavior is as follows: @@ -94,6 +96,9 @@ public class WifiLastResortWatchdog { private Map<String, Pair<AvailableNetworkFailureCount, Integer>> mSsidFailureCount = new HashMap<>(); + /* List of failure BSSID */ + private Set<String> mBssidFailureList = new HashSet<>(); + // Tracks: if ClientModeImpl is in ConnectedState private boolean mWifiIsConnected = false; // Is Watchdog allowed to trigger now? Set to false after triggering. Set to true after @@ -208,11 +213,11 @@ public class WifiLastResortWatchdog { */ public void updateAvailableNetworks( List<Pair<ScanDetail, WifiConfiguration>> availableNetworks) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateAvailableNetworks: size = " + availableNetworks.size()); - } // Add new networks to mRecentAvailableNetworks if (availableNetworks != null) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "updateAvailableNetworks: size = " + availableNetworks.size()); + } for (Pair<ScanDetail, WifiConfiguration> pair : availableNetworks) { final ScanDetail scanDetail = pair.first; final WifiConfiguration config = pair.second; @@ -240,9 +245,9 @@ public class WifiLastResortWatchdog { 1); // Do not re-enable Watchdog in LAST_TRIGGER_TIMEOUT_MILLIS // after last time Watchdog be triggered - if (mTimeLastTrigger == 0 + if (!mWatchdogAllowedToTrigger && (mTimeLastTrigger == 0 || (mClock.getElapsedSinceBootMillis() - mTimeLastTrigger) - >= LAST_TRIGGER_TIMEOUT_MILLIS) { + >= LAST_TRIGGER_TIMEOUT_MILLIS)) { localLog("updateAvailableNetworks: setWatchdogTriggerEnabled to true"); setWatchdogTriggerEnabled(true); } @@ -330,7 +335,6 @@ public class WifiLastResortWatchdog { localLog(toString()); mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); incrementWifiMetricsTriggerCounts(); - clearAllFailureCounts(); } return isRestartNeeded; } @@ -349,7 +353,8 @@ public class WifiLastResortWatchdog { } if (!mWatchdogAllowedToTrigger && mWatchdogFixedWifi && checkIfAtleastOneNetworkHasEverConnected() - && checkIfConnectedBackToSameSsid()) { + && checkIfConnectedBackToSameSsid() + && checkIfConnectedBssidHasEverFailed()) { takeBugReportWithCurrentProbability("Wifi fixed after restart"); // WiFi has connected after a Watchdog trigger, without any new networks becoming // available, log a Watchdog success in wifi metrics @@ -357,8 +362,6 @@ public class WifiLastResortWatchdog { long durationMs = mClock.getElapsedSinceBootMillis() - mTimeLastTrigger; mWifiMetrics.setWatchdogSuccessTimeDurationMs(durationMs); } - // We connected to something! Reset failure counts for everything - clearAllFailureCounts(); // If the watchdog trigger was disabled (it triggered), connecting means we did // something right, re-enable it so it can fire again. localLog("connectedStateTransition: setWatchdogTriggerEnabled to true"); @@ -366,6 +369,14 @@ public class WifiLastResortWatchdog { } /** + * Helper function to check if device connected to BSSID + * which is in BSSID failure list after watchdog trigger. + */ + private boolean checkIfConnectedBssidHasEverFailed() { + return mBssidFailureList.contains(mClientModeImpl.getWifiInfo().getBSSID()); + } + + /** * Helper function to check if device connect back to same * SSID after watchdog trigger */ @@ -408,6 +419,7 @@ public class WifiLastResortWatchdog { // Bssid count is actually unused except for logging purposes // SSID count is incremented within the BSSID counting method incrementBssidFailureCount(ssid, bssid, reason); + mBssidFailureList.add(bssid); } } @@ -587,7 +599,7 @@ public class WifiLastResortWatchdog { } /** - * Clear failure counts for each network in recentAvailableNetworks + * Clear all failure counts */ public void clearAllFailureCounts() { if (mVerboseLoggingEnabled) Log.v(TAG, "clearAllFailureCounts."); @@ -601,6 +613,7 @@ public class WifiLastResortWatchdog { final AvailableNetworkFailureCount failureCount = entry.getValue().first; failureCount.resetCounts(); } + mBssidFailureList.clear(); } /** * Gets the buffer of recently available networks @@ -615,6 +628,10 @@ public class WifiLastResortWatchdog { */ private void setWatchdogTriggerEnabled(boolean enable) { if (mVerboseLoggingEnabled) Log.v(TAG, "setWatchdogTriggerEnabled: enable = " + enable); + // Reset failure counts before actives watchdog + if (enable) { + clearAllFailureCounts(); + } mWatchdogAllowedToTrigger = enable; } diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index c0b04d34c7..724f072259 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -905,24 +905,6 @@ public class WifiMetrics { } /** - * Increment number of pno scans started successfully over offload - */ - public void incrementPnoScanStartedOverOffloadCount() { - synchronized (mLock) { - mPnoScanMetrics.numPnoScanStartedOverOffload++; - } - } - - /** - * Increment number of pno scans failed over offload - */ - public void incrementPnoScanFailedOverOffloadCount() { - synchronized (mLock) { - mPnoScanMetrics.numPnoScanFailedOverOffload++; - } - } - - /** * Increment number of times pno scan found a result */ public void incrementPnoFoundNetworkEventCount() { diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index 5ed0b7bdc8..35316f7c34 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -51,6 +51,7 @@ import com.android.server.wifi.util.WifiPermissionsUtil; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -607,6 +608,10 @@ public class WifiNetworkSuggestionsManager { mAppOps.stopWatchingMode(appOpsChangedListener); } + /** + * Remove provided list from that App active list. If provided list is empty, will remove all. + * Will disconnect network if current connected network is in the remove list. + */ private void removeInternal( @NonNull Collection<ExtendedWifiNetworkSuggestion> extNetworkSuggestions, @NonNull String packageName, @@ -626,6 +631,8 @@ public class WifiNetworkSuggestionsManager { // Stop tracking app-op changes from the app if they don't have active suggestions. stopTrackingAppOpsChange(packageName); } + // Disconnect suggested network if connected + triggerDisconnectIfServingNetworkSuggestionRemoved(extNetworkSuggestions); // Clear the scan cache. removeFromScanResultMatchInfoMap(extNetworkSuggestions); } @@ -653,13 +660,6 @@ public class WifiNetworkSuggestionsManager { + ". Network suggestions not found in active network suggestions"); return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID; } - if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { - // empty list is used to clear everything for the app. - if (extNetworkSuggestions.isEmpty()) { - extNetworkSuggestions = new HashSet<>(perAppInfo.extNetworkSuggestions); - } - triggerDisconnectIfServingNetworkSuggestionRemoved(extNetworkSuggestions); - } removeInternal(extNetworkSuggestions, packageName, perAppInfo); saveToStore(); mWifiMetrics.incrementNetworkSuggestionApiNumModification(); @@ -673,8 +673,6 @@ public class WifiNetworkSuggestionsManager { public void removeApp(@NonNull String packageName) { PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); if (perAppInfo == null) return; - // Disconnect from the current network, if the only suggestion for it was removed. - triggerDisconnectIfServingNetworkSuggestionRemoved(perAppInfo.extNetworkSuggestions); removeInternal(Collections.EMPTY_LIST, packageName, perAppInfo); // Remove the package fully from the internal database. mActiveNetworkSuggestionsPerApp.remove(packageName); @@ -683,14 +681,27 @@ public class WifiNetworkSuggestionsManager { } /** + * Get all network suggestion for target App + * @return List of WifiNetworkSuggestions + */ + public @NonNull List<WifiNetworkSuggestion> get(@NonNull String packageName) { + List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); + PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); + // if App never suggested return empty list. + if (perAppInfo == null) return networkSuggestionList; + for (ExtendedWifiNetworkSuggestion extendedSuggestion : perAppInfo.extNetworkSuggestions) { + networkSuggestionList.add(extendedSuggestion.wns); + } + return networkSuggestionList; + } + + + /** * Clear all internal state (for network settings reset). */ public void clear() { Iterator<Map.Entry<String, PerAppInfo>> iter = mActiveNetworkSuggestionsPerApp.entrySet().iterator(); - // Disconnect if we're connected to one of the suggestions. - triggerDisconnectIfServingNetworkSuggestionRemoved( - mActiveNetworkSuggestionsMatchingConnection); while (iter.hasNext()) { Map.Entry<String, PerAppInfo> entry = iter.next(); removeInternal(Collections.EMPTY_LIST, entry.getKey(), entry.getValue()); diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java index 973c06dc9f..86b72f6e99 100644 --- a/service/java/com/android/server/wifi/WifiScoreCard.java +++ b/service/java/com/android/server/wifi/WifiScoreCard.java @@ -789,6 +789,7 @@ public class WifiScoreCard { * @param obfuscate - if true, ssids and bssids are omitted (short id only) */ public byte[] getNetworkListByteArray(boolean obfuscate) { + // These are really grouped by ssid, ignoring the security type. Map<String, Network.Builder> networks = new ArrayMap<>(); for (PerBssid perBssid: mApForBssid.values()) { String key = perBssid.ssid; @@ -799,15 +800,12 @@ public class WifiScoreCard { if (!obfuscate) { network.setSsid(perBssid.ssid); } - if (perBssid.mSecurityType != null) { - network.setSecurityType(perBssid.mSecurityType); - } - if (perBssid.mNetworkAgentId >= network.getNetworkAgentId()) { - network.setNetworkAgentId(perBssid.mNetworkAgentId); - } - if (perBssid.mNetworkConfigId >= network.getNetworkConfigId()) { - network.setNetworkConfigId(perBssid.mNetworkConfigId); - } + } + if (perBssid.mNetworkAgentId >= network.getNetworkAgentId()) { + network.setNetworkAgentId(perBssid.mNetworkAgentId); + } + if (perBssid.mNetworkConfigId >= network.getNetworkConfigId()) { + network.setNetworkConfigId(perBssid.mNetworkConfigId); } network.addAccessPoints(perBssid.toAccessPoint(obfuscate)); } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 51c3dc7122..e8c7d8301f 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -1305,7 +1305,7 @@ public class WifiServiceImpl extends BaseWifiService { } // also clear interface ip state - send null for now since we don't know what // interface (and we only have one anyway) - updateInterfaceIpState(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); + updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); } return; } @@ -1939,9 +1939,6 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("getMatchingPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); } - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)) { - return new HashMap<>(); - } return mClientModeImpl.syncGetAllMatchingFqdnsForScanResults(scanResults, mClientModeImplChannel); } @@ -1961,9 +1958,6 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("getMatchingOsuProviders uid=%").c(Binder.getCallingUid()).flush(); } - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)) { - return new HashMap<>(); - } return mClientModeImpl.syncGetMatchingOsuProviders(scanResults, mClientModeImplChannel); } @@ -1983,9 +1977,6 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getMatchingPasspointConfigsForOsuProviders uid=%").c( Binder.getCallingUid()).flush(); } - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)) { - return new HashMap<>(); - } if (osuProviders == null) { Log.e(TAG, "Attempt to retrieve Passpoint configuration with null osuProviders"); return new HashMap<>(); @@ -2012,9 +2003,6 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getWifiConfigsForPasspointProfiles uid=%").c( Binder.getCallingUid()).flush(); } - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)) { - return new ArrayList<>(); - } if (fqdnList == null) { Log.e(TAG, "Attempt to retrieve WifiConfiguration with null fqdn List"); return new ArrayList<>(); @@ -2289,10 +2277,6 @@ public class WifiServiceImpl extends BaseWifiService { return false; } mLog.info("addorUpdatePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); - if (!mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)) { - return false; - } return mClientModeImpl.syncAddOrUpdatePasspointConfig(mClientModeImplChannel, config, Binder.getCallingUid(), packageName); } @@ -2314,9 +2298,6 @@ public class WifiServiceImpl extends BaseWifiService { throw new SecurityException(TAG + ": Permission denied"); } mLog.info("removePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)) { - return false; - } return mClientModeImpl.syncRemovePasspointConfig(mClientModeImplChannel, fqdn); } @@ -2341,10 +2322,6 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); } - if (!mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)) { - return new ArrayList<>(); - } return mClientModeImpl.syncGetPasspointConfigs(mClientModeImplChannel); } @@ -2357,10 +2334,6 @@ public class WifiServiceImpl extends BaseWifiService { public void queryPasspointIcon(long bssid, String fileName) { enforceAccessPermission(); mLog.info("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); - if (!mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)) { - throw new UnsupportedOperationException("Passpoint not enabled"); - } mClientModeImpl.syncQueryPasspointIcon(mClientModeImplChannel, bssid, fileName); } @@ -2969,14 +2942,11 @@ public class WifiServiceImpl extends BaseWifiService { } // Delete all Passpoint configurations - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)) { - List<PasspointConfiguration> configs = mClientModeImpl.syncGetPasspointConfigs( - mClientModeImplChannel); - if (configs != null) { - for (PasspointConfiguration config : configs) { - removePasspointConfiguration(config.getHomeSp().getFqdn(), packageName); - } + List<PasspointConfiguration> configs = mClientModeImpl.syncGetPasspointConfigs( + mClientModeImplChannel); + if (configs != null) { + for (PasspointConfiguration config : configs) { + removePasspointConfiguration(config.getHomeSp().getFqdn(), packageName); } } } @@ -3149,10 +3119,6 @@ public class WifiServiceImpl extends BaseWifiService { if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { throw new SecurityException(TAG + ": Permission denied"); } - if (!mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)) { - throw new UnsupportedOperationException("Passpoint not enabled"); - } final int uid = Binder.getCallingUid(); mLog.trace("startSubscriptionProvisioning uid=%").c(uid).flush(); if (mClientModeImpl.syncStartSubscriptionProvisioning(uid, provider, @@ -3359,6 +3325,28 @@ public class WifiServiceImpl extends BaseWifiService { } /** + * See {@link android.net.wifi.WifiManager#getNetworkSuggestions()} + * @param callingPackageName Package Name of the app getting the suggestions. + * @return a list of network suggestions suggested by this app + */ + public List<WifiNetworkSuggestion> getNetworkSuggestions(String callingPackageName) { + mAppOps.checkPackage(Binder.getCallingUid(), callingPackageName); + enforceAccessPermission(); + if (mVerboseLoggingEnabled) { + mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush(); + } + Mutable<List<WifiNetworkSuggestion>> result = new Mutable<>(); + boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors( + () -> result.value = mWifiNetworkSuggestionsManager.get(callingPackageName), + RUN_WITH_SCISSORS_TIMEOUT_MILLIS); + if (!runWithScissorsSuccess) { + Log.e(TAG, "Failed to post runnable to get network suggestions"); + return new ArrayList<>(); + } + return result.value; + } + + /** * Gets the factory Wi-Fi MAC addresses. * @throws SecurityException if the caller does not have permission. * @return Array of String representing Wi-Fi MAC addresses, or null if failed. diff --git a/service/java/com/android/server/wifi/WificondControl.java b/service/java/com/android/server/wifi/WificondControl.java index bd756f6439..43983a40fc 100644 --- a/service/java/com/android/server/wifi/WificondControl.java +++ b/service/java/com/android/server/wifi/WificondControl.java @@ -158,18 +158,6 @@ public class WificondControl implements IBinder.DeathRecipient { Log.d(TAG, "Pno Scan failed event"); mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount(); } - - @Override - public void OnPnoScanOverOffloadStarted() { - Log.d(TAG, "Pno scan over offload started"); - mWifiInjector.getWifiMetrics().incrementPnoScanStartedOverOffloadCount(); - } - - @Override - public void OnPnoScanOverOffloadFailed(int reason) { - Log.d(TAG, "Pno scan over offload failed"); - mWifiInjector.getWifiMetrics().incrementPnoScanFailedOverOffloadCount(); - } } /** diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java index 366af13f35..7cb6e84c87 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java @@ -26,13 +26,16 @@ import android.hardware.wifi.V1_0.NanMatchInd; import android.hardware.wifi.V1_0.NanStatusType; import android.hardware.wifi.V1_0.WifiNanStatus; import android.hardware.wifi.V1_2.IWifiNanIfaceEventCallback; +import android.hardware.wifi.V1_2.NanDataPathChannelInfo; import android.hardware.wifi.V1_2.NanDataPathScheduleUpdateInd; import android.os.ShellCommand; import android.util.Log; +import android.util.SparseArray; import android.util.SparseIntArray; import libcore.util.HexEncoding; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -75,13 +78,14 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp private static final int CB_EV_DATA_PATH_SCHED_UPDATE = 11; private SparseIntArray mCallbackCounter = new SparseIntArray(); + private SparseArray<ArrayList<NanDataPathChannelInfo>> mChannelInfoPerNdp = new SparseArray<>(); private void incrementCbCount(int callbackId) { mCallbackCounter.put(callbackId, mCallbackCounter.get(callbackId) + 1); } /** - * Interpreter of adb shell command 'adb shell wifiaware native_cb ...'. + * Interpreter of adb shell command 'adb shell cmd wifiaware native_cb ...'. * * @return -1 if parameter not recognized or invalid value, 0 otherwise. */ @@ -121,6 +125,17 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp } return 0; } + case "get_channel_info": { + String option = parentShell.getNextOption(); + if (VDBG) Log.v(TAG, "option='" + option + "'"); + if (option != null) { + pwe.println("Unknown option to 'get_channel_info'"); + return -1; + } + String channelInfoString = convertChannelInfoToJsonString(); + pwo.println(channelInfoString); + return 0; + } default: pwe.println("Unknown 'wifiaware native_cb <cmd>'"); } @@ -140,6 +155,7 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp pw.println(" " + command); pw.println(" get_cb_count [--reset]: gets the number of callbacks (and optionally reset " + "count)"); + pw.println(" get_channel_info: prints out existing NDP channel info as a JSON String"); } @Override @@ -502,13 +518,15 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp + ", peerNdiMacAddr=" + String.valueOf( HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess=" + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status - + ", appInfo.size()=" + event.V1_0.appInfo.size()); + + ", appInfo.size()=" + event.V1_0.appInfo.size() + + ", channelInfo" + event.channelInfo); } if (!mIsHal12OrLater) { Log.wtf(TAG, "eventDataPathConfirm_1_2 should not be called by a <1.2 HAL!"); return; } incrementCbCount(CB_EV_DATA_PATH_CONFIRM); + mChannelInfoPerNdp.put(event.V1_0.ndpInstanceId, event.channelInfo); mWifiAwareStateManager.onDataPathConfirmNotification(event.V1_0.ndpInstanceId, event.V1_0.peerNdiMacAddr, event.V1_0.dataPathSetupSuccess, @@ -526,6 +544,9 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp return; } incrementCbCount(CB_EV_DATA_PATH_SCHED_UPDATE); + for (int ndpInstanceId : event.ndpInstanceIds) { + mChannelInfoPerNdp.put(ndpInstanceId, event.channelInfo); + } mWifiAwareStateManager.onDataPathScheduleUpdateNotification(event.peerDiscoveryAddress, event.ndpInstanceIds, event.channelInfo); @@ -535,16 +556,25 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp public void eventDataPathTerminated(int ndpInstanceId) { if (mDbg) Log.v(TAG, "eventDataPathTerminated: ndpInstanceId=" + ndpInstanceId); incrementCbCount(CB_EV_DATA_PATH_TERMINATED); + mChannelInfoPerNdp.remove(ndpInstanceId); mWifiAwareStateManager.onDataPathEndNotification(ndpInstanceId); } /** + * Reset the channel info when Aware is down. + */ + /* package */ void resetChannelInfo() { + mChannelInfoPerNdp.clear(); + } + + /** * Dump the internal state of the class. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("WifiAwareNativeCallback:"); pw.println(" mCallbackCounter: " + mCallbackCounter); + pw.println(" mChannelInfoPerNdp: " + mChannelInfoPerNdp); } @@ -577,4 +607,30 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp sb.append(status.status).append(" (").append(status.description).append(")"); return sb.toString(); } + + /** + * Transfer the channel Info dict into a Json String which can be decoded by Json reader. + * The Format is: "{ndpInstanceId: [{"channelFreq": channelFreq, + * "channelBandwidth": channelBandwidth, "numSpatialStreams": numSpatialStreams}]}" + * @return Json String. + */ + private String convertChannelInfoToJsonString() { + JSONObject channelInfoJson = new JSONObject(); + try { + for (int i = 0; i < mChannelInfoPerNdp.size(); i++) { + JSONArray infoJsonArray = new JSONArray(); + for (NanDataPathChannelInfo info : mChannelInfoPerNdp.valueAt(i)) { + JSONObject j = new JSONObject(); + j.put("channelFreq", info.channelFreq); + j.put("channelBandwidth", info.channelBandwidth); + j.put("numSpatialStreams", info.numSpatialStreams); + infoJsonArray.put(j); + } + channelInfoJson.put(Integer.toString(mChannelInfoPerNdp.keyAt(i)), infoJsonArray); + } + } catch (JSONException e) { + Log.e(TAG, "onCommand: get_channel_info e=" + e); + } + return channelInfoJson.toString(); + } } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java index 6556bb084b..e3361bfc0a 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java @@ -51,6 +51,7 @@ public class WifiAwareNativeManager { private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener = new InterfaceAvailableForRequestListener(); private int mReferenceCount = 0; + private volatile boolean mAwareNativeAvailable = false; WifiAwareNativeManager(WifiAwareStateManager awareStateManager, HalDeviceManager halDeviceManager, @@ -101,6 +102,13 @@ public class WifiAwareNativeManager { } /** + * Return the Availability of WifiAware native HAL + */ + public boolean isAwareNativeAvailable() { + return mAwareNativeAvailable; + } + + /** * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched. * Return may be null if not initialized/available. */ @@ -194,6 +202,7 @@ public class WifiAwareNativeManager { mInterfaceDestroyedListener = null; mHalDeviceManager.removeIface(mWifiNanIface); mWifiNanIface = null; + mWifiAwareNativeCallback.resetChannelInfo(); } } @@ -205,6 +214,7 @@ public class WifiAwareNativeManager { } mWifiNanIface = null; mReferenceCount = 0; + mAwareNativeAvailable = false; mWifiAwareStateManager.disableUsage(); } } @@ -235,8 +245,10 @@ public class WifiAwareNativeManager { } synchronized (mLock) { if (isAvailable) { + mAwareNativeAvailable = true; mWifiAwareStateManager.enableUsage(); } else if (mWifiNanIface == null) { // not available could mean already have NAN + mAwareNativeAvailable = false; mWifiAwareStateManager.disableUsage(); } } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java index e6e961d690..a0f937d33b 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java @@ -418,7 +418,7 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub { + ", retryCount=" + retryCount); } - mStateManager.sendMessage(clientId, sessionId, peerId, message, messageId, retryCount); + mStateManager.sendMessage(uid, clientId, sessionId, peerId, message, messageId, retryCount); } @Override diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java index 9b096e525a..072788081b 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java @@ -673,8 +673,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe * Place a request to send a message on a discovery session on the state * machine queue. */ - public void sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId, - int retryCount) { + public void sendMessage(int uid, int clientId, int sessionId, int peerId, byte[] message, + int messageId, int retryCount) { Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); msg.arg1 = COMMAND_TYPE_ENQUEUE_SEND_MESSAGE; msg.arg2 = clientId; @@ -683,6 +683,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message); msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID, messageId); msg.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT, retryCount); + msg.getData().putInt(MESSAGE_BUNDLE_KEY_UID, uid); mSm.sendMessage(msg); } @@ -704,6 +705,10 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe if (mDbg) Log.d(TAG, "enableUsage(): while Wi-Fi is disabled - ignoring"); return; } + if (!mWifiAwareNativeManager.isAwareNativeAvailable()) { + if (mDbg) Log.d(TAG, "enableUsage(): while Aware Native isn't Available - ignoring"); + return; + } Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); msg.arg1 = COMMAND_TYPE_ENABLE_USAGE; mSm.sendMessage(msg); @@ -1196,6 +1201,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe private short mCurrentTransactionId = TRANSACTION_ID_IGNORE; private static final long AWARE_SEND_MESSAGE_TIMEOUT = 10_000; + private static final int MESSAGE_QUEUE_DEPTH_PER_UID = 50; private int mSendArrivalSequenceCounter = 0; private boolean mSendQueueBlocked = false; private final SparseArray<Message> mHostQueuedSendMessages = new SparseArray<>(); @@ -1633,6 +1639,17 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID) + ", mSendArrivalSequenceCounter=" + mSendArrivalSequenceCounter); } + int uid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_UID); + if (isUidExceededMessageQueueDepthLimit(uid)) { + if (mDbg) { + Log.v(TAG, "message queue limit exceeded for uid=" + uid + + " at messageId=" + + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID)); + } + onMessageSendFailLocal(msg, NanStatusType.INTERNAL_FAILURE); + waitForResponse = false; + break; + } Message sendMsg = obtainMessage(msg.what); sendMsg.copyFrom(msg); sendMsg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ, @@ -2103,6 +2120,24 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe transmitNextMessage(); } + private boolean isUidExceededMessageQueueDepthLimit(int uid) { + int size = mHostQueuedSendMessages.size(); + int numOfMessages = 0; + if (size < MESSAGE_QUEUE_DEPTH_PER_UID) { + return false; + } + for (int i = 0; i < size; ++i) { + if (mHostQueuedSendMessages.valueAt(i).getData() + .getInt(MESSAGE_BUNDLE_KEY_UID) == uid) { + numOfMessages++; + if (numOfMessages >= MESSAGE_QUEUE_DEPTH_PER_UID) { + return true; + } + } + } + return false; + } + @Override protected String getLogRecString(Message msg) { StringBuilder sb = new StringBuilder(WifiAwareStateManager.messageToString(msg)); @@ -2542,6 +2577,10 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } if (completedCommand.arg1 == COMMAND_TYPE_CONNECT) { + if (mCurrentAwareConfiguration == null) { // enabled (as opposed to re-configured) + createAllDataPathInterfaces(); + } + Bundle data = completedCommand.getData(); int clientId = completedCommand.arg2; @@ -2580,9 +2619,6 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe return; } - if (mCurrentAwareConfiguration == null) { // enabled (as opposed to re-configured) - createAllDataPathInterfaces(); - } mCurrentAwareConfiguration = mergeConfigRequests(null); if (mCurrentAwareConfiguration == null) { Log.wtf(TAG, "onConfigCompletedLocal: got a null merged configuration after config!?"); diff --git a/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java b/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java index 94f584f72c..f56945a98f 100644 --- a/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java +++ b/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java @@ -413,11 +413,25 @@ public class OsuServerConnection { } X509Certificate certificate = getCert(certInfo.getKey()); - if (certificate == null || !ServiceProviderVerifier.verifyCertFingerprint( + if (certificate == null) { + // In case of an invalid cert, clear all of retrieved CA certs so that + // PasspointProvisioner aborts current flow. getCert already logs the error. + trustRootCertificates.clear(); + break; + } + + // Verify that the certificate's fingerprint matches the one provided in the PPS-MO + // profile, in accordance with section 7.3.1 of the HS2.0 specification. + if (!ServiceProviderVerifier.verifyCertFingerprint( certificate, certInfo.getValue())) { - // If any failure happens, clear all of retrieved CA certs so that + // If fingerprint does not match, clear all of retrieved CA certs so that // PasspointProvisioner aborts current flow. trustRootCertificates.clear(); + String certName = ""; + if (certificate.getSubjectDN() != null) { + certName = certificate.getSubjectDN().getName(); + } + Log.e(TAG, "Fingerprint does not match the certificate " + certName); break; } certificates.add(certificate); diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java index a26582c5c9..a800aa976d 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -90,6 +90,7 @@ import android.util.Pair; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.internal.R; import com.android.internal.app.IBatteryStats; import com.android.internal.util.AsyncChannel; @@ -114,6 +115,8 @@ import org.mockito.ArgumentMatcher; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; +import org.mockito.quality.Strictness; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; @@ -153,6 +156,10 @@ public class ClientModeImplTest { MacAddress.fromString("10:22:34:56:78:92"); private static final MacAddress TEST_LOCAL_MAC_ADDRESS = MacAddress.fromString("2a:53:43:c3:56:21"); + private static final MacAddress TEST_DEFAULT_MAC_ADDRESS = + MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); + private static final MacAddress TEST_AGGRESSIVE_MAC_ADDRESS = + MacAddress.fromString("3a:53:43:c3:56:21"); // NetworkAgent creates threshold ranges with Integers private static final int RSSI_THRESHOLD_MAX = -30; @@ -162,6 +169,7 @@ public class ClientModeImplTest { private static final byte RSSI_THRESHOLD_BREACH_MAX = -20; private long mBinderToken; + private MockitoSession mSession; private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) { return mock(class1, withSettings().extraInterfaces(interfaces)); @@ -403,7 +411,6 @@ public class ClientModeImplTest { /** uncomment this to enable logs from ClientModeImpls */ // enableDebugLogs(); - mWifiMonitor = new MockWifiMonitor(); when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); when(mWifiInjector.getClock()).thenReturn(new Clock()); @@ -496,6 +503,11 @@ public class ClientModeImplTest { mIpClientCallback.onQuit(); return null; }).when(mIpClient).shutdown(); + + // static mocking + mSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT) + .spyStatic(MacAddress.class) + .startMocking(); initializeCmi(); mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); @@ -582,6 +594,7 @@ public class ClientModeImplTest { mNetworkAgentAsyncChannel = null; mNetworkAgentHandler = null; mCmi = null; + mSession.finishMocking(); } @Test @@ -935,7 +948,7 @@ public class ClientModeImplTest { loadComponentsInStaMode(); WifiConfiguration config = mConnectedNetwork; config.networkId = FRAMEWORK_NETWORK_ID; - when(config.getOrCreateRandomizedMacAddress()).thenReturn(TEST_LOCAL_MAC_ADDRESS); + config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS); config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; setupAndStartConnectSequence(config); validateSuccessfulConnectSequence(config); @@ -2559,6 +2572,56 @@ public class ClientModeImplTest { } /** + * Verifies that + * 1. aggressive MAC is generated when ClientModeImpl is created. + * 2. aggressive MAC is generated again during connection when the appropriate amount of time + * have passed. + * @throws Exception + */ + @Test + public void testAggressiveMacUpdatedDuringConnection() throws Exception { + ExtendedMockito.verify(() -> MacAddress.createRandomUnicastAddress()); + when(mClock.getElapsedSinceBootMillis()).thenReturn( + ClientModeImpl.AGGRESSIVE_MAC_REFRESH_MS + 1); + connect(); + ExtendedMockito.verify(() -> MacAddress.createRandomUnicastAddress(), times(2)); + } + + /** + * Verifies that aggressive MAC is not updated due to time constraint. + * @throws Exception + */ + @Test + public void testAggressiveMacNotUpdatedDueToTimeConstraint() throws Exception { + ExtendedMockito.verify(() -> MacAddress.createRandomUnicastAddress()); + when(mClock.getElapsedSinceBootMillis()).thenReturn( + ClientModeImpl.AGGRESSIVE_MAC_REFRESH_MS); + connect(); + ExtendedMockito.verify(() -> MacAddress.createRandomUnicastAddress()); + } + + /** + * Verifies that + * 1. connected MAC randomization is on and + * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and + * 3. the WifiConfiguration should use "aggressive mode" + * 4. ClientmodeImpl programs the aggressive MAC when connecting the network. + */ + @Test + public void testMacRandomizationAggressiveMacIsUsed() throws Exception { + when(MacAddress.createRandomUnicastAddress()).thenReturn(TEST_AGGRESSIVE_MAC_ADDRESS); + when(mWifiConfigManager.shouldUseAggressiveMode(any())).thenReturn(true); + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + when(mClock.getElapsedSinceBootMillis()).thenReturn( + ClientModeImpl.AGGRESSIVE_MAC_REFRESH_MS + 1); + connect(); + verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_AGGRESSIVE_MAC_ADDRESS); + } + + /** * Verifies that when * 1. Global feature support flag is set to false * 2. connected MAC randomization is on and @@ -2576,8 +2639,6 @@ public class ClientModeImplTest { assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); connect(); - verify(mWifiConfigManager, never()).setNetworkRandomizedMacAddress(0, - TEST_LOCAL_MAC_ADDRESS); verify(mWifiNative, never()).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); verify(mWifiMetrics, never()) .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); @@ -2601,7 +2662,6 @@ public class ClientModeImplTest { assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); connect(); - verify(mWifiConfigManager).setNetworkRandomizedMacAddress(0, TEST_LOCAL_MAC_ADDRESS); verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); verify(mWifiMetrics) .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); @@ -2626,7 +2686,6 @@ public class ClientModeImplTest { .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString()); connect(); - verify(mWifiConfigManager).setNetworkRandomizedMacAddress(0, TEST_LOCAL_MAC_ADDRESS); verify(mWifiNative, never()).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); verify(mWifiMetrics, never()) .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); @@ -2660,7 +2719,6 @@ public class ClientModeImplTest { mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); mLooper.dispatchAll(); - verify(mWifiConfigManager, never()).setNetworkRandomizedMacAddress(anyInt(), any()); verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS); verify(mWifiMetrics) .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); @@ -2692,7 +2750,6 @@ public class ClientModeImplTest { mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); mLooper.dispatchAll(); - verify(mWifiConfigManager, never()).setNetworkRandomizedMacAddress(anyInt(), any()); verify(mWifiNative, never()).setMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS); verify(mWifiMetrics, never()) .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); @@ -2734,8 +2791,7 @@ public class ClientModeImplTest { WifiConfiguration config = mock(WifiConfiguration.class); config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - when(config.getOrCreateRandomizedMacAddress()) - .thenReturn(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS)); + config.setRandomizedMacAddress(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS)); when(config.getNetworkSelectionStatus()) .thenReturn(new WifiConfiguration.NetworkSelectionStatus()); when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); @@ -2743,7 +2799,6 @@ public class ClientModeImplTest { mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); mLooper.dispatchAll(); - verify(config).getOrCreateRandomizedMacAddress(); verify(mWifiNative, never()).setMacAddress(eq(WIFI_IFACE_NAME), any(MacAddress.class)); } @@ -3705,4 +3760,39 @@ public class ClientModeImplTest { verify(mWifiNative).simIdentityResponse(WIFI_IFACE_NAME, FRAMEWORK_NETWORK_ID, "13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", ""); } + + /** + * Verifies that WifiLastResortWatchdog is notified of DHCP failures when recevied + * NETWORK_DISCONNECTION_EVENT while in ObtainingIpState. + */ + @Test + public void testDhcpFailureUpdatesWatchdog_WhenDisconnectedWhileObtainingIpAddr() + throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + + verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); + + mLooper.startAutoDispatch(); + mCmi.syncEnableNetwork(mCmiAsyncChannel, 0, true); + mLooper.stopAutoDispatch(); + + verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); + + mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); + mLooper.dispatchAll(); + + assertEquals("ObtainingIpState", getCurrentState().getName()); + + // Verifies that WifiLastResortWatchdog be notified. + mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + assertEquals("DisconnectedState", getCurrentState().getName()); + verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded( + sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_DHCP); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 28964b1096..cd7aee301a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -1902,9 +1902,6 @@ public class WifiConfigManagerTest { WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(config); - MacAddress testMac = MacAddress.createRandomUnicastAddress(); - mWifiConfigManager.setNetworkRandomizedMacAddress(result.getNetworkId(), testMac); - // Verify that randomized MAC address is masked when obtaining saved networks from // invalid UID List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.INVALID_UID); @@ -1915,7 +1912,8 @@ public class WifiConfigManagerTest { // system UID configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); assertEquals(1, configs.size()); - assertEquals(testMac, configs.get(0).getRandomizedMacAddress()); + String macAddress = configs.get(0).getRandomizedMacAddress().toString(); + assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, macAddress); // Verify that randomized MAC address is masked when obtaining saved networks from // (carrier app) non-creator of the config @@ -1927,18 +1925,18 @@ public class WifiConfigManagerTest { // (carrier app) creator of the config configs = mWifiConfigManager.getSavedNetworks(TEST_CREATOR_UID); assertEquals(1, configs.size()); - assertEquals(testMac, configs.get(0).getRandomizedMacAddress()); + assertEquals(macAddress, configs.get(0).getRandomizedMacAddress().toString()); // Verify that randomized MAC address is unmasked when getting list of privileged (with // password) configurations WifiConfiguration configWithRandomizedMac = mWifiConfigManager .getConfiguredNetworkWithPassword(result.getNetworkId()); - assertEquals(testMac, configWithRandomizedMac.getRandomizedMacAddress()); + assertEquals(macAddress, configs.get(0).getRandomizedMacAddress().toString()); // Ensure that the MAC address is present when asked for config with MAC address. configWithRandomizedMac = mWifiConfigManager .getConfiguredNetworkWithoutMasking(result.getNetworkId()); - assertEquals(testMac, configWithRandomizedMac.getRandomizedMacAddress()); + assertEquals(macAddress, configs.get(0).getRandomizedMacAddress().toString()); } /** @@ -1949,9 +1947,6 @@ public class WifiConfigManagerTest { WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(config); - MacAddress testMac = MacAddress.createRandomUnicastAddress(); - mWifiConfigManager.setNetworkRandomizedMacAddress(result.getNetworkId(), testMac); - // Verify macRandomizationSetting is not masked out when feature is supported. List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); assertEquals(1, configs.size()); @@ -1970,9 +1965,6 @@ public class WifiConfigManagerTest { WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(config); - MacAddress testMac = MacAddress.createRandomUnicastAddress(); - mWifiConfigManager.setNetworkRandomizedMacAddress(result.getNetworkId(), testMac); - // Verify macRandomizationSetting is masked out when feature is unsupported. List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); assertEquals(1, configs.size()); @@ -4299,31 +4291,6 @@ public class WifiConfigManagerTest { } /** - * Verifies that the method setNetworkRandomizedMacAddress changes the randomized MAC - * address variable in the internal configuration. - */ - @Test - public void testSetNetworkRandomizedMacAddressUpdatesInternalMacAddress() { - WifiConfiguration originalConfig = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(originalConfig); - - // Verify that internal randomized MAC address does not change from - // from setting external randomized MAC address - MacAddress originalMac = originalConfig.getOrCreateRandomizedMacAddress(); - WifiConfiguration retrievedConfig = mWifiConfigManager - .getConfiguredNetworkWithoutMasking(result.getNetworkId()); - assertNotEquals(originalMac, retrievedConfig.getRandomizedMacAddress()); - - // Verify that changing randomized MAC address through setNetworkRandomizedMacAddress - // changes the internal randomized MAC address - MacAddress newMac = MacAddress.createRandomUnicastAddress(); - mWifiConfigManager.setNetworkRandomizedMacAddress(result.getNetworkId(), newMac); - retrievedConfig = mWifiConfigManager - .getConfiguredNetworkWithoutMasking(result.getNetworkId()); - assertEquals(newMac, retrievedConfig.getRandomizedMacAddress()); - } - - /** * Verifies that the method resetSimNetworks updates SIM presence status and SIM configs. */ @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java index 7c55228caf..9f0b4f05e9 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java @@ -1520,8 +1520,9 @@ public class WifiLastResortWatchdogTest { verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogBadDhcpNetworksTotal(3); verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadDhcp(); - // set connection to ssids[0] + // set connection to ssids[0]/bssids[0] when(mWifiInfo.getSSID()).thenReturn(ssids[0]); + when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); // Simulate wifi connecting after triggering mLastResortWatchdog.connectedStateTransition(true); @@ -1859,8 +1860,9 @@ public class WifiLastResortWatchdogTest { // Simulate wifi disconnecting mLastResortWatchdog.connectedStateTransition(false); - // set connection to ssids[0] + // set connection to ssids[0]/bssids[0] when(mWifiInfo.getSSID()).thenReturn(ssids[0]); + when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); // Test another round, and this time successfully connect after restart trigger for (int i = 0; i < ssids.length; i++) { @@ -2073,8 +2075,9 @@ public class WifiLastResortWatchdogTest { verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); // Age out network + candidates = new ArrayList<>(); for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(null); + mLastResortWatchdog.updateAvailableNetworks(candidates); } assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 0); @@ -2145,8 +2148,9 @@ public class WifiLastResortWatchdogTest { // Simulate wifi disconnecting mLastResortWatchdog.connectedStateTransition(false); - // set connection to ssids[0] + // set connection to ssids[0]/bssids[0] when(mWifiInfo.getSSID()).thenReturn(ssids[0]); + when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); // Test another round, and this time successfully connect after restart trigger for (int i = 0; i < ssids.length; i++) { @@ -2254,4 +2258,59 @@ public class WifiLastResortWatchdogTest { mLooper.dispatchAll(); verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); } + + /** + * Verifies that bugreports are not triggered if device connected back to a new BSSID + * after recovery. + */ + @Test + public void testNotTriggerBugreportIfConnectedToNewBssid() { + int associationRejections = 4; + int authenticationFailures = 3; + String[] ssids = {"\"test1\"", "\"test1\"", "\"test1\""}; + String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55"}; + int[] frequencies = {2437, 5180, 5180}; + String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; + int[] levels = {-60, -86, -50}; + boolean[] isEphemeral = {false, false, false}; + boolean[] hasEverConnected = {true, true, true}; + // Buffer potential candidates 1,2,& 3 + List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, + bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); + mLastResortWatchdog.updateAvailableNetworks(candidates); + + // Ensure new networks have zero'ed failure counts + for (int i = 0; i < ssids.length; i++) { + assertFailureCountEquals(bssids[i], 0, 0, 0); + } + + long timeAtFailure = 100; + long timeAtReconnect = 5000; + when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure, timeAtReconnect); + + //Increment failure counts + for (int i = 0; i < associationRejections; i++) { + mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(ssids[1], bssids[1], + WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); + } + for (int i = 0; i < authenticationFailures; i++) { + mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(ssids[2], bssids[2], + WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); + } + + // Verify watchdog has triggered a restart + verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); + + // set connection to ssids[0]/bssids[0] + when(mWifiInfo.getSSID()).thenReturn(ssids[0]); + when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); + + // Simulate wifi connecting after triggering + mLastResortWatchdog.connectedStateTransition(true); + + // Verify takeBugReport is not called + mLooper.dispatchAll(); + verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); + verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java index 7e086d4ce1..4475ad99b4 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java @@ -383,8 +383,6 @@ public class WifiMetricsTest { private static final int NUM_PARTIAL_SCAN_RESULTS = 73; private static final int NUM_PNO_SCAN_ATTEMPTS = 20; private static final int NUM_PNO_SCAN_FAILED = 5; - private static final int NUM_PNO_SCAN_STARTED_OVER_OFFLOAD = 17; - private static final int NUM_PNO_SCAN_FAILED_OVER_OFFLOAD = 8; private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10; private static final int NUM_WPS_ATTEMPTS = 17; private static final int NUM_WPS_SUCCESS = 21; @@ -801,12 +799,6 @@ public class WifiMetricsTest { for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) { mWifiMetrics.incrementPnoScanFailedCount(); } - for (int i = 0; i < NUM_PNO_SCAN_STARTED_OVER_OFFLOAD; i++) { - mWifiMetrics.incrementPnoScanStartedOverOffloadCount(); - } - for (int i = 0; i < NUM_PNO_SCAN_FAILED_OVER_OFFLOAD; i++) { - mWifiMetrics.incrementPnoScanFailedOverOffloadCount(); - } for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) { mWifiMetrics.incrementPnoFoundNetworkEventCount(); } @@ -1156,8 +1148,6 @@ public class WifiMetricsTest { assertNotNull(pno_metrics); assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts); assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed); - assertEquals(NUM_PNO_SCAN_STARTED_OVER_OFFLOAD, pno_metrics.numPnoScanStartedOverOffload); - assertEquals(NUM_PNO_SCAN_FAILED_OVER_OFFLOAD, pno_metrics.numPnoScanFailedOverOffload); assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents); for (ConnectToNetworkNotificationAndActionCount notificationCount diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java index 97a1833707..b237a9cb1c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -1322,45 +1322,12 @@ public class WifiNetworkSuggestionsManagerTest { } /** - * Verify that we don't disconnect from the network if the only network suggestion matching the - * connected network is removed when App doesn't have NetworkCarrierProvisioningPermission. - */ - @Test - public void - testRemoveNetworkSuggestionsMatchingConnectionSuccessWithOneMatchNoCarrierProvision() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), false, false, TEST_UID_1, - TEST_PACKAGE_1); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, networkSuggestion.wifiConfiguration, - TEST_BSSID); - - // Now remove the network suggestion and ensure we did not trigger a disconnect. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - verify(mClientModeImpl, never()).disconnectCommand(); - } - - /** * Verify that we will disconnect from the network if the only network suggestion matching the - * connected network is removed when App has NetworkCarrierProvisioningPermission. + * connected network is removed. */ @Test public void - testRemoveNetworkSuggestionsMatchingConnectionSuccessWithOneMatchCarrierProvision() { + testRemoveNetworkSuggestionsMatchingConnectionSuccessWithOneMatch() { WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( WifiConfigurationTestUtil.createOpenNetwork(), false, false, TEST_UID_1, TEST_PACKAGE_1); @@ -1368,8 +1335,6 @@ public class WifiNetworkSuggestionsManagerTest { new ArrayList<WifiNetworkSuggestion>() {{ add(networkSuggestion); }}; - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(true); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1)); @@ -1388,12 +1353,12 @@ public class WifiNetworkSuggestionsManagerTest { } /** - * Verify that we will disconnect from network when App has NetworkCarrierProvisioningPermission - * and removed all its suggestions by remove empty list. + * Verify that we will disconnect from network when App removed all its suggestions by remove + * empty list. */ @Test public void - testRemoveAllNetworkSuggestionsMatchingConnectionSuccessWithOneMatchCarrierProvision() { + testRemoveAllNetworkSuggestionsMatchingConnectionSuccessWithOneMatch() { WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( WifiConfigurationTestUtil.createOpenNetwork(), false, false, TEST_UID_1, TEST_PACKAGE_1); @@ -1401,8 +1366,6 @@ public class WifiNetworkSuggestionsManagerTest { new ArrayList<WifiNetworkSuggestion>() {{ add(networkSuggestion); }}; - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(true); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1)); @@ -2009,6 +1972,55 @@ public class WifiNetworkSuggestionsManagerTest { } /** + * Verify get network suggestion return the right result + * 1. App never suggested, should return empty list. + * 2. App has network suggestions, return all its suggestion. + * 3. App suggested and remove them all, should return empty list. + */ + @Test + public void testGetNetworkSuggestions() { + // test App never suggested. + List<WifiNetworkSuggestion> storedNetworkSuggestionListPerApp = + mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1); + assertEquals(storedNetworkSuggestionListPerApp.size(), 0); + + // App add network suggestions then get stored suggestions. + WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOpenNetwork(), false, false, TEST_UID_1, + TEST_PACKAGE_1); + WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOweNetwork(), false, false, TEST_UID_1, + TEST_PACKAGE_1); + WifiNetworkSuggestion networkSuggestion3 = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createSaeNetwork(), false, false, TEST_UID_1, + TEST_PACKAGE_1); + WifiNetworkSuggestion networkSuggestion4 = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createPskNetwork(), false, false, TEST_UID_1, + TEST_PACKAGE_1); + List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); + networkSuggestionList.add(networkSuggestion1); + networkSuggestionList.add(networkSuggestion2); + networkSuggestionList.add(networkSuggestion3); + networkSuggestionList.add(networkSuggestion4); + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, + TEST_PACKAGE_1)); + mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); + storedNetworkSuggestionListPerApp = + mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1); + assertEquals(new HashSet<>(networkSuggestionList), + new HashSet<>(storedNetworkSuggestionListPerApp)); + + // App remove all network suggestions, expect empty list. + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.remove(new ArrayList<>(), TEST_UID_1, + TEST_PACKAGE_1)); + storedNetworkSuggestionListPerApp = + mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1); + assertEquals(storedNetworkSuggestionListPerApp.size(), 0); + } + + /** * Creates a scan detail corresponding to the provided network values. */ private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration) { diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index af624da112..24d8de54b2 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -99,6 +99,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; import android.net.wifi.WifiManager.SoftApCallback; +import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiSsid; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; @@ -385,8 +386,6 @@ public class WifiServiceImplTest { when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); when(mClientModeImpl.syncStartSubscriptionProvisioning(anyInt(), any(OsuProvider.class), any(IProvisioningCallback.class), any())).thenReturn(true); - when(mPackageManager.hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)).thenReturn(true); // Create an OSU provider that can be provisioned via an open OSU AP mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); @@ -2619,7 +2618,6 @@ public class WifiServiceImplTest { config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); PackageManager pm = mock(PackageManager.class); - when(pm.hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)).thenReturn(true); when(mContext.getPackageManager()).thenReturn(pm); when(pm.getApplicationInfo(any(), anyInt())).thenReturn(mApplicationInfo); when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), @@ -2699,21 +2697,6 @@ public class WifiServiceImplTest { } /** - * Verify that the call to startSubscriptionProvisioning is not directed to the Passpoint - * specific API startSubscriptionProvisioning when the feature is not supported. - */ - @Test(expected = UnsupportedOperationException.class) - public void testStartSubscriptionProvisioniningPasspointUnsupported() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mPackageManager.hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)).thenReturn(false); - mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, mProvisioningCallback); - } - - /** * Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint * specific API startSubscriptionProvisioning when the caller provides invalid arguments */ @@ -3626,29 +3609,6 @@ public class WifiServiceImplTest { } /** - * Verify that Passpoint configuration is not removed in factoryReset if Passpoint feature - * is not supported. - */ - @Test - public void testFactoryResetWithoutPasspointSupport() throws Exception { - setupClientModeImplHandlerForPost(); - - mWifiServiceImpl.mClientModeImplChannel = mAsyncChannel; - when(mPackageManager.hasSystemFeature( - PackageManager.FEATURE_WIFI_PASSPOINT)).thenReturn(false); - - mWifiServiceImpl.factoryReset(TEST_PACKAGE_NAME); - mLooper.dispatchAll(); - - verify(mClientModeImpl).syncGetConfiguredNetworks(anyInt(), any(), anyInt()); - verify(mClientModeImpl, never()).syncGetPasspointConfigs(any()); - verify(mClientModeImpl, never()).syncRemovePasspointConfig(any(), anyString()); - verify(mWifiConfigManager).clearDeletedEphemeralNetworks(); - verify(mClientModeImpl).clearNetworkRequestUserApprovedAccessPoints(); - verify(mWifiNetworkSuggestionsManager).clear(); - } - - /** * Verify that a call to factoryReset throws a SecurityException if the caller does not have * the CONNECTIVITY_INTERNAL permission. */ @@ -3918,6 +3878,24 @@ public class WifiServiceImplTest { } /** + * Ensure that we invoke {@link WifiNetworkSuggestionsManager} to get network + * suggestions. + */ + @Test + public void testGetNetworkSuggestions() { + setupClientModeImplHandlerForRunWithScissors(); + List<WifiNetworkSuggestion> testList = new ArrayList<>(); + when(mWifiNetworkSuggestionsManager.get(anyString())).thenReturn(testList); + assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME)); + + doReturn(false).when(mHandlerSpyForCmiRunWithScissors) + .runWithScissors(any(), anyLong()); + assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME)); + + verify(mWifiNetworkSuggestionsManager, times(1)).get(eq(TEST_PACKAGE_NAME)); + } + + /** * Verify that if the caller has NETWORK_SETTINGS permission, then it can invoke * {@link WifiManager#disableEphemeralNetwork(String)}. */ diff --git a/service/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java b/service/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java index ca48f38aea..65ae968c4b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java @@ -880,12 +880,6 @@ public class WificondControlTest { pnoScanEvent.OnPnoScanFailed(); verify(mWifiMetrics).incrementPnoScanFailedCount(); - - pnoScanEvent.OnPnoScanOverOffloadStarted(); - verify(mWifiMetrics).incrementPnoScanStartedOverOffloadCount(); - - pnoScanEvent.OnPnoScanOverOffloadFailed(0); - verify(mWifiMetrics).incrementPnoScanFailedOverOffloadCount(); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java index f2cc45fefd..647f11d213 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java @@ -163,6 +163,7 @@ public class WifiAwareDataPathStateManagerTest { // allows older (more extrensive) tests to run. when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), anyInt())).thenReturn(true); when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); mDut = new WifiAwareStateManager(); mDut.setNative(mMockNativeManager, mMockNative); diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java index 140e7e43c5..f6240c8a4a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java @@ -18,6 +18,7 @@ package com.android.server.wifi.aware; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; @@ -289,5 +290,9 @@ public class WifiAwareNativeManagerTest { any()); mInOrder.verify(mIWifiNanIface12Mock).registerEventCallback_1_2(any()); assertEquals("Interface mismatch", mIWifiNanIface12Mock, mDut.getWifiNanIface()); + + // 3. receive Availability Change, has interface, should ignore + mAvailListenerCaptor.getValue().onAvailabilityChanged(false); + assertTrue("AwareNativeAvailable mismatch ", mDut.isAwareNativeAvailable()); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java index 1204c4f815..f95157346b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java @@ -553,8 +553,8 @@ public class WifiAwareServiceImplTest { mDut.sendMessage(clientId, sessionId, peerId, message, messageId, 0); - verify(mAwareStateManagerMock).sendMessage(clientId, sessionId, peerId, message, messageId, - 0); + verify(mAwareStateManagerMock).sendMessage(anyInt(), eq(clientId), eq(sessionId), + eq(peerId), eq(message), eq(messageId), eq(0)); } /** @@ -570,8 +570,8 @@ public class WifiAwareServiceImplTest { mDut.sendMessage(clientId, sessionId, peerId, message, messageId, 0); - verify(mAwareStateManagerMock).sendMessage(clientId, sessionId, peerId, message, messageId, - 0); + verify(mAwareStateManagerMock).sendMessage(anyInt(), eq(clientId), eq(sessionId), + eq(peerId), eq(message), eq(messageId), eq(0)); } @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java index d6b1b38d14..3d48a23b7b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java @@ -165,6 +165,7 @@ public class WifiAwareStateManagerTest { when(mMockPowerManager.isDeviceIdleMode()).thenReturn(false); when(mMockPowerManager.isInteractive()).thenReturn(true); when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); @@ -1437,8 +1438,8 @@ public class WifiAwareStateManagerTest { peerMsg.getBytes()); // (4) message Tx successful queuing - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); @@ -1447,8 +1448,8 @@ public class WifiAwareStateManagerTest { mMockLooper.dispatchAll(); // (5) message Tx successful queuing - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId2, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId2, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId2)); @@ -1547,7 +1548,7 @@ public class WifiAwareStateManagerTest { int peerId2 = peerIdCaptor.getValue(); // (4) sending messages back to same peers: one Tx fails, other succeeds - mDut.sendMessage(clientId, sessionId.getValue(), peerId2, msgToPeer2.getBytes(), + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId2, msgToPeer2.getBytes(), msgToPeerId2, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), @@ -1556,7 +1557,7 @@ public class WifiAwareStateManagerTest { mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); mDut.onMessageSendSuccessNotification(transactionIdVal); - mDut.sendMessage(clientId, sessionId.getValue(), peerId1, msgToPeer1.getBytes(), + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId1, msgToPeer1.getBytes(), msgToPeerId1, 0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); @@ -1641,8 +1642,8 @@ public class WifiAwareStateManagerTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageReceived(peerId.capture(), eq(msgFromPeer1.getBytes())); - mDut.sendMessage(clientId, sessionId.getValue(), peerId.getValue(), msgToPeer1.getBytes(), - msgToPeerId1, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId.getValue(), + msgToPeer1.getBytes(), msgToPeerId1, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(requestorId), eq(peerMacOrig), eq(msgToPeer1.getBytes()), @@ -1659,8 +1660,8 @@ public class WifiAwareStateManagerTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageReceived(peerId.capture(), eq(msgFromPeer2.getBytes())); - mDut.sendMessage(clientId, sessionId.getValue(), peerId.getValue(), msgToPeer2.getBytes(), - msgToPeerId2, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId.getValue(), + msgToPeer2.getBytes(), msgToPeerId2, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(requestorId), eq(peerMacLater), eq(msgToPeer2.getBytes()), @@ -1732,7 +1733,7 @@ public class WifiAwareStateManagerTest { eq(peerMatchFilter.getBytes())); // (3) send message to invalid peer ID - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue() + 5, + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue() + 5, ssi.getBytes(), messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, @@ -1801,8 +1802,8 @@ public class WifiAwareStateManagerTest { eq(peerMatchFilter.getBytes())); // (3) send 2 messages and enqueue successfully - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); @@ -1810,8 +1811,8 @@ public class WifiAwareStateManagerTest { mDut.onMessageSendQueuedSuccessResponse(transactionId1); mMockLooper.dispatchAll(); - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId + 1, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId + 1, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 1)); @@ -1820,8 +1821,8 @@ public class WifiAwareStateManagerTest { mMockLooper.dispatchAll(); // (4) send a message and get a queueing failure (not queue full) - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId + 2, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId + 2, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 2)); @@ -1836,8 +1837,8 @@ public class WifiAwareStateManagerTest { when(mMockNative.sendMessage(anyShort(), anyByte(), anyInt(), any(), any(), anyInt())).thenReturn(false); - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId + 3, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId + 3, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 3)); @@ -1927,8 +1928,8 @@ public class WifiAwareStateManagerTest { eq(peerMatchFilter.getBytes())); // (3) send message and enqueue successfully - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId, retryCount); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId, retryCount); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); @@ -2014,8 +2015,8 @@ public class WifiAwareStateManagerTest { eq(peerMatchFilter.getBytes())); // (3) send message and enqueue successfully - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), ssi.getBytes(), - messageId, retryCount); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + ssi.getBytes(), messageId, retryCount); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); @@ -2110,7 +2111,7 @@ public class WifiAwareStateManagerTest { int remainingMessages = numberOfMessages; for (int i = 0; i < numberOfMessages; ++i) { - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, messageIdBase + i, 0); mMockLooper.dispatchAll(); // at 1/2 interval have the system simulate transmitting a queued message over-the-air @@ -2137,6 +2138,153 @@ public class WifiAwareStateManagerTest { } /** + * Validate that the message queue depth per process function. Tests the case + * with two processes both have message num larger than queue depth. And all messages get + * into the firmware queue are sent out and are received on first attempt. + */ + @Test + public void testSendMessageQueueLimitBlock() throws Exception { + final int clientId1 = 1005; + final int clientId2 = 1006; + final int uid1 = 1000; + final int uid2 = 1500; + final int pid1 = 2000; + final int pid2 = 3000; + final String callingPackage1 = "com.google.somePackage1"; + final String callingPackage2 = "com.google.somePackage2"; + final String serviceName1 = "some-service-name1"; + final String serviceName2 = "some-service-name2"; + final byte subscribeId1 = 15; + final byte subscribeId2 = 16; + final int requestorId1 = 22; + final int requestorId2 = 23; + final byte[] peerMac1 = HexEncoding.decode("060708090A0B".toCharArray(), false); + final byte[] peerMac2 = HexEncoding.decode("060708090A0C".toCharArray(), false); + final int messageIdBase1 = 6948; + final int messageIdBase2 = 7948; + final int numberOfMessages = 70; + final int queueDepth = 6; + final int messageQueueDepthPerUid = 50; + final int numOfReject = numberOfMessages - messageQueueDepthPerUid; + + ConfigRequest configRequest1 = new ConfigRequest.Builder().build(); + SubscribeConfig subscribeConfig1 = new SubscribeConfig.Builder() + .setServiceName(serviceName1).build(); + ConfigRequest configRequest2 = new ConfigRequest.Builder().build(); + SubscribeConfig subscribeConfig2 = new SubscribeConfig.Builder() + .setServiceName(serviceName2).build(); + + IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); + IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( + IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); + ArgumentCaptor<Integer> sessionId1 = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> sessionId2 = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> messageIdCaptorFail = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> messageIdCaptorSuccess = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> peerIdCaptor1 = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> peerIdCaptor2 = ArgumentCaptor.forClass(Integer.class); + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); + + mDut.enableUsage(); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); + mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); + mMockLooper.dispatchAll(); + + // (0) connect + mDut.connect(clientId1, uid1, pid1, callingPackage1, mockCallback, configRequest1, false); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), + eq(configRequest1), eq(false), eq(true), eq(true), eq(false)); + mDut.onConfigSuccessResponse(transactionId.getValue()); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onConnectSuccess(clientId1); + + mDut.connect(clientId2, uid2, pid2, callingPackage2, mockCallback, configRequest2, false); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onConnectSuccess(clientId2); + + // (1) subscribe + mDut.subscribe(clientId1, subscribeConfig1, mockSessionCallback); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), + eq(subscribeConfig1)); + mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId1); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onSessionStarted(sessionId1.capture()); + + mDut.subscribe(clientId2, subscribeConfig2, mockSessionCallback); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), + eq(subscribeConfig2)); + mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId2); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onSessionStarted(sessionId2.capture()); + + // (2) match + mDut.onMatchNotification(subscribeId1, requestorId1, peerMac1, null, null, 0, 0); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor1.capture(), isNull(), isNull()); + + mDut.onMatchNotification(subscribeId2, requestorId2, peerMac2, null, null, 0, 0); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor2.capture(), isNull(), isNull()); + + // (3) Enqueue messages + SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, + null, null, null); + when(mMockNative.sendMessage(anyShort(), anyByte(), anyInt(), any(), + any(), anyInt())).thenAnswer(answerObj); + + for (int i = 0; i < numberOfMessages; ++i) { + mDut.sendMessage(uid1, clientId1, sessionId1.getValue(), peerIdCaptor1.getValue(), null, + messageIdBase1 + i, 0); + } + for (int i = 0; i < numberOfMessages; ++i) { + mDut.sendMessage(uid2, clientId2, sessionId2.getValue(), peerIdCaptor2.getValue(), null, + messageIdBase2 + i, 0); + } + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback, times(numOfReject * 2)) + .onMessageSendFail(messageIdCaptorFail.capture(), + eq(NanStatusType.INTERNAL_FAILURE)); + + // (4) Transmit messages + int successNum = 0; + for (int i = 0; i < numberOfMessages * 2; ++i) { + if (answerObj.process()) { + successNum++; + } else { + break; + } + mMockLooper.dispatchAll(); + } + assertEquals("queue empty", 0, answerObj.queueSize()); + assertEquals("success message num", messageQueueDepthPerUid * 2, successNum); + inOrder.verify(mockSessionCallback, times(messageQueueDepthPerUid * 2)) + .onMessageSendSuccess(messageIdCaptorSuccess.capture()); + + for (int i = 0; i < numOfReject; ++i) { + assertEquals("message ID: " + i + messageQueueDepthPerUid, + messageIdBase1 + i + messageQueueDepthPerUid, + (int) messageIdCaptorFail.getAllValues().get(i)); + assertEquals("message ID: " + i + messageQueueDepthPerUid, + messageIdBase2 + i + messageQueueDepthPerUid, + (int) messageIdCaptorFail.getAllValues().get(i + numOfReject)); + } + + for (int i = 0; i < messageQueueDepthPerUid; ++i) { + assertEquals("message ID: " + i, messageIdBase1 + i, + (int) messageIdCaptorSuccess.getAllValues().get(i)); + assertEquals("message ID: " + i, messageIdBase2 + i, + (int) messageIdCaptorSuccess.getAllValues().get(i + messageQueueDepthPerUid)); + } + + verifyNoMoreInteractions(mockCallback, mockSessionCallback); + } + + /** * Validate that the host-side message queue functions. A combination of imperfect conditions: * - Failure to queue: synchronous firmware error * - Failure to queue: asyncronous firmware error @@ -2250,7 +2398,7 @@ public class WifiAwareStateManagerTest { any(), anyInt())).thenAnswer(answerObj); for (int i = 0; i < numberOfMessages; ++i) { - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, + mDut.sendMessage(uid + i, clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, messageIdBase + i, retransmitCount); mMockLooper.dispatchAll(); } @@ -2334,8 +2482,8 @@ public class WifiAwareStateManagerTest { eq(peerMatchFilter.getBytes())); // (3) message null Tx successful queuing - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, messageId, - 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + null, messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), isNull(byte[].class), eq(messageId)); @@ -2350,7 +2498,7 @@ public class WifiAwareStateManagerTest { validateInternalSendMessageQueuesCleanedUp(messageId); // (5) message byte[0] Tx successful queuing - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), new byte[0], + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), new byte[0], messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), @@ -2366,8 +2514,8 @@ public class WifiAwareStateManagerTest { validateInternalSendMessageQueuesCleanedUp(messageId); // (7) message "" Tx successful queuing - mDut.sendMessage(clientId, sessionId.getValue(), peerIdCaptor.getValue(), "".getBytes(), - messageId, 0); + mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), + "".getBytes(), messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), byteArrayCaptor.capture(), eq(messageId)); @@ -3126,6 +3274,7 @@ public class WifiAwareStateManagerTest { inOrder.verify(mMockNativeManager).start(any(Handler.class)); mDut.enableUsage(); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); mMockLooper.dispatchAll(); inOrder.verify(mMockNativeManager).tryToGetAware(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); @@ -3165,8 +3314,16 @@ public class WifiAwareStateManagerTest { simulateWifiStateChange(true); mMockLooper.dispatchAll(); + // when WifiAware Native is not available, DOZE OFF -> no change + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(false); + simulatePowerStateChangeDoze(false); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); + // (5) power state change: DOZE OFF simulatePowerStateChangeDoze(false); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); mMockLooper.dispatchAll(); collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); validateCorrectAwareStatusChangeBroadcast(inOrder); @@ -3192,6 +3349,7 @@ public class WifiAwareStateManagerTest { inOrder.verify(mMockNativeManager).start(any(Handler.class)); mDut.enableUsage(); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); mMockLooper.dispatchAll(); inOrder.verify(mMockNativeManager).tryToGetAware(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); @@ -3227,8 +3385,16 @@ public class WifiAwareStateManagerTest { simulateWifiStateChange(true); mMockLooper.dispatchAll(); + // when WifiAware Native is not available, enable location -> no change + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(false); + simulateLocationModeChange(true); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); + mMockLooper.dispatchAll(); + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); + // (4) location mode change: enable simulateLocationModeChange(true); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); mMockLooper.dispatchAll(); collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); validateCorrectAwareStatusChangeBroadcast(inOrder); @@ -3254,6 +3420,7 @@ public class WifiAwareStateManagerTest { inOrder.verify(mMockNativeManager).start(any(Handler.class)); mDut.enableUsage(); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); mMockLooper.dispatchAll(); inOrder.verify(mMockNativeManager).tryToGetAware(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); @@ -3289,8 +3456,16 @@ public class WifiAwareStateManagerTest { simulateLocationModeChange(true); mMockLooper.dispatchAll(); + // when WifiAware Native is not available, enable Wifi -> no change + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(false); + simulateWifiStateChange(true); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); + mMockLooper.dispatchAll(); + when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); + // (4) wifi state change: enable simulateWifiStateChange(true); + inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); mMockLooper.dispatchAll(); collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); validateCorrectAwareStatusChangeBroadcast(inOrder); |