1/*
2 * Copyright (C) 2017 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 */
16package com.android.networkrecommendation.util;
17
18import static com.android.networkrecommendation.Constants.TAG;
19import static com.android.networkrecommendation.util.SsidUtil.quoteSsid;
20
21import android.net.NetworkKey;
22import android.net.WifiKey;
23import android.net.wifi.ScanResult;
24import android.net.wifi.WifiConfiguration;
25import android.support.annotation.Nullable;
26import android.text.TextUtils;
27import com.android.networkrecommendation.config.G;
28
29/**
30 * Scan result utility for any {@link ScanResult} related operations. TODO(b/34125341): Delete this
31 * class once exposed as a SystemApi
32 */
33public class ScanResultUtil {
34
35    /**
36     * Helper method to check if the provided |scanResult| corresponds to a PSK network or not. This
37     * checks if the provided capabilities string contains PSK encryption type or not.
38     */
39    public static boolean isScanResultForPskNetwork(ScanResult scanResult) {
40        return scanResult.capabilities.contains("PSK");
41    }
42
43    /**
44     * Helper method to check if the provided |scanResult| corresponds to a EAP network or not. This
45     * checks if the provided capabilities string contains EAP encryption type or not.
46     */
47    public static boolean isScanResultForEapNetwork(ScanResult scanResult) {
48        return scanResult.capabilities.contains("EAP");
49    }
50
51    /**
52     * Helper method to check if the provided |scanResult| corresponds to a WEP network or not. This
53     * checks if the provided capabilities string contains WEP encryption type or not.
54     */
55    public static boolean isScanResultForWepNetwork(ScanResult scanResult) {
56        return scanResult.capabilities.contains("WEP");
57    }
58
59    /**
60     * Helper method to check if the provided |scanResult| corresponds to an open network or not.
61     * This checks if the provided capabilities string does not contain either of WEP, PSK or EAP
62     * encryption types or not.
63     */
64    public static boolean isScanResultForOpenNetwork(ScanResult scanResult) {
65        return !(isScanResultForWepNetwork(scanResult)
66                || isScanResultForPskNetwork(scanResult)
67                || isScanResultForEapNetwork(scanResult));
68    }
69
70    /** Create a {@link NetworkKey} from a ScanResult, properly quoting the SSID. */
71    @Nullable
72    public static final NetworkKey createNetworkKey(ScanResult scanResult) {
73        WifiKey wifiKey = createWifiKey(scanResult);
74        if (wifiKey == null) {
75            return null;
76        }
77        return new NetworkKey(wifiKey);
78    }
79
80    /**
81     * Helper method to quote the SSID in Scan result to use for comparing/filling SSID stored in
82     * WifiConfiguration object.
83     */
84    @Nullable
85    public static WifiKey createWifiKey(ScanResult result) {
86        if (result == null) {
87            Blog.e(TAG, "Couldn't create WifiKey, provided scan result is null.");
88            return null;
89        }
90        try {
91            return new WifiKey(quoteSsid(result.SSID), result.BSSID);
92        } catch (IllegalArgumentException | NullPointerException e) {
93            // Expect IllegalArgumentException only in Android O.
94            Blog.e(
95                    TAG,
96                    e,
97                    "Couldn't make a wifi key from %s/%s",
98                    Blog.pii(result.SSID, G.Netrec.enableSensitiveLogging.get()),
99                    Blog.pii(result.BSSID, G.Netrec.enableSensitiveLogging.get()));
100            return null;
101        }
102    }
103
104    /** @return {@code true} if the result is for a 2.4GHz network. */
105    public static boolean is24GHz(ScanResult result) {
106        return is24GHz(result.frequency);
107    }
108
109    /** @return {@code true} if the frequency is for a 2.4GHz network. */
110    public static boolean is24GHz(int freq) {
111        return freq > 2400 && freq < 2500;
112    }
113
114    /** @return {@code true} if the result is for a 5GHz network. */
115    public static boolean is5GHz(ScanResult result) {
116        return is5GHz(result.frequency);
117    }
118
119    /** @return {@code true} if the frequency is for a 5GHz network. */
120    public static boolean is5GHz(int freq) {
121        return freq > 4900 && freq < 5900;
122    }
123
124    /**
125     * Checks if the provided |scanResult| match with the provided |config|. Essentially checks if
126     * the network config and scan result have the same SSID and encryption type.
127     */
128    public static boolean doesScanResultMatchWithNetwork(
129            ScanResult scanResult, WifiConfiguration config) {
130        // Add the double quotes to the scan result SSID for comparison with the network configs.
131        String configSSID = quoteSsid(scanResult.SSID);
132        if (TextUtils.equals(config.SSID, configSSID)) {
133            if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
134                    && WifiConfigurationUtil.isConfigForPskNetwork(config)) {
135                return true;
136            }
137            if (ScanResultUtil.isScanResultForEapNetwork(scanResult)
138                    && WifiConfigurationUtil.isConfigForEapNetwork(config)) {
139                return true;
140            }
141            if (ScanResultUtil.isScanResultForWepNetwork(scanResult)
142                    && WifiConfigurationUtil.isConfigForWepNetwork(config)) {
143                return true;
144            }
145            if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)
146                    && WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
147                return true;
148            }
149        }
150        return false;
151    }
152}
153