summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunil Ravi <sunilravi@google.com>2020-02-20 09:56:25 -0800
committerSunil Ravi <sunilravi@google.com>2020-02-24 04:33:06 +0000
commitddfe48103565da1edfa1a1bece5d2fd5f2e5b064 (patch)
treeb0242defa4b8ac3a2507a22ad95868ae12b8ace8
parent3f287f8eef3cec1f09a2e68d40ebc77a7b7f3e70 (diff)
DPP R2 compatibility check
On receiving DPP error code "CANNOT_FIND_NETWORK", look into the scan cache and update the error code to "NOT_COMPATIBLE", if network's operating channel is not present in enrollee's scanned channel. Bug: 149477842 Test: atest Test: Manual, DPP connection success/failure tests. Change-Id: I786e7541ea365836189979053270cd6748d6adc4 (cherry picked from commit d7e35020761ebdababbf4da43145a5459b296a54)
-rw-r--r--service/java/com/android/server/wifi/DppManager.java102
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java2
-rw-r--r--service/java/com/android/server/wifi/util/ApConfigUtil.java34
-rw-r--r--tests/wifitests/src/com/android/server/wifi/DppManagerTest.java64
4 files changed, 195 insertions, 7 deletions
diff --git a/service/java/com/android/server/wifi/DppManager.java b/service/java/com/android/server/wifi/DppManager.java
index 1f228bcb5..11572f1d2 100644
--- a/service/java/com/android/server/wifi/DppManager.java
+++ b/service/java/com/android/server/wifi/DppManager.java
@@ -26,17 +26,22 @@ import android.hardware.wifi.supplicant.V1_3.DppProgressCode;
import android.hardware.wifi.supplicant.V1_3.DppSuccessCode;
import android.net.wifi.EasyConnectStatusCallback;
import android.net.wifi.IDppCallback;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.WakeupMessage;
import com.android.server.wifi.WifiNative.DppEventCallback;
+import com.android.server.wifi.util.ApConfigUtil;
+import java.util.ArrayList;
+import java.util.List;
/**
* DPP Manager class
* Implements the DPP Initiator APIs and callbacks
@@ -57,6 +62,7 @@ public class DppManager {
private static final String DPP_TIMEOUT_TAG = TAG + " Request Timeout";
private static final int DPP_TIMEOUT_MS = 40_000; // 40 seconds
private final DppMetrics mDppMetrics;
+ private final ScanRequestProxy mScanRequestProxy;
private final DppEventCallback mDppEventCallback = new DppEventCallback() {
@Override
@@ -89,7 +95,7 @@ public class DppManager {
};
DppManager(Handler handler, WifiNative wifiNative, WifiConfigManager wifiConfigManager,
- Context context, DppMetrics dppMetrics) {
+ Context context, DppMetrics dppMetrics, ScanRequestProxy scanRequestProxy) {
mHandler = handler;
mWifiNative = wifiNative;
mWifiConfigManager = wifiConfigManager;
@@ -97,6 +103,7 @@ public class DppManager {
mContext = context;
mClock = new Clock();
mDppMetrics = dppMetrics;
+ mScanRequestProxy = scanRequestProxy;
// Setup timer
mDppTimeoutMessage = new WakeupMessage(mContext, mHandler,
@@ -558,6 +565,88 @@ public class DppManager {
onFailure(dppStatusCode, null, null, null);
}
+ /**
+ *
+ * This function performs the Enrollee compatibility check with the network.
+ * Compatibilty check is done based on the channel match.
+ * The logic looks into the scan cache and checks if network's
+ * operating channel match with one of the channel in enrollee's scanned channel list.
+ *
+ * @param ssid Network name.
+ * @param channelList contains the list of operating class/channels enrollee used to search for
+ * the network.
+ * Reference: DPP spec section: DPP Connection Status Object section.
+ * (eg for channelList: "81/1,2,3,4,5,6,7,8,9,10,11,117/40,115/48")
+ * @return True On compatibility check failures due to error conditions or
+ * when AP is not seen in scan cache or when AP is seen in scan cache and
+ * operating channel is included in enrollee's scanned channel list.
+ * False when network's operating channel is not included in Enrollee's
+ * scanned channel list.
+ *
+ */
+ private boolean isEnrolleeCompatibleWithNetwork(String ssid, String channelList) {
+ if (ssid == null || channelList == null) {
+ return true;
+ }
+ SparseArray<int[]> dppChannelList = WifiManager.parseDppChannelList(channelList);
+
+ if (dppChannelList.size() == 0) {
+ Log.d(TAG, "No channels found after parsing channel list string");
+ return true;
+ }
+
+ List<Integer> freqList = new ArrayList<Integer>();
+
+ /* Convert the received operatingClass/channels to list of frequencies */
+ for (int i = 0; i < dppChannelList.size(); i++) {
+ /* Derive the band corresponding to operating class */
+ int operatingClass = dppChannelList.keyAt(i);
+ int[] channels = dppChannelList.get(operatingClass);
+ int band = ApConfigUtil.getBandFromOperatingClass(operatingClass);
+ if (band < 0) {
+ Log.e(TAG, "Band corresponding to the operating class: " + operatingClass
+ + " not found in the table");
+ continue;
+ }
+ /* Derive frequency list from channel and band */
+ for (int j = 0; j < channels.length; j++) {
+ int freq = ApConfigUtil.convertChannelToFrequency(channels[j], band);
+ if (freq < 0) {
+ Log.e(TAG, "Invalid frequency after converting channel: " + channels[j]
+ + " band: " + band);
+ continue;
+ }
+ freqList.add(freq);
+ }
+ }
+
+ if (freqList.size() == 0) {
+ Log.d(TAG, "frequency list is empty");
+ return true;
+ }
+
+ /* Check the scan cache for the network enrollee tried to find */
+ boolean isNetworkInScanCache = false;
+ boolean channelMatch = false;
+ for (ScanResult scanResult : mScanRequestProxy.getScanResults()) {
+ if (!ssid.equals(scanResult.SSID)) {
+ continue;
+ }
+ isNetworkInScanCache = true;
+ if (freqList.contains(scanResult.frequency)) {
+ channelMatch = true;
+ break;
+ }
+ }
+
+ if (isNetworkInScanCache & !channelMatch) {
+ Log.d(TAG, "Update the error code to NOT_COMPATIBLE"
+ + " as enrollee didn't scan network's operating channel");
+ return false;
+ }
+ return true;
+ }
+
private void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) {
try {
if (mDppRequestInfo == null) {
@@ -610,8 +699,15 @@ public class DppManager {
case DppFailureCode.CANNOT_FIND_NETWORK:
// This is the only case where channel list is populated, according to the
// DPP spec section 6.3.5.2 DPP Connection Status Object
- dppFailureCode = EasyConnectStatusCallback
- .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK;
+ if (isEnrolleeCompatibleWithNetwork(ssid, channelList)) {
+ dppFailureCode =
+ EasyConnectStatusCallback
+ .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK;
+ } else {
+ dppFailureCode =
+ EasyConnectStatusCallback
+ .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE;
+ }
break;
case DppFailureCode.ENROLLEE_AUTHENTICATION:
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 71f8b7073..787f89331 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -357,7 +357,7 @@ public class WifiInjector {
mWifiMulticastLockManager = new WifiMulticastLockManager(
mClientModeImpl.getMcastLockManagerFilterController(), mBatteryStats);
mDppManager = new DppManager(wifiHandler, mWifiNative,
- mWifiConfigManager, mContext, mDppMetrics);
+ mWifiConfigManager, mContext, mDppMetrics, mScanRequestProxy);
// Register the various network Nominators with the network selector.
mWifiNetworkSelector.registerNetworkNominator(mSavedNetworkNominator);
diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index bf319b4f2..7703f2819 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -27,6 +27,7 @@ import android.net.wifi.SoftApConfiguration.BandType;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiScanner;
import android.util.Log;
+import android.util.SparseArray;
import com.android.server.wifi.WifiNative;
import com.android.wifi.resources.R;
@@ -56,6 +57,39 @@ public class ApConfigUtil {
private static final Random sRandom = new Random();
/**
+ * Valid Global Operating classes in each wifi band
+ * Reference: Table E-4 in IEEE Std 802.11-2016.
+ */
+ private static final SparseArray<int[]> sBandToOperatingClass = new SparseArray<>();
+ static {
+ sBandToOperatingClass.append(SoftApConfiguration.BAND_2GHZ, new int[]{81, 82, 83, 84});
+ sBandToOperatingClass.append(SoftApConfiguration.BAND_5GHZ, new int[]{115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130});
+ sBandToOperatingClass.append(SoftApConfiguration.BAND_6GHZ, new int[]{131, 132, 133, 134});
+ }
+
+ /**
+ * Helper function to get the band corresponding to the operating class.
+ *
+ * @param operatingClass Global operating class.
+ * @return band, -1 if no match.
+ *
+ */
+ public static int getBandFromOperatingClass(int operatingClass) {
+ for (int i = 0; i < sBandToOperatingClass.size(); i++) {
+ int band = sBandToOperatingClass.keyAt(i);
+ int[] operatingClasses = sBandToOperatingClass.get(band);
+
+ for (int j = 0; j < operatingClasses.length; j++) {
+ if (operatingClasses[j] == operatingClass) {
+ return band;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
* Convert channel/band to frequency.
* Note: the utility does not perform any regulatory domain compliance.
* @param channel number to convert
diff --git a/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java b/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java
index 9bfa9b6a2..19d17c979 100644
--- a/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java
@@ -66,7 +66,9 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.wifi.EasyConnectStatusCallback;
import android.net.wifi.IDppCallback;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiSsid;
import android.os.Handler;
import android.os.IBinder;
import android.os.test.TestLooper;
@@ -80,6 +82,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Unit tests for {@link DppManager}.
*/
@@ -89,10 +94,12 @@ public class DppManagerTest extends WifiBaseTest {
private static final String TEST_INTERFACE_NAME = "testif0";
private static final int TEST_PEER_ID = 1;
private static final String TEST_SSID = "\"Test_SSID\"";
+ private static final String TEST_SSID_NO_QUOTE = TEST_SSID.replace("\"", "");
private static final String TEST_SSID_ENCODED = "546573745f53534944";
private static final String TEST_PASSWORD = "\"secretPassword\"";
private static final String TEST_PASSWORD_ENCODED = "73656372657450617373776f7264";
private static final int TEST_NETWORK_ID = 1;
+ private static final String TEST_BSSID = "01:02:03:04:05:06";
TestLooper mLooper;
@@ -116,6 +123,8 @@ public class DppManagerTest extends WifiBaseTest {
WakeupMessage mWakeupMessage;
@Mock
DppMetrics mDppMetrics;
+ @Mock
+ ScanRequestProxy mScanRequestProxy;
String mUri =
"DPP:C:81/1;I:DPP_TESTER;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADebGHMJoCcE7OZP/aek5muaJo"
@@ -148,7 +157,7 @@ public class DppManagerTest extends WifiBaseTest {
private DppManager createDppManager() {
DppManager dppManger = new DppManager(new Handler(mLooper.getLooper()), mWifiNative,
- mWifiConfigManager, mContext, mDppMetrics);
+ mWifiConfigManager, mContext, mDppMetrics, mScanRequestProxy);
dppManger.mDppTimeoutMessage = mWakeupMessage;
dppManger.enableVerboseLogging(1);
return dppManger;
@@ -741,10 +750,59 @@ public class DppManagerTest extends WifiBaseTest {
testOnFailureCallback(FAILURE, EASY_CONNECT_EVENT_FAILURE_GENERIC);
}
+ /**
+ * Helper function for setting up a scan result.
+ *
+ * @param frequency Network's operating channel in Mhz.
+ *
+ */
+ private void addTestNetworkInScanResult(int frequency) {
+ String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]";
+ ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(TEST_SSID_NO_QUOTE),
+ TEST_SSID_NO_QUOTE, TEST_BSSID, 1245, 0, caps, -78, frequency,
+ 1025, 22, 33, 20, 0, 0, true);
+ List<ScanResult> scanResults = new ArrayList<>();
+ scanResults.add(scanResult);
+ when(mScanRequestProxy.getScanResults()).thenReturn(scanResults);
+ }
+
+ @Test
+ public void testOnFailureCallbackCannotFindNetworkNoErrCodeChangeOnChannelMatch()
+ throws Exception {
+ int[] bandList = new int[]{81, 83, 84, 115};
+ addTestNetworkInScanResult(2437); //channel number 6
+ // Include Network channel(6) in Enrollee scanned channels.
+ testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE,
+ "81/1,2,3,4,5,6,7,8,9,10,11,115/48",
+ bandList, EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK);
+ }
+
+ @Test
+ public void testOnFailureCallbackCannotFindNetworkErrCodeIsUpdatedOnChannelMismatch()
+ throws Exception {
+ int[] bandList = new int[]{81, 83, 84, 115};
+ addTestNetworkInScanResult(5180); //channel number 36
+ // Don't include Network channel(36) in Enrollee scanned channels.
+ testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE,
+ "81/1,2,3,4,5,6,7,8,9,10,11,115/48",
+ bandList, EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE);
+ }
+
+ @Test
+ public void testOnFailureCallbackCannotFindNetworkNoErrCodeChangeOnInvalidScannedChannelList()
+ throws Exception {
+ int[] bandList = new int[]{81, 83, 84};
+ addTestNetworkInScanResult(5180); //channel number 36
+ // Send Invalid operating class/channel list
+ testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE,
+ "1035/1,2,3,4,5,6,7,8,9,10,11,25/45",
+ bandList, EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK);
+ }
+
@Test
public void testOnFailureCallbackCannotFindNetwork() throws Exception {
int[] bandList = new int[]{1, 6, 11};
- testOnFailureCallback(CANNOT_FIND_NETWORK, "SSID", "1, 3, 6, 8, 11",
+ testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE, "1, 3, 6, 8, 11",
bandList, EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK);
}
@@ -757,7 +815,7 @@ public class DppManagerTest extends WifiBaseTest {
@Test
public void testOnFailureCallbackEnrolleeAuthentication() throws Exception {
int[] bandList = new int[]{1, 6, 11};
- testOnFailureCallback(ENROLLEE_AUTHENTICATION, new String("SSID"), null,
+ testOnFailureCallback(ENROLLEE_AUTHENTICATION, new String(TEST_SSID_NO_QUOTE), null,
bandList, EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION);
}