diff options
author | Sunil Ravi <sunilravi@google.com> | 2020-02-20 09:56:25 -0800 |
---|---|---|
committer | Sunil Ravi <sunilravi@google.com> | 2020-02-24 04:33:06 +0000 |
commit | ddfe48103565da1edfa1a1bece5d2fd5f2e5b064 (patch) | |
tree | b0242defa4b8ac3a2507a22ad95868ae12b8ace8 /service | |
parent | 3f287f8eef3cec1f09a2e68d40ebc77a7b7f3e70 (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)
Diffstat (limited to 'service')
3 files changed, 134 insertions, 4 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 |