Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wifi.util;
     18 
     19 import android.net.wifi.ScanResult;
     20 import android.net.wifi.WifiConfiguration;
     21 
     22 import com.android.internal.annotations.VisibleForTesting;
     23 import com.android.internal.util.ArrayUtils;
     24 import com.android.server.wifi.ScanDetail;
     25 import com.android.server.wifi.hotspot2.NetworkDetail;
     26 
     27 import java.io.PrintWriter;
     28 import java.util.List;
     29 /**
     30  * Scan result utility for any {@link ScanResult} related operations.
     31  * Currently contains:
     32  *   > Helper method for converting a ScanResult to a ScanDetail.
     33  *     Only fields that are supported in ScanResult are copied.
     34  *   > Helper methods to identify the encryption of a ScanResult.
     35  */
     36 public class ScanResultUtil {
     37     private ScanResultUtil() { /* not constructable */ }
     38 
     39     /**
     40      * This method should only be used when the informationElements field in the provided scan
     41      * result is filled in with the IEs from the beacon.
     42      */
     43     public static ScanDetail toScanDetail(ScanResult scanResult) {
     44         NetworkDetail networkDetail = new NetworkDetail(scanResult.BSSID,
     45                 scanResult.informationElements, scanResult.anqpLines, scanResult.frequency);
     46         return new ScanDetail(scanResult, networkDetail);
     47     }
     48 
     49     /**
     50      * Helper method to check if the provided |scanResult| corresponds to a PSK network or not.
     51      * This checks if the provided capabilities string contains PSK encryption type or not.
     52      */
     53     public static boolean isScanResultForPskNetwork(ScanResult scanResult) {
     54         return scanResult.capabilities.contains("PSK");
     55     }
     56 
     57     /**
     58      * Helper method to check if the provided |scanResult| corresponds to a EAP network or not.
     59      * This checks if the provided capabilities string contains EAP encryption type or not.
     60      */
     61     public static boolean isScanResultForEapNetwork(ScanResult scanResult) {
     62         return scanResult.capabilities.contains("EAP");
     63     }
     64 
     65     /**
     66      * Helper method to check if the provided |scanResult| corresponds to a WEP network or not.
     67      * This checks if the provided capabilities string contains WEP encryption type or not.
     68      */
     69     public static boolean isScanResultForWepNetwork(ScanResult scanResult) {
     70         return scanResult.capabilities.contains("WEP");
     71     }
     72 
     73     /**
     74      * Helper method to check if the provided |scanResult| corresponds to an open network or not.
     75      * This checks if the provided capabilities string does not contain either of WEP, PSK or EAP
     76      * encryption types or not.
     77      */
     78     public static boolean isScanResultForOpenNetwork(ScanResult scanResult) {
     79         return !(isScanResultForWepNetwork(scanResult) || isScanResultForPskNetwork(scanResult)
     80                 || isScanResultForEapNetwork(scanResult));
     81     }
     82 
     83     /**
     84      * Helper method to quote the SSID in Scan result to use for comparing/filling SSID stored in
     85      * WifiConfiguration object.
     86      */
     87     @VisibleForTesting
     88     public static String createQuotedSSID(String ssid) {
     89         return "\"" + ssid + "\"";
     90     }
     91 
     92     /**
     93      * Creates a network configuration object using the provided |scanResult|.
     94      * This is used to create ephemeral network configurations.
     95      */
     96     public static WifiConfiguration createNetworkFromScanResult(ScanResult scanResult) {
     97         WifiConfiguration config = new WifiConfiguration();
     98         config.SSID = createQuotedSSID(scanResult.SSID);
     99         setAllowedKeyManagementFromScanResult(scanResult, config);
    100         return config;
    101     }
    102 
    103     /**
    104      * Sets the {@link WifiConfiguration#allowedKeyManagement} field on the given
    105      * {@link WifiConfiguration} based on its corresponding {@link ScanResult}.
    106      */
    107     public static void setAllowedKeyManagementFromScanResult(ScanResult scanResult,
    108             WifiConfiguration config) {
    109         if (isScanResultForPskNetwork(scanResult)) {
    110             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
    111         } else if (isScanResultForEapNetwork(scanResult)) {
    112             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
    113             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
    114         } else if (isScanResultForWepNetwork(scanResult)) {
    115             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    116             config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
    117             config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
    118         } else {
    119             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    120         }
    121     }
    122 
    123     /**
    124      * Dump the provided scan results list to |pw|.
    125      */
    126     public static void dumpScanResults(PrintWriter pw, List<ScanResult> scanResults, long nowMs) {
    127         if (scanResults != null && scanResults.size() != 0) {
    128             pw.println("    BSSID              Frequency      RSSI           Age(sec)     SSID "
    129                     + "                                Flags");
    130             for (ScanResult r : scanResults) {
    131                 long timeStampMs = r.timestamp / 1000;
    132                 String age;
    133                 if (timeStampMs <= 0) {
    134                     age = "___?___";
    135                 } else if (nowMs < timeStampMs) {
    136                     age = "  0.000";
    137                 } else if (timeStampMs < nowMs - 1000000) {
    138                     age = ">1000.0";
    139                 } else {
    140                     age = String.format("%3.3f", (nowMs - timeStampMs) / 1000.0);
    141                 }
    142                 String ssid = r.SSID == null ? "" : r.SSID;
    143                 String rssiInfo = "";
    144                 if (ArrayUtils.size(r.radioChainInfos) == 1) {
    145                     rssiInfo = String.format("%5d(%1d:%3d)       ", r.level,
    146                             r.radioChainInfos[0].id, r.radioChainInfos[0].level);
    147                 } else if (ArrayUtils.size(r.radioChainInfos) == 2) {
    148                     rssiInfo = String.format("%5d(%1d:%3d/%1d:%3d)", r.level,
    149                             r.radioChainInfos[0].id, r.radioChainInfos[0].level,
    150                             r.radioChainInfos[1].id, r.radioChainInfos[1].level);
    151                 } else {
    152                     rssiInfo = String.format("%9d         ", r.level);
    153                 }
    154                 pw.printf("  %17s  %9d  %18s   %7s    %-32s  %s\n",
    155                         r.BSSID,
    156                         r.frequency,
    157                         rssiInfo,
    158                         age,
    159                         String.format("%1.32s", ssid),
    160                         r.capabilities);
    161             }
    162         }
    163     }
    164 }
    165