diff options
27 files changed, 723 insertions, 472 deletions
diff --git a/apex/Android.bp b/apex/Android.bp index 1278b3040c..a758067a23 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -17,7 +17,6 @@ apex_defaults { name: "com.android.wifi-defaults", androidManifest: ":com.android.wifi-androidManifest", - native_shared_libs: ["libwifi-jni"], java_libs: [ "wifi-service", "framework-wifi", diff --git a/service/Android.bp b/service/Android.bp index e0c886a243..51b11e6591 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -26,43 +26,6 @@ java_defaults { }, } -// Make the JNI part -// ============================================================ -cc_library_shared { - name: "libwifi-jni", - - cflags: [ - "-Wall", - "-Werror", - "-Wextra", - "-Wno-unused-parameter", - "-Wno-unused-function", - "-Wunused-variable", - "-Winit-self", - "-Wwrite-strings", - "-Wshadow", - ], - - shared_libs: [ - "liblog", - "libnativehelper", - "libcutils", - "libutils", - "libdl", - ], - - srcs: [ - "jni/com_android_server_wifi_WifiNative.cpp", - "jni/jni_helper.cpp", - ], - - product_variables: { - pdk: { - enabled: false, - }, - }, -} - filegroup { name: "wifi-service-srcs", srcs: [ @@ -152,7 +115,6 @@ java_library { required: [ "cacerts_wfa", - "libwifi-jni", "services", "wifi-service-resources", ], diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 4ca339af1d..812b2450ec 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -119,6 +119,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; import com.android.server.wifi.util.ExternalCallbackTracker; import com.android.server.wifi.util.NativeUtil; import com.android.server.wifi.util.RssiUtil; +import com.android.server.wifi.util.ScanResultUtil; import com.android.server.wifi.util.TelephonyUtil; import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData; import com.android.server.wifi.util.TelephonyUtil.SimAuthResponseData; @@ -3113,6 +3114,24 @@ public class ClientModeImpl extends StateMachine { mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_STA_IFACE_DOWN); } + /** + * Helper method to check if WPA2 network upgrade feature is enabled in the framework + * + * @return boolean true if feature is enabled. + */ + private boolean isWpa3SaeUpgradeEnabled() { + return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeEnabled); + } + + /** + * Helper method to check if WPA2 network upgrade offload is enabled in the driver/fw + * + * @return boolean true if feature is enabled. + */ + private boolean isWpa3SaeUpgradeOffloadEnabled() { + return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled); + } + /******************************************************** * HSM states *******************************************************/ @@ -3819,6 +3838,11 @@ public class ClientModeImpl extends StateMachine { config.enterpriseConfig.setAnonymousIdentity(anonAtRealm); } + if (isWpa3SaeUpgradeEnabled() && config.allowedKeyManagement.get( + WifiConfiguration.KeyMgmt.WPA_PSK)) { + config = upgradeToWpa3IfPossible(config); + } + if (mWifiNative.connectToNetwork(mInterfaceName, config)) { mWifiInjector.getWifiLastResortWatchdog().noteStartConnectTime(); mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config); @@ -5938,4 +5962,69 @@ public class ClientModeImpl extends StateMachine { mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); } } + + private WifiConfiguration upgradeToWpa3IfPossible(@NonNull WifiConfiguration config) { + if (isWpa3SaeUpgradeOffloadEnabled()) { + // Driver offload of upgrading legacy WPA/WPA2 connection to WPA3 + if (mVerboseLoggingEnabled) { + Log.d(TAG, "Driver upgrade legacy WPA/WPA2 connection to WPA3"); + } + config.allowedAuthAlgorithms.clear(); + // Note: KeyMgmt.WPA2_PSK is already enabled, enable SAE as well + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); + return config; + } + + boolean canUpgradePskToSae = false; + + // Check if network selection selected a good WPA3 candidate AP for a WPA2 + // saved network. + ScanResult scanResultCandidate = config.getNetworkSelectionStatus().getCandidate(); + if (scanResultCandidate != null) { + ScanResultMatchInfo scanResultMatchInfo = ScanResultMatchInfo + .fromScanResult(scanResultCandidate); + if ((scanResultMatchInfo.networkType == WifiConfiguration.SECURITY_TYPE_SAE)) { + canUpgradePskToSae = true; + } else { + // No SAE candidate + return config; + } + } + + // Now check if there are any additional legacy WPA2 only APs in range. + ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy(); + for (ScanResult scanResult : scanRequestProxy.getScanResults()) { + if (!config.SSID.equals(ScanResultUtil.createQuotedSSID(scanResult.SSID))) { + continue; + } + if (ScanResultUtil.isScanResultForPskNetwork(scanResult) + && !ScanResultUtil.isScanResultForSaeNetwork(scanResult)) { + // Found a legacy WPA2 AP in range. Do not upgrade the connection to WPA3 to + // allow seamless roaming within the ESS. + if (mVerboseLoggingEnabled) { + Log.d(TAG, "Found legacy WPA2 AP, do not upgrade to WPA3"); + } + canUpgradePskToSae = false; + break; + } + if (ScanResultUtil.isScanResultForSaeNetwork(scanResult) + && scanResultCandidate == null) { + // When the user manually selected a network from the Wi-Fi picker, evaluate + // if to upgrade based on the scan results. The most typical use case during + // the WPA3 transition mode is to have a WPA2/WPA3 AP in transition mode. In + // this case, we would like to upgrade the connection. + canUpgradePskToSae = true; + } + } + + if (canUpgradePskToSae) { + // Upgrade legacy WPA/WPA2 connection to WPA3 + if (mVerboseLoggingEnabled) { + Log.d(TAG, "Upgrade legacy WPA/WPA2 connection to WPA3"); + } + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + } + + return config; + } } diff --git a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java index 1f26e0c5af..d7d08578f9 100644 --- a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java +++ b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java @@ -104,16 +104,20 @@ public class NetworkSuggestionNominator implements WifiNetworkSelector.NetworkNo for (Pair<ScanDetail, WifiConfiguration> candidate : candidates) { Set<ExtendedWifiNetworkSuggestion> matchingPasspointExtSuggestions = mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForFqdn(candidate.second.FQDN) - .stream() - .filter( - ens -> ens.isAutoJoinEnabled) - .collect(Collectors.toSet()); + .getNetworkSuggestionsForFqdn(candidate.second.FQDN); if (matchingPasspointExtSuggestions == null || matchingPasspointExtSuggestions.isEmpty()) { + mLocalLog.log("Suggestion is missing for passpoint: " + candidate.second.FQDN); continue; } - matchMetaInfo.putAll(matchingPasspointExtSuggestions, + Set<ExtendedWifiNetworkSuggestion> autoJoinEnabledExtSuggestions = + matchingPasspointExtSuggestions.stream() + .filter(ewns -> ewns.isAutoJoinEnabled) + .collect(Collectors.toSet()); + if (autoJoinEnabledExtSuggestions.isEmpty()) { + continue; + } + matchMetaInfo.putAll(autoJoinEnabledExtSuggestions, candidate.second, candidate.first); } } diff --git a/service/java/com/android/server/wifi/ScanResultMatchInfo.java b/service/java/com/android/server/wifi/ScanResultMatchInfo.java index 752de679ce..3c4bf34d53 100644 --- a/service/java/com/android/server/wifi/ScanResultMatchInfo.java +++ b/service/java/com/android/server/wifi/ScanResultMatchInfo.java @@ -45,6 +45,10 @@ public class ScanResultMatchInfo { public boolean oweInTransitionMode; /** + * True if created from a scan result + */ + private boolean mFromScanResult = false; + /** * Fetch network type from network configuration. */ private static @WifiConfiguration.SecurityType int getNetworkType(WifiConfiguration config) { @@ -120,6 +124,7 @@ public class ScanResultMatchInfo { info.networkType = getNetworkType(scanResult); info.oweInTransitionMode = false; info.pskSaeInTransitionMode = false; + info.mFromScanResult = true; if (info.networkType == WifiConfiguration.SECURITY_TYPE_SAE) { // Note that scan result util will always choose the highest security protocol. info.pskSaeInTransitionMode = @@ -135,7 +140,8 @@ public class ScanResultMatchInfo { /** * Checks for equality of network type. */ - public boolean networkTypeEquals(@NonNull ScanResultMatchInfo other) { + public boolean networkTypeEquals(@NonNull ScanResultMatchInfo other, + boolean saeAutoUpgradeEnabled) { boolean networkTypeEquals; // Detect <SSID, PSK+SAE> scan result and say it is equal to <SSID, PSK> configuration if (other.pskSaeInTransitionMode && networkType == WifiConfiguration.SECURITY_TYPE_PSK @@ -148,6 +154,14 @@ public class ScanResultMatchInfo { // Special case we treat Enhanced Open and Open as equals. This is done to support the // case where a saved network is Open but we found an OWE in transition network. networkTypeEquals = true; + } else if ((saeAutoUpgradeEnabled) + && ((mFromScanResult && networkType == WifiConfiguration.SECURITY_TYPE_SAE + && other.networkType == WifiConfiguration.SECURITY_TYPE_PSK) + || (other.mFromScanResult + && other.networkType == WifiConfiguration.SECURITY_TYPE_SAE + && networkType == WifiConfiguration.SECURITY_TYPE_PSK))) { + // Allow upgrading WPA2 PSK connections to WPA3 SAE AP + networkTypeEquals = true; } else { networkTypeEquals = networkType == other.networkType; } @@ -156,6 +170,17 @@ public class ScanResultMatchInfo { @Override public boolean equals(Object otherObj) { + return matchForNetworkSelection(otherObj, false); + } + + /** + * Match two ScanResultMatchInfo objects while considering configuration in overlays + * + * @param otherObj Other object to compare against + * @param saeAutoUpgradeEnabled A boolean that indicates if WPA3 auto upgrade feature is enabled + * @return true if objects are equal for network selection purposes, false otherwise + */ + public boolean matchForNetworkSelection(Object otherObj, boolean saeAutoUpgradeEnabled) { if (this == otherObj) { return true; } else if (!(otherObj instanceof ScanResultMatchInfo)) { @@ -165,7 +190,7 @@ public class ScanResultMatchInfo { if (!Objects.equals(networkSsid, other.networkSsid)) { return false; } - return networkTypeEquals(other); + return networkTypeEquals(other, saeAutoUpgradeEnabled); } @Override @@ -175,6 +200,9 @@ public class ScanResultMatchInfo { @Override public String toString() { - return "ScanResultMatchInfo: ssid: " + networkSsid + ", type: " + networkType; + return "ScanResultMatchInfo: SSID: " + networkSsid + ", type: " + networkType + + ", WPA3 in transition mode: " + pskSaeInTransitionMode + + ", OWE in transition mode: " + oweInTransitionMode + ", from scan result: " + + mFromScanResult; } } diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java index 1f6ed8dee7..13296010d0 100644 --- a/service/java/com/android/server/wifi/WifiCandidates.java +++ b/service/java/com/android/server/wifi/WifiCandidates.java @@ -18,6 +18,7 @@ package com.android.server.wifi; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.net.MacAddress; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; @@ -25,6 +26,7 @@ import android.util.ArrayMap; import com.android.internal.util.Preconditions; import com.android.server.wifi.proto.WifiScoreCardProto; +import com.android.wifi.resources.R; import java.util.ArrayList; import java.util.Collection; @@ -38,10 +40,12 @@ import java.util.StringJoiner; public class WifiCandidates { private static final String TAG = "WifiCandidates"; - WifiCandidates(@NonNull WifiScoreCard wifiScoreCard) { + WifiCandidates(@NonNull WifiScoreCard wifiScoreCard, @NonNull Context context) { mWifiScoreCard = Preconditions.checkNotNull(wifiScoreCard); + mContext = context; } private final WifiScoreCard mWifiScoreCard; + private final Context mContext; /** * Represents a connectable candidate. @@ -387,7 +391,8 @@ public class WifiCandidates { ScanResultMatchInfo key1 = ScanResultMatchInfo.fromScanResult(scanResult); if (!config.isPasspoint()) { ScanResultMatchInfo key2 = ScanResultMatchInfo.fromWifiConfiguration(config); - if (!key1.equals(key2)) { + if (!key1.matchForNetworkSelection(key2, mContext.getResources() + .getBoolean(R.bool.config_wifiSaeUpgradeEnabled))) { return failure(key1, key2); } } diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index a80e3df3e6..bbec2f3556 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -153,9 +153,6 @@ public class WifiConnectivityManager { private boolean mScreenOn = false; private int mWifiState = WIFI_STATE_UNKNOWN; private int mInitialScanState = INITIAL_SCAN_STATE_COMPLETE; - private boolean mEnablePartialInitialScan = false; - private int mInitialScanChannelMaxCount; - private long mInitialScanChannelMaxAgeInMillis; private boolean mAutoJoinEnabledExternal = true; // enabled by default private boolean mUntrustedConnectionAllowed = false; private boolean mTrustedConnectionAllowed = false; @@ -796,8 +793,11 @@ public class WifiConnectivityManager { WifiConfiguration config = mStateMachine.getCurrentWifiConfiguration(); if (config == null) { - freqs = mConfigManager.fetchChannelSetForPartialScan(mInitialScanChannelMaxAgeInMillis, - mInitialScanChannelMaxCount); + long ageInMillis = 1000 * 60 * mContext.getResources().getInteger( + R.integer.config_wifiInitialPartialScanChannelCacheAgeMins); + int maxCount = mContext.getResources().getInteger( + R.integer.config_wifiInitialPartialScanChannelMaxCount); + freqs = mConfigManager.fetchChannelSetForPartialScan(ageInMillis, maxCount); } else { freqs = mConfigManager.fetchChannelSetForNetworkForPartialScan( config.networkId, CHANNEL_LIST_AGE_MS, mWifiInfo.getFrequency()); @@ -1224,7 +1224,8 @@ public class WifiConnectivityManager { mScreenOn = screenOn; - if (mWifiState == WIFI_STATE_DISCONNECTED && mEnablePartialInitialScan) { + if (mWifiState == WIFI_STATE_DISCONNECTED + && mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) { setInitialScanState(INITIAL_SCAN_STATE_START); } @@ -1445,14 +1446,7 @@ public class WifiConnectivityManager { mBssidBlocklistMonitor.clearBssidBlocklist(); mWifiChannelUtilization.init(mStateMachine.getWifiLinkLayerStats()); - mEnablePartialInitialScan = - mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan); - mInitialScanChannelMaxAgeInMillis = 1000 * 60 * mContext.getResources().getInteger( - R.integer.config_wifiInitialPartialScanChannelCacheAgeMins); - mInitialScanChannelMaxCount = mContext.getResources().getInteger( - R.integer.config_wifiInitialPartialScanChannelMaxCount); - - if (mEnablePartialInitialScan) { + if (mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) { setInitialScanState(INITIAL_SCAN_STATE_START); } diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java index 3e22d863fd..f047f3273f 100644 --- a/service/java/com/android/server/wifi/WifiDiagnostics.java +++ b/service/java/com/android/server/wifi/WifiDiagnostics.java @@ -315,7 +315,7 @@ class WifiDiagnostics extends BaseWifiDiagnostics { byte[] fwMemoryDump; byte[] mDriverStateDump; byte[] alertData; - LimitedCircularArray<String> kernelLogLines; + ArrayList<String> kernelLogLines; ArrayList<String> logcatLines; void clearVerboseLogs() { @@ -634,8 +634,8 @@ class WifiDiagnostics extends BaseWifiDiagnostics { } } - report.logcatLines = getLogcat(127); - report.kernelLogLines = getKernelLog(127); + report.logcatLines = getLogcatSystem(127); + report.kernelLogLines = getLogcatKernel(127); if (captureFWDump) { report.fwMemoryDump = mWifiNative.getFwMemoryDump(); @@ -694,10 +694,11 @@ class WifiDiagnostics extends BaseWifiDiagnostics { return result; } - private ArrayList<String> getLogcat(int maxLines) { - ArrayList<String> lines = new ArrayList<String>(maxLines); + private ArrayList<String> getLogcat(String logcatSections, int maxLines) { + ArrayList<String> lines = new ArrayList<>(maxLines); try { - Process process = mJavaRuntime.exec(String.format("logcat -t %d", maxLines)); + Process process = mJavaRuntime.exec( + String.format("logcat -b %s -t %d", logcatSections, maxLines)); BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream())); String line; @@ -714,18 +715,15 @@ class WifiDiagnostics extends BaseWifiDiagnostics { mLog.dump("Exception while capturing logcat: %").c(e.toString()).flush(); } return lines; + } - private LimitedCircularArray<String> getKernelLog(int maxLines) { - if (DBG) mLog.tC("Reading kernel log ..."); - LimitedCircularArray<String> lines = new LimitedCircularArray<String>(maxLines); - String log = mWifiNative.readKernelLog(); - String logLines[] = log.split("\n"); - for (int i = 0; i < logLines.length; i++) { - lines.addLast(logLines[i]); - } - if (DBG) mLog.dump("Added % lines").c(logLines.length).flush(); - return lines; + private ArrayList<String> getLogcatSystem(int maxLines) { + return getLogcat("main,system,crash", maxLines); + } + + private ArrayList<String> getLogcatKernel(int maxLines) { + return getLogcat("kernel", maxLines); } /** Packet fate reporting */ diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index cf953e76ba..6d0aaa8791 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -54,10 +54,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -80,7 +76,6 @@ import java.util.TimeZone; */ public class WifiNative { private static final String TAG = "WifiNative"; - private static final String JNI_LIB = "/apex/com.android.wifi/lib64/libwifi-jni.so"; private final SupplicantStaIfaceHal mSupplicantStaIfaceHal; private final HostapdHal mHostapdHal; @@ -3491,44 +3486,4 @@ public class WifiNative { return iface.phyCapabilities.isWifiStandardSupported(standard); } } - - /******************************************************** - * JNI operations - ********************************************************/ - /* Register native functions */ - static { - /* Native functions are defined in libwifi-jni.so */ - try { - System.load(JNI_LIB); - registerNatives(); - } catch (UnsatisfiedLinkError e) { - Log.e(TAG, "Failed to load jni library", e); - } - } - - private static native int registerNatives(); - /* kernel logging support */ - private static native byte[] readKernelLogNative(); - - /** - * Fetches the latest kernel logs. - */ - public synchronized String readKernelLog() { - try { - byte[] bytes = readKernelLogNative(); - if (bytes != null) { - CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); - try { - CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes)); - return decoded.toString(); - } catch (CharacterCodingException cce) { - return new String(bytes, StandardCharsets.ISO_8859_1); - } - } - } catch (UnsatisfiedLinkError e) { - // TODO (b/145196311): Fix this linker error. - Log.e(TAG, "Failed to load jni library", e); - } - return "*** failed to read kernel log ***"; - } } diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index 59b4a284ed..70ca7be4c6 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -1105,7 +1105,7 @@ public class WifiNetworkFactory extends NetworkFactory { ScanResultMatchInfo fromScanResult = ScanResultMatchInfo.fromScanResult(scanResult); ScanResultMatchInfo fromWifiConfiguration = ScanResultMatchInfo.fromWifiConfiguration(wns.wifiConfiguration); - return fromScanResult.networkTypeEquals(fromWifiConfiguration); + return fromScanResult.networkTypeEquals(fromWifiConfiguration, false); } // Loops through the scan results and finds scan results matching the active network diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java index 3d6668a031..f8edff1e51 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -710,7 +710,7 @@ public class WifiNetworkSelector { final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork(); final double lastSelectionWeight = calculateLastSelectionWeight(); - WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard); + WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard, mContext); if (currentNetwork != null) { wifiCandidates.setCurrent(currentNetwork.networkId, currentBssid); } diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index 851d6ce006..4ae1378ae6 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -660,7 +660,11 @@ public class WifiNetworkSuggestionsManager { Log.w(TAG, "Empty list of network suggestions for " + packageName + ". Ignoring"); return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; } - if (!validateNetworkSuggestions(networkSuggestions, uid, packageName)) { + if (!validateNetworkSuggestions(networkSuggestions)) { + Log.e(TAG, "Invalid suggestion from app: " + packageName); + return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID; + } + if (!validateCarrierNetworkSuggestions(networkSuggestions, uid, packageName)) { Log.e(TAG, "bad wifi suggestion from app: " + packageName); return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED; } @@ -736,8 +740,24 @@ public class WifiNetworkSuggestionsManager { return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; } - private boolean validateNetworkSuggestions(List<WifiNetworkSuggestion> networkSuggestions, - int uid, String packageName) { + private boolean validateNetworkSuggestions(List<WifiNetworkSuggestion> networkSuggestions) { + for (WifiNetworkSuggestion wns : networkSuggestions) { + if (wns.passpointConfiguration == null) { + if (!WifiConfigurationUtil.validate(wns.wifiConfiguration, + WifiConfigurationUtil.VALIDATE_FOR_ADD)) { + return false; + } + } else { + if (!wns.passpointConfiguration.validate()) { + return false; + } + } + } + return true; + } + + private boolean validateCarrierNetworkSuggestions( + List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) { if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid) || mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(packageName) != TelephonyManager.UNKNOWN_CARRIER_ID) { diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java index 559ebeea1e..63e7a340cb 100644 --- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java +++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java @@ -313,12 +313,14 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { switch (msg.what) { case WifiScanner.CMD_ENABLE: + Log.i(TAG, "Received a request to enable scanning, UID = " + msg.sendingUid); setupScannerImpls(); mBackgroundScanStateMachine.sendMessage(Message.obtain(msg)); mSingleScanStateMachine.sendMessage(Message.obtain(msg)); mPnoScanStateMachine.sendMessage(Message.obtain(msg)); break; case WifiScanner.CMD_DISABLE: + Log.i(TAG, "Received a request to disable scanning, UID = " + msg.sendingUid); teardownScannerImpls(); mBackgroundScanStateMachine.sendMessage(Message.obtain(msg)); mSingleScanStateMachine.sendMessage(Message.obtain(msg)); diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/util/TelephonyUtil.java index 30ccefecfd..95f01a8bcc 100644 --- a/service/java/com/android/server/wifi/util/TelephonyUtil.java +++ b/service/java/com/android/server/wifi/util/TelephonyUtil.java @@ -28,6 +28,7 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.pps.Credential; import android.os.Handler; +import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.ImsiEncryptionInfo; import android.telephony.SubscriptionInfo; @@ -169,17 +170,19 @@ public class TelephonyUtil { } for (SubscriptionInfo subInfo : activeSubInfos) { int subId = subInfo.getSubscriptionId(); - if ((carrierConfigManager.getConfigForSubId(subId) - .getInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT) + PersistableBundle bundle = carrierConfigManager.getConfigForSubId(subId); + if (bundle != null) { + if ((bundle.getInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT) & TelephonyManager.KEY_TYPE_WLAN) != 0) { - vlogd("IMSI encryption is required for " + subId); - mImsiEncryptionRequired.put(subId, true); - } - - if ((carrierConfigManager.getConfigForSubId(subId) - .getBoolean(CarrierConfigManager.ENABLE_EAP_METHOD_PREFIX_BOOL))) { - vlogd("EAP Prefix is required for " + subId); - mEapMethodPrefixEnable.put(subId, true); + vlogd("IMSI encryption is required for " + subId); + mImsiEncryptionRequired.put(subId, true); + } + if (bundle.getBoolean(CarrierConfigManager.ENABLE_EAP_METHOD_PREFIX_BOOL)) { + vlogd("EAP Prefix is required for " + subId); + mEapMethodPrefixEnable.put(subId, true); + } + } else { + Log.e(TAG, "Carrier config is missing for: " + subId); } try { diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp deleted file mode 100644 index 262357ac65..0000000000 --- a/service/jni/com_android_server_wifi_WifiNative.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "wifi-jni" - -#include <ctype.h> -#include <stdlib.h> -#include <sys/klog.h> - -#include <log/log.h> -#include <jni.h> -#include <nativehelper/jni_macros.h> -#include <nativehelper/JNIHelp.h> - -#include "jni_helper.h" - -namespace android { - - -static jbyteArray android_net_wifi_readKernelLogNative(JNIEnv *env, jclass cls) { - JNIHelper helper(env); - ALOGV("Reading kernel logs"); - - int size = klogctl(/* SYSLOG_ACTION_SIZE_BUFFER */ 10, 0, 0); - if (size < 1) { - ALOGD("no kernel logs"); - return helper.newByteArray(0).detach(); - } - - char *buf = (char *)malloc(size); - if (buf == NULL) { - ALOGD("can't allocate temporary storage"); - return helper.newByteArray(0).detach(); - } - - int read = klogctl(/* SYSLOG_ACTION_READ_ALL */ 3, buf, size); - if (read < 0) { - ALOGD("can't read logs - %d", read); - free(buf); - return helper.newByteArray(0).detach(); - } else { - ALOGV("read %d bytes", read); - } - - if (read != size) { - ALOGV("read %d bytes, expecting %d", read, size); - } - - JNIObject<jbyteArray> result = helper.newByteArray(read); - if (result.isNull()) { - ALOGD("can't allocate array"); - free(buf); - return result.detach(); - } - - helper.setByteArrayRegion(result, 0, read, (jbyte*)buf); - free(buf); - return result.detach(); -} - -// ---------------------------------------------------------------------------- - -/* - * JNI registration. - */ -static JNINativeMethod gWifiMethods[] = { - NATIVE_METHOD(android_net_wifi, readKernelLogNative, "()[B"), -}; - -/* User to register native functions */ -extern "C" -jint Java_com_android_server_wifi_WifiNative_registerNatives(JNIEnv* env, jclass clazz) { - return jniRegisterNativeMethods(env, - "com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods)); -} - -}; // namespace android diff --git a/service/jni/jni_helper.cpp b/service/jni/jni_helper.cpp deleted file mode 100644 index 60110c942d..0000000000 --- a/service/jni/jni_helper.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2016, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "wifi" - -#include <hardware_legacy/wifi_hal.h> -#include <nativehelper/ScopedUtfChars.h> -#include <utils/Log.h> -#include <utils/String16.h> -#include <utils/misc.h> - -#include "jni_helper.h" - -namespace android { - -/* JNI Helpers for wifi_hal implementation */ - -JNIHelper::JNIHelper(JavaVM *vm) -{ - vm->AttachCurrentThread(&mEnv, NULL); - mVM = vm; -} - -JNIHelper::JNIHelper(JNIEnv *env) -{ - mVM = NULL; - mEnv = env; -} - -JNIHelper::~JNIHelper() -{ - if (mVM != NULL) { - // mVM->DetachCurrentThread(); /* 'attempting to detach while still running code' */ - mVM = NULL; /* not really required; but may help debugging */ - mEnv = NULL; /* not really required; but may help debugging */ - } -} - -jobject JNIHelper::newLocalRef(jobject obj) { - return mEnv->NewLocalRef(obj); -} - -void JNIHelper::deleteLocalRef(jobject obj) { - mEnv->DeleteLocalRef(obj); -} - -JNIObject<jbyteArray> JNIHelper::newByteArray(int num) { - return JNIObject<jbyteArray>(*this, mEnv->NewByteArray(num)); -} - -void JNIHelper::setByteArrayRegion(jbyteArray array, int from, int to, const jbyte *bytes) { - mEnv->SetByteArrayRegion(array, from, to, bytes); -} -}; // namespace android diff --git a/service/jni/jni_helper.h b/service/jni/jni_helper.h deleted file mode 100644 index 82b5c70043..0000000000 --- a/service/jni/jni_helper.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2016, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <jni.h> - -namespace android { - -/* JNI Helpers for wifi_hal to WifiNative bridge implementation */ - -class JNIHelper; - -template<typename T> -class JNIObject { -protected: - JNIHelper &mHelper; - T mObj; -public: - JNIObject(JNIHelper &helper, T obj); - JNIObject(const JNIObject<T>& rhs); - virtual ~JNIObject(); - JNIHelper& getHelper() const { - return mHelper; - } - T get() const { - return mObj; - } - operator T() const { - return mObj; - } - bool isNull() const { - return mObj == NULL; - } - void release(); - T detach() { - T tObj = mObj; - mObj = NULL; - return tObj; - } - T clone(); - JNIObject<T>& operator = (const JNIObject<T>& rhs) { - release(); - mHelper = rhs.mHelper; - mObj = rhs.mObj; - return *this; - } - void print() { - ALOGD("holding %p", mObj); - } - -private: - template<typename T2> - JNIObject(const JNIObject<T2>& rhs); // NOLINT(implicit) -}; - -class JNIHelper { - JavaVM *mVM; - JNIEnv *mEnv; - -public : - explicit JNIHelper(JavaVM *vm); - explicit JNIHelper(JNIEnv *env); - ~JNIHelper(); - - /* helpers to deal with static members */ - JNIObject<jbyteArray> newByteArray(int num); - void setByteArrayRegion(jbyteArray array, int from, int to, const jbyte *bytes); - -private: - /* Jni wrappers */ - friend class JNIObject<jbyteArray>; - jobject newLocalRef(jobject obj); - void deleteLocalRef(jobject obj); -}; - -template<typename T> -JNIObject<T>::JNIObject(JNIHelper &helper, T obj) - : mHelper(helper), mObj(obj) -{ } - -template<typename T> -JNIObject<T>::JNIObject(const JNIObject<T>& rhs) - : mHelper(rhs.mHelper), mObj(NULL) -{ - mObj = (T)mHelper.newLocalRef(rhs.mObj); -} - -template<typename T> -JNIObject<T>::~JNIObject() { - release(); -} - -template<typename T> -void JNIObject<T>::release() -{ - if (mObj != NULL) { - mHelper.deleteLocalRef(mObj); - mObj = NULL; - } -} - -template<typename T> -T JNIObject<T>::clone() -{ - return mHelper.newLocalRef(mObj); -} -} - -#define THROW(env, message) (env).throwException(message, __LINE__) diff --git a/service/res/values/config.xml b/service/res/values/config.xml index d6f25325c2..f9c272a536 100644 --- a/service/res/values/config.xml +++ b/service/res/values/config.xml @@ -347,4 +347,10 @@ <!-- Integer indicating the RSSI and link layer stats polling interval in milliseconds when device is connected and screen is on --> <integer translatable="false" name="config_wifiPollRssiIntervalMilliseconds">3000</integer> + + <!-- Enable WPA2 to WPA3 auto-upgrade --> + <bool translatable="false" name="config_wifiSaeUpgradeEnabled">true</bool> + + <!-- Enable WPA2 to WPA3 auto-upgrade offload to capable Driver/Firmware --> + <bool translatable="false" name="config_wifiSaeUpgradeOffloadEnabled">false</bool> </resources> diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml index be8eaf25b6..d76d5a60ef 100644 --- a/service/res/values/overlayable.xml +++ b/service/res/values/overlayable.xml @@ -109,6 +109,8 @@ <item type="bool" name="config_wifiSuspendOptimizationsEnabled" /> <item type="integer" name="config_wifiRttBackgroundExecGapMs" /> <item type="integer" name="config_wifiPollRssiIntervalMilliseconds" /> + <item type="bool" name="config_wifiSaeUpgradeEnabled" /> + <item type="bool" name="config_wifiSaeUpgradeOffloadEnabled" /> <!-- Params from config.xml that can be overlayed --> <!-- Params from strings.xml that can be overlayed --> diff --git a/service/tests/wifitests/Android.bp b/service/tests/wifitests/Android.bp index e9bb540336..0b1bcda5aa 100644 --- a/service/tests/wifitests/Android.bp +++ b/service/tests/wifitests/Android.bp @@ -94,7 +94,6 @@ android_test { // These must be explicitly included because they are not normally accessible // from apps. jni_libs: [ - "libwifi-jni", "libbase", "libc++", "ld-android", 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 bca7b8eaeb..6f838d143f 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -103,6 +103,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; import com.android.server.wifi.util.RssiUtilTest; +import com.android.server.wifi.util.ScanResultUtil; import com.android.server.wifi.util.TelephonyUtil; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.server.wifi.util.WifiPermissionsWrapper; @@ -124,8 +125,10 @@ import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; @@ -385,6 +388,7 @@ public class ClientModeImplTest extends WifiBaseTest { @Mock ConnectionFailureNotifier mConnectionFailureNotifier; @Mock EapFailureNotifier mEapFailureNotifier; @Mock ThroughputPredictor mThroughputPredictor; + @Mock ScanRequestProxy mScanRequestProxy; final ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> mConfigUpdateListenerCaptor = ArgumentCaptor.forClass(WifiConfigManager.OnNetworkUpdateListener.class); @@ -445,6 +449,7 @@ public class ClientModeImplTest extends WifiBaseTest { .thenReturn(mConnectionFailureNotifier); when(mWifiInjector.getBssidBlocklistMonitor()).thenReturn(mBssidBlocklistMonitor); when(mWifiInjector.getThroughputPredictor()).thenReturn(mThroughputPredictor); + when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any())) .thenReturn(Pair.create(Process.INVALID_UID, "")); when(mWifiNative.initialize()).thenReturn(true); @@ -4166,4 +4171,294 @@ public class ClientModeImplTest extends WifiBaseTest { mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 7000); assertEquals(6000, mCmi.getPollRssiIntervalMsecs()); } + + /** + * Verifies that the logic does not modify PSK key management when WPA3 auto upgrade feature is + * disabled. + * + * @throws Exception + */ + @Test + public void testNoWpa3UpgradeWhenOverlaysAreOff() throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + WifiConfiguration config = mock(WifiConfiguration.class); + BitSet allowedKeyManagement = mock(BitSet.class); + config.allowedKeyManagement = allowedKeyManagement; + when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))).thenReturn( + true); + when(config.getNetworkSelectionStatus()) + .thenReturn(new WifiConfiguration.NetworkSelectionStatus()); + when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, false); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); + + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); + } + + /** + * Verifies that the logic always enables SAE key management when WPA3 auto upgrade offload + * feature is enabled. + * + * @throws Exception + */ + @Test + public void testWpa3UpgradeOffload() throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + WifiConfiguration config = mock(WifiConfiguration.class); + BitSet allowedKeyManagement = mock(BitSet.class); + BitSet allowedAuthAlgorithms = mock(BitSet.class); + config.allowedKeyManagement = allowedKeyManagement; + config.allowedAuthAlgorithms = allowedAuthAlgorithms; + when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))).thenReturn( + true); + when(config.getNetworkSelectionStatus()) + .thenReturn(new WifiConfiguration.NetworkSelectionStatus()); + when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, true); + + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(allowedKeyManagement).set(eq(WifiConfiguration.KeyMgmt.SAE)); + verify(allowedAuthAlgorithms).clear(); + } + + /** + * Verifies that the logic does not enable SAE key management when WPA3 auto upgrade feature is + * enabled but no SAE candidate is available. + * + * @throws Exception + */ + @Test + public void testNoWpa3UpgradeWithPskCandidate() throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + WifiConfiguration config = mock(WifiConfiguration.class); + BitSet allowedKeyManagement = mock(BitSet.class); + config.allowedKeyManagement = allowedKeyManagement; + when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) + .thenReturn(true); + WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); + when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); + + String ssid = "WPA2-Network"; + String caps = "[WPA2-FT/PSK+PSK][ESS][WPS]"; + ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, + "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, + 0, true); + scanResult.informationElements = new ScanResult.InformationElement[]{ + createIE(ScanResult.InformationElement.EID_SSID, + ssid.getBytes(StandardCharsets.UTF_8)) + }; + when(networkSelectionStatus.getCandidate()).thenReturn(scanResult); + + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); + } + + /** + * Verifies that the logic enables SAE key management when WPA3 auto upgrade feature is + * enabled and an SAE candidate is available. + * + * @throws Exception + */ + @Test + public void testWpa3UpgradeWithSaeCandidate() throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + WifiConfiguration config = mock(WifiConfiguration.class); + BitSet allowedKeyManagement = mock(BitSet.class); + BitSet allowedAuthAlgorithms = mock(BitSet.class); + BitSet allowedProtocols = mock(BitSet.class); + BitSet allowedPairwiseCiphers = mock(BitSet.class); + BitSet allowedGroupCiphers = mock(BitSet.class); + config.allowedKeyManagement = allowedKeyManagement; + config.allowedAuthAlgorithms = allowedAuthAlgorithms; + config.allowedProtocols = allowedProtocols; + config.allowedPairwiseCiphers = allowedPairwiseCiphers; + config.allowedGroupCiphers = allowedGroupCiphers; + when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) + .thenReturn(true); + WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); + when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); + when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())).thenReturn(null); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); + + final String ssid = "WPA3-Network"; + String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]"; + ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, + "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, + 0, true); + scanResult.informationElements = new ScanResult.InformationElement[]{ + createIE(ScanResult.InformationElement.EID_SSID, + ssid.getBytes(StandardCharsets.UTF_8)) + }; + when(networkSelectionStatus.getCandidate()).thenReturn(scanResult); + + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(config).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); + } + + /** + * Verifies that the logic does not enable SAE key management when WPA3 auto upgrade feature is + * enabled and an SAE candidate is available, while another WPA2 AP is in range. + * + * @throws Exception + */ + @Test + public void testWpa3UpgradeWithSaeCandidateAndPskApInRange() throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + WifiConfiguration config = mock(WifiConfiguration.class); + BitSet allowedKeyManagement = mock(BitSet.class); + BitSet allowedAuthAlgorithms = mock(BitSet.class); + BitSet allowedProtocols = mock(BitSet.class); + BitSet allowedPairwiseCiphers = mock(BitSet.class); + BitSet allowedGroupCiphers = mock(BitSet.class); + config.allowedKeyManagement = allowedKeyManagement; + config.allowedAuthAlgorithms = allowedAuthAlgorithms; + config.allowedProtocols = allowedProtocols; + config.allowedPairwiseCiphers = allowedPairwiseCiphers; + config.allowedGroupCiphers = allowedGroupCiphers; + when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) + .thenReturn(true); + WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); + when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); + when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())).thenReturn(null); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); + + final String saeBssid = "ab:cd:01:ef:45:89"; + final String pskBssid = "ab:cd:01:ef:45:9a"; + + final String ssidSae = "Mixed-Network"; + config.SSID = ScanResultUtil.createQuotedSSID(ssidSae); + config.networkId = 1; + + String capsSae = "[WPA2-FT/SAE+SAE][ESS][WPS]"; + ScanResult scanResultSae = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidSae), ssidSae, + saeBssid, 1245, 0, capsSae, -78, 2412, 1025, 22, 33, 20, 0, + 0, true); + ScanResult.InformationElement ieSae = createIE(ScanResult.InformationElement.EID_SSID, + ssidSae.getBytes(StandardCharsets.UTF_8)); + scanResultSae.informationElements = new ScanResult.InformationElement[]{ieSae}; + when(networkSelectionStatus.getCandidate()).thenReturn(scanResultSae); + ScanResult.InformationElement[] ieArr = new ScanResult.InformationElement[1]; + ieArr[0] = ieSae; + + final String ssidPsk = "Mixed-Network"; + String capsPsk = "[WPA2-FT/PSK+PSK][ESS][WPS]"; + ScanResult scanResultPsk = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidPsk), ssidPsk, + pskBssid, 1245, 0, capsPsk, -48, 2462, 1025, 22, 33, 20, 0, + 0, true); + ScanResult.InformationElement iePsk = createIE(ScanResult.InformationElement.EID_SSID, + ssidPsk.getBytes(StandardCharsets.UTF_8)); + scanResultPsk.informationElements = new ScanResult.InformationElement[]{iePsk}; + ScanResult.InformationElement[] ieArrPsk = new ScanResult.InformationElement[1]; + ieArrPsk[0] = iePsk; + List<ScanResult> scanResults = new ArrayList<>(); + scanResults.add(scanResultPsk); + scanResults.add(scanResultSae); + + when(mScanRequestProxy.getScanResults()).thenReturn(scanResults); + + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); + } + + /** + * Verifies that the logic enables SAE key management when WPA3 auto upgrade feature is + * enabled and no candidate is available (i.e. user selected a WPA2 saved network and the + * network is actually WPA3. + * + * @throws Exception + */ + @Test + public void testWpa3UpgradeWithNoCandidate() throws Exception { + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + WifiConfiguration config = mock(WifiConfiguration.class); + BitSet allowedKeyManagement = mock(BitSet.class); + BitSet allowedAuthAlgorithms = mock(BitSet.class); + BitSet allowedProtocols = mock(BitSet.class); + BitSet allowedPairwiseCiphers = mock(BitSet.class); + BitSet allowedGroupCiphers = mock(BitSet.class); + config.allowedKeyManagement = allowedKeyManagement; + config.allowedAuthAlgorithms = allowedAuthAlgorithms; + config.allowedProtocols = allowedProtocols; + config.allowedPairwiseCiphers = allowedPairwiseCiphers; + config.allowedGroupCiphers = allowedGroupCiphers; + when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) + .thenReturn(true); + WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); + when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); + + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); + + final String saeBssid = "ab:cd:01:ef:45:89"; + final String ssidSae = "WPA3-Network"; + config.SSID = ScanResultUtil.createQuotedSSID(ssidSae); + config.networkId = 1; + + String capsSae = "[WPA2-FT/SAE+SAE][ESS][WPS]"; + ScanResult scanResultSae = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidSae), ssidSae, + saeBssid, 1245, 0, capsSae, -78, 2412, 1025, 22, 33, 20, 0, + 0, true); + ScanResult.InformationElement ieSae = createIE(ScanResult.InformationElement.EID_SSID, + ssidSae.getBytes(StandardCharsets.UTF_8)); + scanResultSae.informationElements = new ScanResult.InformationElement[]{ieSae}; + when(networkSelectionStatus.getCandidate()).thenReturn(null); + List<ScanResult> scanResults = new ArrayList<>(); + scanResults.add(scanResultSae); + + when(mScanRequestProxy.getScanResults()).thenReturn(scanResults); + + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(config).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); + } + + private static ScanResult.InformationElement createIE(int id, byte[] bytes) { + ScanResult.InformationElement ie = new ScanResult.InformationElement(); + ie.id = id; + ie.bytes = bytes; + return ie; + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java b/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java index 1cc7fa83fc..ba9adc3acf 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java @@ -18,7 +18,6 @@ package com.android.server.wifi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; import android.net.wifi.WifiConfiguration; @@ -26,6 +25,7 @@ import androidx.test.filters.SmallTest; import org.junit.Test; + /** * Unit tests for {@link com.android.server.wifi.ScanResultMatchInfoTest}. */ @@ -225,4 +225,95 @@ public class ScanResultMatchInfoTest extends WifiBaseTest { return WifiConfigurationTestUtil.createScanDetailForWpa2Wpa3TransitionModeNetwork( configuration, bssid, -40, 2402, 0, 0); } + + /** + * Tests equality properties for PSK to SAE upgrades + */ + @Test + public void testEqualityRulesForPskToSaeUpgrade() { + WifiConfiguration wifiConfigurationSae = + WifiConfigurationTestUtil.createSaeNetwork("\"Upgrade\""); + WifiConfiguration wifiConfigurationPsk = + WifiConfigurationTestUtil.createPskNetwork("\"Upgrade\""); + ScanDetail scanDetailSae = createScanDetailForNetwork(wifiConfigurationSae, + "AC:AB:AD:AE:AF:FC"); + + ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationPsk); + ScanResultMatchInfo key2 = ScanResultMatchInfo + .fromScanResult(scanDetailSae.getScanResult()); + ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); + + // Test a.equals(a) + assertTrue(key1.matchForNetworkSelection(key1, true)); + + // Test if a.equals(b) then b.equals(a) + assertTrue(key1.matchForNetworkSelection(key2, true)); + assertTrue(key2.matchForNetworkSelection(key1, true)); + + // Test consistency + assertTrue(key1.matchForNetworkSelection(key2, true)); + assertTrue(key1.matchForNetworkSelection(key2, true)); + assertTrue(key1.matchForNetworkSelection(key2, true)); + assertTrue(key1.matchForNetworkSelection(key2, true)); + + // Test WifiConfiguration objects are not equal + assertFalse(key1.matchForNetworkSelection(key3, true)); + assertFalse(key3.matchForNetworkSelection(key1, true)); + } + + /** + * Tests equality properties for PSK to SAE upgrades when feature is disabled + */ + @Test + public void testEqualityRulesForPskToSaeUpgradeWithOverlayDisable() { + WifiConfiguration wifiConfigurationSae = + WifiConfigurationTestUtil.createSaeNetwork("\"Upgrade\""); + WifiConfiguration wifiConfigurationPsk = + WifiConfigurationTestUtil.createPskNetwork("\"Upgrade\""); + ScanDetail scanDetailSae = createScanDetailForNetwork(wifiConfigurationSae, + "AC:AB:AD:AE:AF:FC"); + + ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationPsk); + ScanResultMatchInfo key2 = ScanResultMatchInfo + .fromScanResult(scanDetailSae.getScanResult()); + ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); + + // Test a.equals(a) + assertTrue(key1.matchForNetworkSelection(key1, false)); + + // Test if a.equals(b) then b.equals(a) + assertFalse(key1.matchForNetworkSelection(key2, false)); + assertFalse(key2.matchForNetworkSelection(key1, false)); + + // Test consistency + assertFalse(key1.matchForNetworkSelection(key2, false)); + assertFalse(key1.matchForNetworkSelection(key2, false)); + assertFalse(key1.matchForNetworkSelection(key2, false)); + assertFalse(key1.matchForNetworkSelection(key2, false)); + + // Test WifiConfiguration objects are not equal + assertFalse(key1.matchForNetworkSelection(key3, false)); + assertFalse(key3.matchForNetworkSelection(key1, false)); + } + /** + * Test that SAE saved network will never downgrade to a PSK AP (from scan result) + */ + @Test + public void testSaeToPskDoesNotDowngrade() { + WifiConfiguration wifiConfigurationSae = + WifiConfigurationTestUtil.createSaeNetwork("\"Downgrade\""); + WifiConfiguration wifiConfigurationPsk = + WifiConfigurationTestUtil.createPskNetwork("\"Downgrade\""); + ScanDetail scanDetailPsk = createScanDetailForNetwork(wifiConfigurationPsk, + "AC:AB:AD:AE:AF:FC"); + + ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); + ScanResultMatchInfo key2 = ScanResultMatchInfo + .fromScanResult(scanDetailPsk.getScanResult()); + + // Test both a.equals(b) and b.equals(a) are false: + // i.e. SAE saved network will never downgrade to a PSK AP (from scan result) + assertFalse(key1.equals(key2)); + assertFalse(key2.equals(key1)); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java index a0f7952334..1ec9463050 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java @@ -21,6 +21,7 @@ import static com.android.server.wifi.util.NativeUtil.removeEnclosingQuotes; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import android.content.Context; import android.net.MacAddress; import android.net.util.MacAddressUtils; import android.net.wifi.ScanResult; @@ -28,6 +29,8 @@ import android.net.wifi.WifiConfiguration; import androidx.test.filters.SmallTest; +import com.android.wifi.resources.R; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -43,6 +46,7 @@ public class WifiCandidatesTest extends WifiBaseTest { @Mock ScanDetail mScanDetail2; @Mock WifiScoreCard mWifiScoreCard; @Mock WifiScoreCard.PerBssid mPerBssid; + @Mock Context mContext; ScanResult mScanResult1; ScanResult mScanResult2; @@ -51,6 +55,7 @@ public class WifiCandidatesTest extends WifiBaseTest { WifiConfiguration mConfig2; WifiCandidates mWifiCandidates; + MockResources mResources; /** * Sets up for unit test @@ -58,7 +63,7 @@ public class WifiCandidatesTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mWifiCandidates = new WifiCandidates(mWifiScoreCard); + mWifiCandidates = new WifiCandidates(mWifiScoreCard, mContext); mConfig1 = WifiConfigurationTestUtil.createOpenNetwork(); mScanResult1 = new ScanResult() {{ @@ -75,6 +80,9 @@ public class WifiCandidatesTest extends WifiBaseTest { doReturn(mScanResult1).when(mScanDetail1).getScanResult(); doReturn(mScanResult2).when(mScanDetail2).getScanResult(); doReturn(mPerBssid).when(mWifiScoreCard).lookupBssid(any(), any()); + MockResources mResources = new MockResources(); + mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); + doReturn(mResources).when(mContext).getResources(); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java index 2c747e403f..b748fe6bc7 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java @@ -288,11 +288,7 @@ public class WifiConfigurationTestUtil { } public static WifiConfiguration createPskNetwork() { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, null, - null, SECURITY_PSK); - configuration.preSharedKey = TEST_PSK; - return configuration; + return createPskNetwork(createNewSSID()); } public static WifiConfiguration createPskNetwork(String ssid) { diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java index 590db40309..a20bb98729 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java @@ -111,7 +111,6 @@ public class WifiDiagnosticsTest extends WifiBaseTest { }; when(mWifiNative.getRingBufferStatus()).thenReturn(ringBufferStatuses); - when(mWifiNative.readKernelLog()).thenReturn(""); when(mBuildProperties.isEngBuild()).thenReturn(false); when(mBuildProperties.isUserdebugBuild()).thenReturn(false); when(mBuildProperties.isUserBuild()).thenReturn(true); 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 4a27038b3c..e623e75737 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -46,6 +46,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.util.MacAddressUtils; +import android.net.wifi.EAPConstants; import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; @@ -103,12 +104,16 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { private static final String TEST_FEATURE = "testFeature"; private static final String TEST_BSSID = "00:11:22:33:44:55"; private static final String TEST_FQDN = "FQDN"; + private static final String TEST_FRIENDLY_NAME = "test_friendly_name"; + private static final String TEST_REALM = "realm.test.com"; + private static final String TEST_CARRIER_NAME = "test_carrier"; private static final int TEST_UID_1 = 5667; private static final int TEST_UID_2 = 4537; private static final int NETWORK_CALLBACK_ID = 1100; private static final int VALID_CARRIER_ID = 100; private static final int TEST_SUBID = 1; private static final int TEST_NETWORK_ID = 110; + private static final int TEST_CARRIER_ID = 1911; private @Mock Context mContext; private @Mock Resources mResources; @@ -212,10 +217,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testAddNetworkSuggestionsSuccess() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( @@ -265,10 +268,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testRemoveNetworkSuggestionsSuccess() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( @@ -318,10 +319,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testRemoveAllNetworkSuggestionsSuccess() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( @@ -1414,10 +1413,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testNetworkSuggestionsConfigStoreLoad() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; PerAppInfo appInfo = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); @@ -2396,10 +2393,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testOnPasspointNetworkConnectionSuccessWithOneMatch() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( @@ -2553,12 +2548,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testGetPasspointSuggestionFromFqdnWithUserApproval() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); - Credential credential = new Credential(); - passpointConfiguration.setCredential(credential); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, @@ -2581,10 +2572,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testGetPasspointSuggestionFromFqdnWithoutUserApproval() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, @@ -2606,10 +2595,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testIsPasspointSuggestionSharedWithUserSetToTrue() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, @@ -2636,10 +2623,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testIsPasspointSuggestionSharedWithUserSetToFalse() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, @@ -2953,10 +2938,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { */ @Test public void testSetAllowAutoJoinOnPasspointSuggestionNetwork() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); + PasspointConfiguration passpointConfiguration = + createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); WifiConfiguration dummyConfiguration = new WifiConfiguration(); dummyConfiguration.FQDN = TEST_FQDN; WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( @@ -3123,4 +3106,96 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { session.finishMocking(); } } + + /** + * Verify adding invalid suggestions will return right error reason code. + */ + @Test + public void testAddInvalidNetworkSuggestions() { + WifiConfiguration invalidConfig = WifiConfigurationTestUtil.createOpenNetwork(); + invalidConfig.SSID = ""; + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(invalidConfig, + null, false, false, true, true, false); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, + mWifiNetworkSuggestionsManager + .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); + } + + /** + * Verify adding invalid passpoint suggestions will return right error reason code. + */ + @Test + public void testAddInvalidPasspointNetworkSuggestions() { + PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); + HomeSp homeSp = new HomeSp(); + homeSp.setFqdn(TEST_FQDN); + passpointConfiguration.setHomeSp(homeSp); + WifiConfiguration dummyConfig = new WifiConfiguration(); + dummyConfig.FQDN = TEST_FQDN; + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfig, + passpointConfiguration, false, false, true, true, false); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, + mWifiNetworkSuggestionsManager + .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); + } + + /** + * Helper function for creating a test configuration with user credential. + * + * @return {@link PasspointConfiguration} + */ + private PasspointConfiguration createTestConfigWithUserCredential(String fqdn, + String friendlyName) { + PasspointConfiguration config = new PasspointConfiguration(); + HomeSp homeSp = new HomeSp(); + homeSp.setFqdn(fqdn); + homeSp.setFriendlyName(friendlyName); + config.setHomeSp(homeSp); + Map<String, String> friendlyNames = new HashMap<>(); + friendlyNames.put("en", friendlyName); + friendlyNames.put("kr", friendlyName + 1); + friendlyNames.put("jp", friendlyName + 2); + config.setServiceFriendlyNames(friendlyNames); + Credential credential = new Credential(); + credential.setRealm(TEST_REALM); + credential.setCaCertificate(FakeKeys.CA_CERT0); + Credential.UserCredential userCredential = new Credential.UserCredential(); + userCredential.setUsername("username"); + userCredential.setPassword("password"); + userCredential.setEapType(EAPConstants.EAP_TTLS); + userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); + credential.setUserCredential(userCredential); + config.setCredential(credential); + return config; + } + + /** + * Helper function for creating a test configuration with SIM credential. + * + * @return {@link PasspointConfiguration} + */ + private PasspointConfiguration createTestConfigWithSimCredential(String fqdn, String imsi, + String realm) { + PasspointConfiguration config = new PasspointConfiguration(); + HomeSp homeSp = new HomeSp(); + homeSp.setFqdn(fqdn); + homeSp.setFriendlyName(TEST_FRIENDLY_NAME); + config.setHomeSp(homeSp); + Credential credential = new Credential(); + credential.setRealm(TEST_REALM); + Credential.SimCredential simCredential = new Credential.SimCredential(); + simCredential.setImsi(imsi); + simCredential.setEapType(EAPConstants.EAP_SIM); + credential.setSimCredential(simCredential); + config.setCredential(credential); + return config; + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java index adb814e328..26db7cc301 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java @@ -124,6 +124,8 @@ public class TelephonyUtilTest extends WifiBaseTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); + when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) + .thenReturn(mCarrierConfigManager); mTelephonyUtil = new TelephonyUtil(mTelephonyManager, mSubscriptionManager, mFrameworkFacade, mContext, new Handler(mLooper.getLooper())); mSubInfoList = new ArrayList<>(); @@ -157,9 +159,6 @@ public class TelephonyUtilTest extends WifiBaseTest { when(mNonDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); when(mSubscriptionManager.getActiveSubscriptionIdList()) .thenReturn(new int[]{DATA_SUBID, NON_DATA_SUBID}); - - when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) - .thenReturn(mCarrierConfigManager); } @After |