/* * Copyright (C) 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. */ package com.android.server.wifi.util; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.server.wifi.ScanDetail; import com.android.server.wifi.hotspot2.NetworkDetail; import java.io.PrintWriter; import java.util.List; /** * Scan result utility for any {@link ScanResult} related operations. * Currently contains: * > Helper method for converting a ScanResult to a ScanDetail. * Only fields that are supported in ScanResult are copied. * > Helper methods to identify the encryption of a ScanResult. */ public class ScanResultUtil { private ScanResultUtil() { /* not constructable */ } /** * This method should only be used when the informationElements field in the provided scan * result is filled in with the IEs from the beacon. */ public static ScanDetail toScanDetail(ScanResult scanResult) { NetworkDetail networkDetail = new NetworkDetail(scanResult.BSSID, scanResult.informationElements, scanResult.anqpLines, scanResult.frequency); return new ScanDetail(scanResult, networkDetail); } /** * Helper method to check if the provided |scanResult| corresponds to a PSK network or not. * This checks if the provided capabilities string contains PSK encryption type or not. */ public static boolean isScanResultForPskNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("PSK"); } /** * Helper method to check if the provided |scanResult| corresponds to a EAP network or not. * This checks if the provided capabilities string contains EAP encryption type or not. */ public static boolean isScanResultForEapNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("EAP"); } /** * Helper method to check if the provided |scanResult| corresponds to a EAP network or not. * This checks if the provided capabilities string contains EAP encryption type or not. */ public static boolean isScanResultForEapSuiteBNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("SUITE-B-192"); } /** * Helper method to check if the provided |scanResult| corresponds to a WEP network or not. * This checks if the provided capabilities string contains WEP encryption type or not. */ public static boolean isScanResultForWepNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("WEP"); } /** * Helper method to check if the provided |scanResult| corresponds to OWE network. * This checks if the provided capabilities string contains OWE or not. */ public static boolean isScanResultForOweNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("OWE"); } /** * Helper method to check if the provided |scanResult| corresponds to OWE transition network. * This checks if the provided capabilities string contains OWE_TRANSITION or not. */ public static boolean isScanResultForOweTransitionNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("OWE_TRANSITION"); } /** * Helper method to check if the provided |scanResult| corresponds to SAE network. * This checks if the provided capabilities string contains SAE or not. */ public static boolean isScanResultForSaeNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("SAE"); } /** * Helper method to check if the provided |scanResult| corresponds to PSK-SAE transition * network. This checks if the provided capabilities string contains both PSK and SAE or not. */ public static boolean isScanResultForPskSaeTransitionNetwork(ScanResult scanResult) { return scanResult.capabilities.contains("PSK") && scanResult.capabilities.contains("SAE"); } /** * Helper method to check if the provided |scanResult| corresponds to an open network or not. * This checks if the provided capabilities string does not contain either of WEP, PSK, SAE * or EAP encryption types or not. */ public static boolean isScanResultForOpenNetwork(ScanResult scanResult) { return (!(isScanResultForWepNetwork(scanResult) || isScanResultForPskNetwork(scanResult) || isScanResultForEapNetwork(scanResult) || isScanResultForSaeNetwork(scanResult) || isScanResultForEapSuiteBNetwork(scanResult))); } /** * Helper method to quote the SSID in Scan result to use for comparing/filling SSID stored in * WifiConfiguration object. */ @VisibleForTesting public static String createQuotedSSID(String ssid) { return "\"" + ssid + "\""; } /** * Creates a network configuration object using the provided |scanResult|. * This is used to create ephemeral network configurations. */ public static WifiConfiguration createNetworkFromScanResult(ScanResult scanResult) { WifiConfiguration config = new WifiConfiguration(); config.SSID = createQuotedSSID(scanResult.SSID); setAllowedKeyManagementFromScanResult(scanResult, config); return config; } /** * Sets the {@link WifiConfiguration#allowedKeyManagement} field on the given * {@link WifiConfiguration} based on its corresponding {@link ScanResult}. */ public static void setAllowedKeyManagementFromScanResult(ScanResult scanResult, WifiConfiguration config) { if (isScanResultForSaeNetwork(scanResult)) { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); } else if (isScanResultForPskNetwork(scanResult)) { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); } else if (isScanResultForEapSuiteBNetwork(scanResult)) { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); } else if (isScanResultForEapNetwork(scanResult)) { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); } else if (isScanResultForWepNetwork(scanResult)) { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP); } else if (isScanResultForOweNetwork(scanResult)) { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); } else { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); } } /** * Dump the provided scan results list to |pw|. */ public static void dumpScanResults(PrintWriter pw, List scanResults, long nowMs) { if (scanResults != null && scanResults.size() != 0) { pw.println(" BSSID Frequency RSSI Age(sec) SSID " + " Flags"); for (ScanResult r : scanResults) { long timeStampMs = r.timestamp / 1000; String age; if (timeStampMs <= 0) { age = "___?___"; } else if (nowMs < timeStampMs) { age = " 0.000"; } else if (timeStampMs < nowMs - 1000000) { age = ">1000.0"; } else { age = String.format("%3.3f", (nowMs - timeStampMs) / 1000.0); } String ssid = r.SSID == null ? "" : r.SSID; String rssiInfo = ""; if (ArrayUtils.size(r.radioChainInfos) == 1) { rssiInfo = String.format("%5d(%1d:%3d) ", r.level, r.radioChainInfos[0].id, r.radioChainInfos[0].level); } else if (ArrayUtils.size(r.radioChainInfos) == 2) { rssiInfo = String.format("%5d(%1d:%3d/%1d:%3d)", r.level, r.radioChainInfos[0].id, r.radioChainInfos[0].level, r.radioChainInfos[1].id, r.radioChainInfos[1].level); } else { rssiInfo = String.format("%9d ", r.level); } pw.printf(" %17s %9d %18s %7s %-32s %s\n", r.BSSID, r.frequency, rssiInfo, age, String.format("%1.32s", ssid), r.capabilities); } } } }