1155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande/*
2155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Copyright (C) 2010 The Android Open Source Project
3155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
4155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Licensed under the Apache License, Version 2.0 (the "License");
5155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * you may not use this file except in compliance with the License.
6155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * You may obtain a copy of the License at
7155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
8155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *      http://www.apache.org/licenses/LICENSE-2.0
9155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
10155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Unless required by applicable law or agreed to in writing, software
11155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * distributed under the License is distributed on an "AS IS" BASIS,
12155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * See the License for the specific language governing permissions and
14155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * limitations under the License.
15155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande */
16155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
17155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandepackage com.android.server.wifi;
18155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
19eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
20eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpande
2150bb8f65526b16ca8a354fd485d2ed7a343e97aeZoltan Szatmary-Banimport android.app.admin.DeviceAdminInfo;
2250bb8f65526b16ca8a354fd485d2ed7a343e97aeZoltan Szatmary-Banimport android.app.admin.DevicePolicyManagerInternal;
231a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Banimport android.content.ContentResolver;
24155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.content.Context;
25155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.content.Intent;
26faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Leeimport android.content.pm.ApplicationInfo;
27e487a4648dd41881e754f1224aaedead78a0777dSky Faberimport android.content.pm.PackageManager;
2806636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tanimport android.content.pm.UserInfo;
293ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kimimport android.net.IpConfiguration;
303ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kimimport android.net.IpConfiguration.IpAssignment;
313ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kimimport android.net.IpConfiguration.ProxySettings;
32b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kimimport android.net.NetworkInfo.DetailedState;
33d4d0c9ad1e3289702ec341521b9bd01b52e9c1d8Jason Monkimport android.net.ProxyInfo;
343b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colittiimport android.net.StaticIpConfiguration;
352e814680f4dd27a5f825afab189843582235cedcJan Nordqvistimport android.net.wifi.PasspointManagementObjectDefinition;
365bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport android.net.wifi.ScanResult;
37155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiConfiguration;
38155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiConfiguration.KeyMgmt;
39155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiConfiguration.Status;
40155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiEnterpriseConfig;
415bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport android.net.wifi.WifiInfo;
42155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiManager;
438c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Piusimport android.net.wifi.WifiScanner;
44155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WpsInfo;
45155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WpsResult;
46155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.os.Environment;
47611048d11641d9f8136cf2a7065aedbd57095cb9Jeff Sharkeyimport android.os.RemoteException;
48f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.os.SystemClock;
49155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.os.UserHandle;
500fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowskiimport android.os.UserManager;
51c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalleimport android.provider.Settings;
52155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.security.KeyStore;
53155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.text.TextUtils;
54155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.util.LocalLog;
55155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.util.Log;
563ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kimimport android.util.SparseArray;
573ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim
585bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport com.android.internal.R;
59eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport com.android.server.LocalServices;
603ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kimimport com.android.server.net.DelayedDiskWrite;
613ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kimimport com.android.server.net.IpConfigStore;
62ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvistimport com.android.server.wifi.anqp.ANQPElement;
631d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport com.android.server.wifi.anqp.ANQPFactory;
64ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvistimport com.android.server.wifi.anqp.Constants;
65ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvistimport com.android.server.wifi.hotspot2.ANQPData;
66d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpandeimport com.android.server.wifi.hotspot2.AnqpCache;
676dd42662e45750910d8743f7f154269c2755df93Jan Nordqvistimport com.android.server.wifi.hotspot2.IconEvent;
68ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvistimport com.android.server.wifi.hotspot2.NetworkDetail;
69ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvistimport com.android.server.wifi.hotspot2.PasspointMatch;
70d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpandeimport com.android.server.wifi.hotspot2.SupplicantBridge;
71a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvistimport com.android.server.wifi.hotspot2.Utils;
722e814680f4dd27a5f825afab189843582235cedcJan Nordqvistimport com.android.server.wifi.hotspot2.omadm.PasspointManagementObjectManager;
7303e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpandeimport com.android.server.wifi.hotspot2.pps.Credential;
7403e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpandeimport com.android.server.wifi.hotspot2.pps.HomeSP;
75155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
762e814680f4dd27a5f825afab189843582235cedcJan Nordqvistimport org.xml.sax.SAXException;
772e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
785bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.io.BufferedReader;
79b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kimimport java.io.DataOutputStream;
80155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.File;
81155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.FileDescriptor;
82155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.FileNotFoundException;
83155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.FileReader;
84155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.IOException;
85155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.PrintWriter;
8693332917bf29ddbe853a495816e486150f49da40Rebecca Silbersteinimport java.security.cert.X509Certificate;
878f0f666c8bdaf508f191f8590755140b92d970eaxinheimport java.text.DateFormat;
885bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.ArrayList;
8993332917bf29ddbe853a495816e486150f49da40Rebecca Silbersteinimport java.util.BitSet;
90e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalleimport java.util.Calendar;
915bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.Collection;
925bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.Collections;
935bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.Comparator;
948f0f666c8bdaf508f191f8590755140b92d970eaxinheimport java.util.Date;
955bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.HashMap;
965bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.HashSet;
975bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.List;
985bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.Map;
995bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.Objects;
1005bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.Set;
1013d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Piusimport java.util.concurrent.ConcurrentHashMap;
10277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.concurrent.atomic.AtomicBoolean;
10377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.concurrent.atomic.AtomicInteger;
104005c1ef113192f898499a407dd266393a8d6b076vandwalleimport java.util.zip.CRC32;
1055bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvistimport java.util.zip.Checksum;
1065bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist
10703e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
108155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande/**
109155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * This class provides the API to manage configured
110155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * wifi networks. The API is not thread safe is being
111155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * used only from WifiStateMachine.
112155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
113155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * It deals with the following
114155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * - Add/update/remove a WifiConfiguration
115155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *   The configuration contains two types of information.
116c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius *     = IP and proxy configuration that is handled by WifiConfigManager and
117155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       is saved to disk on any change.
118155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
119155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       The format of configuration file is as follows:
120155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       <version>
121155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       <netA_key1><netA_value1><netA_key2><netA_value2>...<EOS>
122155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       <netB_key1><netB_value1><netB_key2><netB_value2>...<EOS>
123155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       ..
124155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
125155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       (key, value) pairs for a given network are grouped together and can
126155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       be in any order. A EOS at the end of a set of (key, value) pairs
127155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       indicates that the next set of (key, value) pairs are for a new
128155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       network. A network is identified by a unique ID_KEY. If there is no
129155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       ID_KEY in the (key, value) pairs, the data is discarded.
130155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
131155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       An invalid version on read would result in discarding the contents of
132155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       the file. On the next write, the latest version is written to file.
133155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
134155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       Any failures during read or write to the configuration file are ignored
135155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       without reporting to the user since the likelihood of these errors are
136155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       low and the impact on connectivity is low.
137155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
138155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *     = SSID & security details that is pushed to the supplicant.
139155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       supplicant saves these details to the disk on calling
140155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       saveConfigCommand().
141155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
142155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *       We have two kinds of APIs exposed:
143155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *        > public API calls that provide fine grained control
144155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *          - enableNetwork, disableNetwork, addOrUpdateNetwork(),
145155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *          removeNetwork(). For these calls, the config is not persisted
146155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *          to the disk. (TODO: deprecate these calls in WifiManager)
147155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *        > The new API calls - selectNetwork(), saveNetwork() & forgetNetwork().
148155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *          These calls persist the supplicant config to disk.
149155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
150155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * - Maintain a list of configured networks for quick access
151155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
152155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande */
153c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Piuspublic class WifiConfigManager {
1540fe550277a9db5a06d8d8265f50a87b4645094f8Samuel Tan    private static boolean sVDBG = false;
1550fe550277a9db5a06d8d8265f50a87b4645094f8Samuel Tan    private static boolean sVVDBG = false;
156c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius    public static final String TAG = "WifiConfigManager";
15773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public static final int MAX_TX_PACKET_FOR_FULL_SCANS = 8;
15873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public static final int MAX_RX_PACKET_FOR_FULL_SCANS = 16;
15973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public static final int MAX_TX_PACKET_FOR_PARTIAL_SCANS = 40;
16073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public static final int MAX_RX_PACKET_FOR_PARTIAL_SCANS = 80;
16173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public static final boolean ROAM_ON_ANY = false;
16273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public static final int MAX_NUM_SCAN_CACHE_ENTRIES = 128;
16373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private static final boolean DBG = true;
16473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private static final String PPS_FILE = "/data/misc/wifi/PerProviderSubscription.conf";
16573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private static final String IP_CONFIG_FILE =
16673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            Environment.getDataDirectory() + "/misc/wifi/ipconfig.txt";
167155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
168e67ec726c07410073575473c0f50dc737629f5davandwalle    // The Wifi verbose log is provided as a way to persist the verbose logging settings
169e67ec726c07410073575473c0f50dc737629f5davandwalle    // for testing purpose.
170e67ec726c07410073575473c0f50dc737629f5davandwalle    // It is not intended for normal use.
17173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private static final String WIFI_VERBOSE_LOGS_KEY = "WIFI_VERBOSE_LOGS";
17270468b47454c8657e8963932f2e08a3f4d7e3881vandwalle
1731ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle    // As we keep deleted PSK WifiConfiguration for a while, the PSK of
1741ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle    // those deleted WifiConfiguration is set to this random unused PSK
1751ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle    private static final String DELETED_CONFIG_PSK = "Mjkd86jEMGn79KhKll298Uu7-deleted";
1761ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle
1778f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
17873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * The maximum number of times we will retry a connection to an access point
17973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * for which we have failed in acquiring an IP address from DHCP. A value of
18073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * N means that we will make N+1 connection attempts in all.
18173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * <p>
18273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
18373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * value if a Settings value is not present.
18473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     */
18573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
18673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
18773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    /**
1888f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * The threshold for each kind of error. If a network continuously encounter the same error more
1898f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * than the threshold times, this network will be disabled. -1 means unavailable.
1908f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
1918f0f666c8bdaf508f191f8590755140b92d970eaxinhe    private static final int[] NETWORK_SELECTION_DISABLE_THRESHOLD = {
1928f0f666c8bdaf508f191f8590755140b92d970eaxinhe            -1, //  threshold for NETWORK_SELECTION_ENABLE
1938f0f666c8bdaf508f191f8590755140b92d970eaxinhe            1,  //  threshold for DISABLED_BAD_LINK
1948f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,  //  threshold for DISABLED_ASSOCIATION_REJECTION
1958f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,  //  threshold for DISABLED_AUTHENTICATION_FAILURE
1968f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,  //  threshold for DISABLED_DHCP_FAILURE
1978f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,  //  threshold for DISABLED_DNS_FAILURE
1988f0f666c8bdaf508f191f8590755140b92d970eaxinhe            6,  //  threshold for DISABLED_TLS_VERSION_MISMATCH
1998f0f666c8bdaf508f191f8590755140b92d970eaxinhe            1,  //  threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS
2008f0f666c8bdaf508f191f8590755140b92d970eaxinhe            1,  //  threshold for DISABLED_NO_INTERNET
2018f0f666c8bdaf508f191f8590755140b92d970eaxinhe            1   //  threshold for DISABLED_BY_WIFI_MANAGER
2028f0f666c8bdaf508f191f8590755140b92d970eaxinhe    };
2038f0f666c8bdaf508f191f8590755140b92d970eaxinhe
2048f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
2058f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Timeout for each kind of error. After the timeout minutes, unblock the network again.
2068f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
2078f0f666c8bdaf508f191f8590755140b92d970eaxinhe    private static final int[] NETWORK_SELECTION_DISABLE_TIMEOUT = {
2088f0f666c8bdaf508f191f8590755140b92d970eaxinhe            Integer.MAX_VALUE,  // threshold for NETWORK_SELECTION_ENABLE
2098f0f666c8bdaf508f191f8590755140b92d970eaxinhe            15,                 // threshold for DISABLED_BAD_LINK
2108f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,                  // threshold for DISABLED_ASSOCIATION_REJECTION
2118f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,                  // threshold for DISABLED_AUTHENTICATION_FAILURE
2128f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,                  // threshold for DISABLED_DHCP_FAILURE
2138f0f666c8bdaf508f191f8590755140b92d970eaxinhe            5,                  // threshold for DISABLED_DNS_FAILURE
2148f0f666c8bdaf508f191f8590755140b92d970eaxinhe            Integer.MAX_VALUE,  // threshold for DISABLED_TLS_VERSION
2158f0f666c8bdaf508f191f8590755140b92d970eaxinhe            Integer.MAX_VALUE,  // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS
2168f0f666c8bdaf508f191f8590755140b92d970eaxinhe            Integer.MAX_VALUE,  // threshold for DISABLED_NO_INTERNET
2178f0f666c8bdaf508f191f8590755140b92d970eaxinhe            Integer.MAX_VALUE   // threshold for DISABLED_BY_WIFI_MANAGER
2188f0f666c8bdaf508f191f8590755140b92d970eaxinhe    };
2198f0f666c8bdaf508f191f8590755140b92d970eaxinhe
22073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicBoolean mEnableAutoJoinWhenAssociated = new AtomicBoolean();
22173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicBoolean mEnableChipWakeUpWhenAssociated = new AtomicBoolean(true);
22273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicBoolean mEnableRssiPollWhenAssociated = new AtomicBoolean(true);
22373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicInteger mThresholdSaturatedRssi5 = new AtomicInteger();
22473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicInteger mThresholdQualifiedRssi24 = new AtomicInteger();
22573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicInteger mEnableVerboseLogging = new AtomicInteger(0);
22673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicInteger mAlwaysEnableScansWhileAssociated = new AtomicInteger(0);
22773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public final AtomicInteger mMaxNumActiveChannelsForPartialScans = new AtomicInteger();
22873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
22973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public boolean mEnableLinkDebouncing;
23073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public boolean mEnableWifiCellularHandoverUserTriggeredAdjustment;
23173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public int mNetworkSwitchingBlackListPeriodMs;
23273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public int mBadLinkSpeed24;
23373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public int mBadLinkSpeed5;
23473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public int mGoodLinkSpeed24;
23573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public int mGoodLinkSpeed5;
23673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
23773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    // These fields are non-final for testing.
23873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public AtomicInteger mThresholdQualifiedRssi5 = new AtomicInteger();
23973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public AtomicInteger mThresholdMinimumRssi5 = new AtomicInteger();
24073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public AtomicInteger mThresholdSaturatedRssi24 = new AtomicInteger();
24173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public AtomicInteger mThresholdMinimumRssi24 = new AtomicInteger();
24273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public AtomicInteger mCurrentNetworkBoost = new AtomicInteger();
24373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public AtomicInteger mBandAward5Ghz = new AtomicInteger();
24473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
245c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle    /**
2461ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle     * If Connectivity Service has triggered an unwanted network disconnect
2471ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle     */
24873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public long mLastUnwantedNetworkDisconnectTimestamp = 0;
2491ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle
2501ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle    /**
25173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * Framework keeps a list of ephemeral SSIDs that where deleted by user,
25273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * so as, framework knows not to autojoin again those SSIDs based on scorer input.
25373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * The list is never cleared up.
25473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     *
25573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field.
256c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle     */
25773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public Set<String> mDeletedEphemeralSSIDs = new HashSet<String>();
258c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle
25973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    /* configured networks with network id as the key */
26073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final ConfigurationMap mConfiguredNetworks;
261c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle
262155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private final LocalLog mLocalLog;
2632d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    private final KeyStore mKeyStore;
26473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final WifiNetworkHistory mWifiNetworkHistory;
26573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final WifiConfigStore mWifiConfigStore;
26673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final AnqpCache mAnqpCache;
26773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final SupplicantBridge mSupplicantBridge;
26873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final SupplicantBridgeCallbacks mSupplicantBridgeCallbacks;
26973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final PasspointManagementObjectManager mMOManager;
27073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final boolean mEnableOsuQueries;
27173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private final SIMAccessor mSIMAccessor;
27206636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    private final UserManager mUserManager;
273bca895e7651c2929ff883568940892987c1a03d3Samuel Tan    private final Object mActiveScanDetailLock = new Object();
274155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2750fe550277a9db5a06d8d8265f50a87b4645094f8Samuel Tan    private Context mContext;
27673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private FrameworkFacade mFacade;
27773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private Clock mClock;
278c1bc5a14b94276421f741eaebb54daa8e63e4a05Roshan Pius    private IpConfigStore mIpconfigStore;
279c1bc5a14b94276421f741eaebb54daa8e63e4a05Roshan Pius    private DelayedDiskWrite mWriter;
280bca895e7651c2929ff883568940892987c1a03d3Samuel Tan    private boolean mOnlyLinkSameCredentialConfigurations;
281bca895e7651c2929ff883568940892987c1a03d3Samuel Tan    private boolean mShowNetworks = false;
28206636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    private int mCurrentUserId = UserHandle.USER_SYSTEM;
283c1bc5a14b94276421f741eaebb54daa8e63e4a05Roshan Pius
28473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    /* Stores a map of NetworkId to ScanCache */
28573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private ConcurrentHashMap<Integer, ScanDetailCache> mScanDetailCaches;
28673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
28773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    /* Tracks the highest priority of configured networks */
28873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private int mLastPriority = -1;
28973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
290931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle    /**
29173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * The mLastSelectedConfiguration is used to remember which network
2928c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle     * was selected last by the user.
293117be607246604e875de62aa8cdd99700b77a2b4vandwalle     * The connection to this network may not be successful, as well
294117be607246604e875de62aa8cdd99700b77a2b4vandwalle     * the selection (i.e. network priority) might not be persisted.
295117be607246604e875de62aa8cdd99700b77a2b4vandwalle     * WiFi state machine is the only object that sets this variable.
296117be607246604e875de62aa8cdd99700b77a2b4vandwalle     */
29773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private String mLastSelectedConfiguration = null;
2988f0f666c8bdaf508f191f8590755140b92d970eaxinhe    private long mLastSelectedTimeStamp =
2998f0f666c8bdaf508f191f8590755140b92d970eaxinhe            WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
300117be607246604e875de62aa8cdd99700b77a2b4vandwalle
3019ccffbb6c3fe8eaa7d70cc3076d0dc3c6a9073e7Pierre Vandwalle    /*
302e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle     * Lost config list, whenever we read a config from networkHistory.txt that was not in
303e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle     * wpa_supplicant.conf
304e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle     */
30573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private HashSet<String> mLostConfigsDbg = new HashSet<String>();
3063d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius
307308a06a125932081304655cda8374ffcf0772b3cSamuel Tan    private ScanDetail mActiveScanDetail;   // ScanDetail associated with active network
308308a06a125932081304655cda8374ffcf0772b3cSamuel Tan
3093d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius    private class SupplicantBridgeCallbacks implements SupplicantBridge.SupplicantBridgeCallbacks {
3103d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        @Override
3113d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        public void notifyANQPResponse(ScanDetail scanDetail,
3123d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius                                       Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
3133d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            updateAnqpCache(scanDetail, anqpElements);
3143d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            if (anqpElements == null || anqpElements.isEmpty()) {
3153d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius                return;
3163d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            }
3173d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            scanDetail.propagateANQPInfo(anqpElements);
3183d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius
3193d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            Map<HomeSP, PasspointMatch> matches = matchNetwork(scanDetail, false);
3203d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            Log.d(Utils.hs2LogTag(getClass()), scanDetail.getSSID() + " pass 2 matches: "
3213d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius                    + toMatchString(matches));
3223d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius
3233d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            cacheScanResultForPasspointConfigs(scanDetail, matches, null);
3243d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        }
3253d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        @Override
3263d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        public void notifyIconFailed(long bssid) {
3273d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            Intent intent = new Intent(WifiManager.PASSPOINT_ICON_RECEIVED_ACTION);
3283d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3293d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_BSSID, bssid);
3303d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
3313d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        }
3323d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius
3333d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius    }
3343d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius
335ac69b83c9cafb9a839b578c3b5b71eb3439244adSamuel Tan    WifiConfigManager(Context context, WifiNative wifiNative, FrameworkFacade facade, Clock clock,
336ac69b83c9cafb9a839b578c3b5b71eb3439244adSamuel Tan            UserManager userManager, KeyStore keyStore) {
3372d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mContext = context;
3382d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mFacade = facade;
339ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        mClock = clock;
3402d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mKeyStore = keyStore;
34106636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        mUserManager = userManager;
342155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
34373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (mShowNetworks) {
3442d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            mLocalLog = wifiNative.getLocalLog();
345155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        } else {
346155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mLocalLog = null;
347155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3482f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle
34973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean(
350448c9536a302c58a79e271b1721c08b8882f800evandwalle                R.bool.config_wifi_only_link_same_credential_configurations);
35173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mMaxNumActiveChannelsForPartialScans.set(mContext.getResources().getInteger(
35277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels));
35373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mEnableLinkDebouncing = mContext.getResources().getBoolean(
3540eebae7334d6129f7ca1344e4b20199794994358vandwalle                R.bool.config_wifi_enable_disconnection_debounce);
35573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mBandAward5Ghz.set(mContext.getResources().getInteger(
3568f0f666c8bdaf508f191f8590755140b92d970eaxinhe                R.integer.config_wifi_framework_5GHz_preference_boost_factor));
35773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mThresholdMinimumRssi5.set(mContext.getResources().getInteger(
35877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz));
35973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mThresholdQualifiedRssi5.set(mContext.getResources().getInteger(
36077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz));
36173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mThresholdSaturatedRssi5.set(mContext.getResources().getInteger(
36277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz));
36373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mThresholdMinimumRssi24.set(mContext.getResources().getInteger(
36477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz));
36573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mThresholdQualifiedRssi24.set(mContext.getResources().getInteger(
36677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz));
36773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mThresholdSaturatedRssi24.set(mContext.getResources().getInteger(
36877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz));
36973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mEnableWifiCellularHandoverUserTriggeredAdjustment = mContext.getResources().getBoolean(
37017e828848eebb4eb11d27ce32d02716334dd6011vandwalle                R.bool.config_wifi_framework_cellular_handover_enable_user_triggered_adjustment);
37173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mBadLinkSpeed24 = mContext.getResources().getInteger(
37217e828848eebb4eb11d27ce32d02716334dd6011vandwalle                R.integer.config_wifi_framework_wifi_score_bad_link_speed_24);
37373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mBadLinkSpeed5 = mContext.getResources().getInteger(
37417e828848eebb4eb11d27ce32d02716334dd6011vandwalle                R.integer.config_wifi_framework_wifi_score_bad_link_speed_5);
37573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mGoodLinkSpeed24 = mContext.getResources().getInteger(
37617e828848eebb4eb11d27ce32d02716334dd6011vandwalle                R.integer.config_wifi_framework_wifi_score_good_link_speed_24);
37773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mGoodLinkSpeed5 = mContext.getResources().getInteger(
37817e828848eebb4eb11d27ce32d02716334dd6011vandwalle                R.integer.config_wifi_framework_wifi_score_good_link_speed_5);
37973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mEnableAutoJoinWhenAssociated.set(mContext.getResources().getBoolean(
38077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                R.bool.config_wifi_framework_enable_associated_network_selection));
38173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mCurrentNetworkBoost.set(mContext.getResources().getInteger(
3828f0f666c8bdaf508f191f8590755140b92d970eaxinhe                R.integer.config_wifi_framework_current_network_boost));
38373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mNetworkSwitchingBlackListPeriodMs = mContext.getResources().getInteger(
3844fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle                R.integer.config_wifi_network_switching_blacklist_time);
385dd490cf1df37b70a8625dc4ec8e712f740dd1e4aPierre Vandwalle
386034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist        boolean hs2on = mContext.getResources().getBoolean(R.bool.config_wifi_hotspot2_enabled);
387034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist        Log.d(Utils.hs2LogTag(getClass()), "Passpoint is " + (hs2on ? "enabled" : "disabled"));
388034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist
3890fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowski        mConfiguredNetworks = new ConfigurationMap(userManager);
3902e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        mMOManager = new PasspointManagementObjectManager(new File(PPS_FILE), hs2on);
3912e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        mEnableOsuQueries = true;
392ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        mAnqpCache = new AnqpCache(mClock);
3933d1baff308fd209648a4d3cf5c02a8bfd1a98a52Roshan Pius        mSupplicantBridgeCallbacks = new SupplicantBridgeCallbacks();
3942d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mSupplicantBridge = new SupplicantBridge(wifiNative, mSupplicantBridgeCallbacks);
3957713c37038f24f06039e5c4c3c191e10a1b9e159Randy Pan        mScanDetailCaches = new ConcurrentHashMap<>(16, 0.75f, 2);
39607a3f9d97394b97965e6754271fb66c1d6bd1753Jan Nordqvist        mSIMAccessor = new SIMAccessor(mContext);
397c1bc5a14b94276421f741eaebb54daa8e63e4a05Roshan Pius        mWriter = new DelayedDiskWrite();
398c1bc5a14b94276421f741eaebb54daa8e63e4a05Roshan Pius        mIpconfigStore = new IpConfigStore(mWriter);
3992d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiNetworkHistory = new WifiNetworkHistory(context, mLocalLog, mWriter);
4002d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore =
40173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                new WifiConfigStore(wifiNative, mKeyStore, mLocalLog, mShowNetworks, true);
402155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
403155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
404c465290772b735d97cba451c9bc5b6cc76db9147Jan Nordqvist    public void trimANQPCache(boolean all) {
405c465290772b735d97cba451c9bc5b6cc76db9147Jan Nordqvist        mAnqpCache.clear(all, DBG);
4068366a82ee1bff4c66d3f3642bf0a60538de5d9daJan Nordqvist    }
4078366a82ee1bff4c66d3f3642bf0a60538de5d9daJan Nordqvist
408ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle    void enableVerboseLogging(int verbose) {
40973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mEnableVerboseLogging.set(verbose);
410ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle        if (verbose > 0) {
41173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            sVDBG = true;
41273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            mShowNetworks = true;
413ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle        } else {
41473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            sVDBG = false;
415ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle        }
4167b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle        if (verbose > 1) {
41773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            sVVDBG = true;
4187b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle        } else {
41973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            sVVDBG = false;
4207b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle        }
421ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle    }
422ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle
423155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
424155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Fetch the list of configured networks
425155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * and enable all stored networks in supplicant.
426155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
427155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    void loadAndEnableAllNetworks() {
4280888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        if (DBG) log("Loading config and enabling all networks ");
429155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        loadConfiguredNetworks();
430155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        enableAllNetworks();
431155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
432155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
433931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle    int getConfiguredNetworksSize() {
434bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        return mConfiguredNetworks.sizeForCurrentUser();
435931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle    }
436931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle
43760969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan    /**
43860969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
43960969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * ephemeral networks).
44060969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * @param pskMap Map of preSharedKeys, keyed by the configKey of the configuration the
44160969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * preSharedKeys belong to
44260969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * @return List of networks
44360969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     */
44460969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan    private List<WifiConfiguration> getSavedNetworks(Map<String, String> pskMap) {
4459878c61bbd81176561991be025af44efc67332feWenchao Tong        List<WifiConfiguration> networks = new ArrayList<>();
446bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
4479878c61bbd81176561991be025af44efc67332feWenchao Tong            WifiConfiguration newConfig = new WifiConfiguration(config);
4483aed1e5a7a7f2ec730c393e2c7d129e3e551a711Jeff Davidson            // When updating this condition, update WifiStateMachine's CONNECT_NETWORK handler to
4493aed1e5a7a7f2ec730c393e2c7d129e3e551a711Jeff Davidson            // correctly handle updating existing configs that are filtered out here.
4508f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (config.ephemeral) {
45160969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan                // Do not enumerate and return this configuration to anyone (e.g. WiFi Picker);
45260969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan                // treat it as unknown instead. This configuration can still be retrieved
45360969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan                // directly by its key or networkId.
4540e3c67280365eb82fc15362a3b98a2c978bde766vandwalle                continue;
4550e3c67280365eb82fc15362a3b98a2c978bde766vandwalle            }
456e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle
4579878c61bbd81176561991be025af44efc67332feWenchao Tong            if (pskMap != null && config.allowedKeyManagement != null
4589878c61bbd81176561991be025af44efc67332feWenchao Tong                    && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)
4592fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                    && pskMap.containsKey(config.configKey(true))) {
4602fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                newConfig.preSharedKey = pskMap.get(config.configKey(true));
4619878c61bbd81176561991be025af44efc67332feWenchao Tong            }
4629878c61bbd81176561991be025af44efc67332feWenchao Tong            networks.add(newConfig);
463155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
464155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return networks;
465155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
466155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
467155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
46860969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * This function returns all configuration, and is used for debug and creating bug reports.
469d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle     */
47073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private List<WifiConfiguration> getAllConfiguredNetworks() {
471d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle        List<WifiConfiguration> networks = new ArrayList<>();
472bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
473d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle            WifiConfiguration newConfig = new WifiConfiguration(config);
474d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle            networks.add(newConfig);
475d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle        }
476d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle        return networks;
477d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle    }
478d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle
479d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle    /**
48060969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
48160969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * ephemeral networks).
4829878c61bbd81176561991be025af44efc67332feWenchao Tong     * @return List of networks
4839878c61bbd81176561991be025af44efc67332feWenchao Tong     */
48460969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan    public List<WifiConfiguration> getSavedNetworks() {
48560969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan        return getSavedNetworks(null);
4869878c61bbd81176561991be025af44efc67332feWenchao Tong    }
4879878c61bbd81176561991be025af44efc67332feWenchao Tong
4889878c61bbd81176561991be025af44efc67332feWenchao Tong    /**
48960969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
49060969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * ephemeral networks), filled with real preSharedKeys.
4919878c61bbd81176561991be025af44efc67332feWenchao Tong     * @return List of networks
4929878c61bbd81176561991be025af44efc67332feWenchao Tong     */
49360969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan    List<WifiConfiguration> getPrivilegedSavedNetworks() {
4942fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan        Map<String, String> pskMap = getCredentialsByConfigKeyMap();
49560969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan        List<WifiConfiguration> configurations = getSavedNetworks(pskMap);
4962e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        for (WifiConfiguration configuration : configurations) {
4972e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            try {
4982e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                configuration
4992e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                        .setPasspointManagementObjectTree(mMOManager.getMOTree(configuration.FQDN));
5002e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            } catch (IOException ioe) {
5012e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                Log.w(TAG, "Failed to parse MO from " + configuration.FQDN + ": " + ioe);
5022e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            }
5032e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
5042e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        return configurations;
5059878c61bbd81176561991be025af44efc67332feWenchao Tong    }
5069878c61bbd81176561991be025af44efc67332feWenchao Tong
5079878c61bbd81176561991be025af44efc67332feWenchao Tong    /**
5083d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius     * Fetch the list of networkId's which are hidden in current user's configuration.
5093d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius     * @return List of networkIds
5103d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius     */
5113d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius    public Set<Integer> getHiddenConfiguredNetworkIds() {
5123d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius        return mConfiguredNetworks.getHiddenNetworkIdsForCurrentUser();
5133d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius    }
5143d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius
5153d995b8a3a508e957e3dac2e508956020cd9abfeRoshan Pius    /**
516ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande     * Find matching network for this scanResult
517ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande     */
518ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande    WifiConfiguration getMatchingConfig(ScanResult scanResult) {
519073c371dbc5b361bf5f6651ed5f6b471012bd673Paul Stewart        if (scanResult == null) {
520073c371dbc5b361bf5f6651ed5f6b471012bd673Paul Stewart            return null;
521073c371dbc5b361bf5f6651ed5f6b471012bd673Paul Stewart        }
522ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande        for (Map.Entry entry : mScanDetailCaches.entrySet()) {
523ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande            Integer netId = (Integer) entry.getKey();
524ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande            ScanDetailCache cache = (ScanDetailCache) entry.getValue();
525ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande            WifiConfiguration config = getWifiConfiguration(netId);
52673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (config == null) {
527ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande                continue;
52873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            }
529ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande            if (cache.get(scanResult.BSSID) != null) {
530ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande                return config;
531ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande            }
532ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande        }
533ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande
534ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande        return null;
535ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande    }
536ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande
537ccbe820337a230f0827f734aca2c51a244a0837fVinit Deshpande    /**
5389878c61bbd81176561991be025af44efc67332feWenchao Tong     * Fetch the preSharedKeys for all networks.
5392fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan     * @return a map from configKey to preSharedKey.
5409878c61bbd81176561991be025af44efc67332feWenchao Tong     */
5412fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan    private Map<String, String> getCredentialsByConfigKeyMap() {
5429878c61bbd81176561991be025af44efc67332feWenchao Tong        return readNetworkVariablesFromSupplicantFile("psk");
5439878c61bbd81176561991be025af44efc67332feWenchao Tong    }
5449878c61bbd81176561991be025af44efc67332feWenchao Tong
5459878c61bbd81176561991be025af44efc67332feWenchao Tong    /**
54660969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * Fetch the list of currently saved networks (i.e. all configured networks, excluding
54760969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * ephemeral networks) that were recently seen.
548f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     *
54960969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * @param scanResultAgeMs The maximum age (in ms) of scan results for which we calculate the
55060969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * RSSI values
55160969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * @param copy If true, the returned list will contain copies of the configurations for the
55260969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * saved networks. Otherwise, the returned list will contain references to these
55360969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan     * configurations.
554f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * @return List of networks
555f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
55660969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan    List<WifiConfiguration> getRecentSavedNetworks(int scanResultAgeMs, boolean copy) {
5578639f6266cb70bf92d1561af43ac2d7b2b97298eJeff Davidson        List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
558f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
559bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
5608f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (config.ephemeral) {
56160969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan                // Do not enumerate and return this configuration to anyone (e.g. WiFi Picker);
56260969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan                // treat it as unknown instead. This configuration can still be retrieved
56360969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan                // directly by its key or networkId.
5640e3c67280365eb82fc15362a3b98a2c978bde766vandwalle                continue;
5650e3c67280365eb82fc15362a3b98a2c978bde766vandwalle            }
5660e3c67280365eb82fc15362a3b98a2c978bde766vandwalle
56760969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan            // Calculate the RSSI for scan results that are more recent than scanResultAgeMs.
56825ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            ScanDetailCache cache = getScanDetailCache(config);
56925ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            if (cache == null) {
57025ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                continue;
57125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            }
57260969bf2c849011fb585cf6dc914dbd779dfb8cfSamuel Tan            config.setVisibility(cache.getVisibility(scanResultAgeMs));
573f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (config.visibility == null) {
574f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
575f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
57673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (config.visibility.rssi5 == WifiConfiguration.INVALID_RSSI
57773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    && config.visibility.rssi24 == WifiConfiguration.INVALID_RSSI) {
578f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
579f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
580f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (copy) {
581f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                networks.add(new WifiConfiguration(config));
582f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else {
583f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                networks.add(config);
584f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
585f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
586f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return networks;
587f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
588f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
589f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /**
590c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle     *  Update the configuration and BSSID with latest RSSI value.
591c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle     */
592c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle    void updateConfiguration(WifiInfo info) {
593c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle        WifiConfiguration config = getWifiConfiguration(info.getNetworkId());
59425ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (config != null && getScanDetailCache(config) != null) {
59525ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            ScanDetail scanDetail = getScanDetailCache(config).getScanDetail(info.getBSSID());
59625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            if (scanDetail != null) {
59725ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                ScanResult result = scanDetail.getScanResult();
598c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle                long previousSeen = result.seen;
599c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle                int previousRssi = result.level;
600c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle
601c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle                // Update the scan result
60225ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                scanDetail.setSeen();
603c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle                result.level = info.getRssi();
604c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle
605c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle                // Average the RSSI value
606c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle                result.averageRssi(previousRssi, previousSeen,
6078f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        WifiQualifiedNetworkSelector.SCAN_RESULT_MAXIMUNM_AGE);
60873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (sVDBG) {
609646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("updateConfiguration freq=" + result.frequency
61073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                            + " BSSID=" + result.BSSID
61173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                            + " RSSI=" + result.level
61273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                            + " " + config.configKey());
613ede507649471f1113e9e1919812115ca5a6bc0c8vandwalle                }
614c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle            }
615c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle        }
616c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle    }
617c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle
618c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle    /**
619f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * get the Wificonfiguration for this netId
620f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     *
621f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * @return Wificonfiguration
622f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
6238f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe    public WifiConfiguration getWifiConfiguration(int netId) {
624bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        return mConfiguredNetworks.getForCurrentUser(netId);
625f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
626f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
627f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /**
628c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle     * Get the Wificonfiguration for this key
629f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * @return Wificonfiguration
630f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
6318f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe    public WifiConfiguration getWifiConfiguration(String key) {
632bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        return mConfiguredNetworks.getByConfigKeyForCurrentUser(key);
633f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
634f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
635f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /**
6368f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Enable all networks (if disabled time expire) and save config. This will be a no-op if the
6378f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * list of configured networks indicates all networks as being enabled
638155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
639155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    void enableAllNetworks() {
640155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        boolean networkEnabledStateChanged = false;
641e0ba94ba9abde13173ae0de8c8939aa4eb9a9085vandwalle
642bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
6438f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (config != null && !config.ephemeral
6448f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    && !config.getNetworkSelectionStatus().isNetworkEnabled()) {
6458f0f666c8bdaf508f191f8590755140b92d970eaxinhe                if (tryEnableQualifiedNetwork(config)) {
646155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    networkEnabledStateChanged = true;
647155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
648155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
649155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
650155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
651155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (networkEnabledStateChanged) {
6522d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            saveConfig();
653155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            sendConfiguredNetworksChangedBroadcast();
654155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
655155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
656155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
6572d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    private boolean setNetworkPriorityNative(WifiConfiguration config, int priority) {
6582d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.setNetworkPriority(config, priority);
659d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
660d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
6612d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    private boolean setSSIDNative(WifiConfiguration config, String ssid) {
6622d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.setNetworkSSID(config, ssid);
663d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
664155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
665ab99a7a345781a9f3ff07335744c1f2073c44ac6Lorenzo Colitti    public boolean updateLastConnectUid(WifiConfiguration config, int uid) {
666f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti        if (config != null) {
667f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti            if (config.lastConnectUid != uid) {
668f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti                config.lastConnectUid = uid;
669f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti                return true;
670f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti            }
671f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti        }
672f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti        return false;
673f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti    }
674f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti
675155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
676155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Selects the specified network for connection. This involves
677155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * updating the priority of all the networks and enabling the given
678155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * network while disabling others.
679155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
680155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Selecting a network will leave the other networks disabled and
681155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * a call to enableAllNetworks() needs to be issued upon a connection
682155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * or a failure event from supplicant
683155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
6848bc78bddb29cdd9e845f313fabb08c485aa40c21Jan Nordqvist     * @param config network to select for connection
6858bc78bddb29cdd9e845f313fabb08c485aa40c21Jan Nordqvist     * @param updatePriorities makes config highest priority network
686155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return false if the network id is invalid
687155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
688f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti    boolean selectNetwork(WifiConfiguration config, boolean updatePriorities, int uid) {
68973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) localLogNetwork("selectNetwork", config.networkId);
690d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        if (config.networkId == INVALID_NETWORK_ID) return false;
6910fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowski        if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
69206636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan                mUserManager.getProfiles(mCurrentUserId))) {
693bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            loge("selectNetwork " + Integer.toString(config.networkId) + ": Network config is not "
694bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    + "visible to current user.");
695bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return false;
696bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
697155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
698155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // Reset the priority of each network at start or if it goes too high.
699155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (mLastPriority == -1 || mLastPriority > 1000000) {
7002d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            if (updatePriorities) {
7012d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                for (WifiConfiguration config2 : mConfiguredNetworks.valuesForCurrentUser()) {
7020047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande                    if (config2.networkId != INVALID_NETWORK_ID) {
7032d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                        setNetworkPriorityNative(config2, 0);
7040047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande                    }
705d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                }
706155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
707155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mLastPriority = 0;
708155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
709155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
710155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // Set to the highest priority and save the configuration.
7110047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande        if (updatePriorities) {
7122d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            setNetworkPriorityNative(config, ++mLastPriority);
7130047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande        }
714155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
715d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        if (config.isPasspoint()) {
716d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            /* need to slap on the SSID of selected bssid to work */
71725ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            if (getScanDetailCache(config).size() != 0) {
71825ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                ScanDetail result = getScanDetailCache(config).getFirst();
719d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                if (result == null) {
720d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                    loge("Could not find scan result for " + config.BSSID);
721d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                } else {
722646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("Setting SSID for " + config.networkId + " to" + result.getSSID());
7232d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                    setSSIDNative(config, result.getSSID());
724d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                }
725d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
726d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            } else {
727d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                loge("Could not find bssid for " + config);
728d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            }
729d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
730155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
7312d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.enableHS20(config.isPasspoint());
73256845c30ef2bc7ccfd92764e4c7352aee03ec3a8Vinit Deshpande
73373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (updatePriorities) {
7342d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            saveConfig();
73573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        }
736155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
737f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti        updateLastConnectUid(config, uid);
738c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
739b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        writeKnownNetworkHistory();
740155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
741155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        /* Enable the given network while disabling all other networks */
7429d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius        selectNetworkWithoutBroadcast(config.networkId);
743155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
744155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande       /* Avoid saving the config & sending a broadcast to prevent settings
745155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        * from displaying a disabled list of networks */
746155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return true;
747155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
748155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
749155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
750155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Add/update the specified configuration and save config
751155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
752155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param config WifiConfiguration to be saved
753155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return network update result
754155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
7550eebae7334d6129f7ca1344e4b20199794994358vandwalle    NetworkUpdateResult saveNetwork(WifiConfiguration config, int uid) {
756952d359198cb1f04c180fc0f795dc316fe97cb5evandwalle        WifiConfiguration conf;
757f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
758155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // A new network cannot have null SSID
75973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (config == null || (config.networkId == INVALID_NETWORK_ID && config.SSID == null)) {
760155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return new NetworkUpdateResult(INVALID_NETWORK_ID);
761155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
762bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
7630fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowski        if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
76406636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan                mUserManager.getProfiles(mCurrentUserId))) {
765bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return new NetworkUpdateResult(INVALID_NETWORK_ID);
766bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
767bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
76873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) localLogNetwork("WifiConfigManager: saveNetwork netId", config.networkId);
76973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) {
770c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius            logd("WifiConfigManager saveNetwork,"
771bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    + " size=" + Integer.toString(mConfiguredNetworks.sizeForAllUsers())
772bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    + " (for all users)"
773992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                    + " SSID=" + config.SSID
774992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                    + " Uid=" + Integer.toString(config.creatorUid)
775992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                    + "/" + Integer.toString(config.lastUpdateUid));
776f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
7772ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
7782ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle        if (mDeletedEphemeralSSIDs.remove(config.SSID)) {
77973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (sVDBG) {
780646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                logd("WifiConfigManager: removed from ephemeral blacklist: " + config.SSID);
7812ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle            }
7822ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle            // NOTE: This will be flushed to disk as part of the addOrUpdateNetworkNative call
7832ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle            // below, since we're creating/modifying a config.
7842ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle        }
7852ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
786155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
7870eebae7334d6129f7ca1344e4b20199794994358vandwalle        NetworkUpdateResult result = addOrUpdateNetworkNative(config, uid);
788155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        int netId = result.getNetworkId();
789f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
79073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) localLogNetwork("WifiConfigManager: saveNetwork got it back netId=", netId);
791f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
792bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        conf = mConfiguredNetworks.getForCurrentUser(netId);
793f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (conf != null) {
7948f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (!conf.getNetworkSelectionStatus().isNetworkEnabled()) {
79573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (sVDBG) localLog("WifiConfigManager: re-enabling: " + conf.SSID);
796f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
797f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                // reenable autojoin, since new information has been provided
7988f0f666c8bdaf508f191f8590755140b92d970eaxinhe                updateNetworkSelectionStatus(netId,
7998f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
800f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
80173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (sVDBG) {
802646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                logd("WifiConfigManager: saveNetwork got config back netId="
803be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                        + Integer.toString(netId)
804be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                        + " uid=" + Integer.toString(config.creatorUid));
805be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle            }
806f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
807f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
8082d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        saveConfig();
80973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        sendConfiguredNetworksChangedBroadcast(
81073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                conf,
81173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                result.isNewNetwork()
81273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        ? WifiManager.CHANGE_REASON_ADDED
81373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
814155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return result;
815155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
816155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
8174fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle    void noteRoamingFailure(WifiConfiguration config, int reason) {
8184fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle        if (config == null) return;
819ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius        config.lastRoamingFailure = mClock.currentTimeMillis();
82073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        config.roamingFailureBlackListTimeMilli =
82173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                2 * (config.roamingFailureBlackListTimeMilli + 1000);
82273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (config.roamingFailureBlackListTimeMilli > mNetworkSwitchingBlackListPeriodMs) {
82373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            config.roamingFailureBlackListTimeMilli = mNetworkSwitchingBlackListPeriodMs;
8244fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle        }
8254fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle        config.lastRoamingFailureReason = reason;
8264fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle    }
8274fa99f57077ab287d6ed1b51cf308c44ce8bbe0bvandwalle
8282d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    void saveWifiConfigBSSID(WifiConfiguration config, String bssid) {
8292d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.setNetworkBSSID(config, bssid);
8309f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle    }
8319f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle
8329f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle
833155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    void updateStatus(int netId, DetailedState state) {
834155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (netId != INVALID_NETWORK_ID) {
835bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            WifiConfiguration config = mConfiguredNetworks.getForAllUsers(netId);
836155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (config == null) return;
837155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            switch (state) {
838155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case CONNECTED:
839155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    config.status = Status.CURRENT;
84027355a942653264388e909a4276196ee63e57811vandwalle                    //we successfully connected, hence remove the blacklist
8418f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    updateNetworkSelectionStatus(netId,
8428f0f666c8bdaf508f191f8590755140b92d970eaxinhe                            WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
843155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
844155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case DISCONNECTED:
845155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    //If network is already disabled, keep the status
846155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    if (config.status == Status.CURRENT) {
847155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        config.status = Status.ENABLED;
848155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    }
849155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
850155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                default:
851155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    //do nothing, retain the existing state
852155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
853155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
854155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
855155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
856155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
8572ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
8582ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle    /**
8592ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     * Disable an ephemeral SSID for the purpose of auto-joining thru scored.
8602ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     * This SSID will never be scored anymore.
8612ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     * The only way to "un-disable it" is if the user create a network for that SSID and then
8622ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     * forget it.
8632ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     *
86473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan     * @param ssid caller must ensure that the SSID passed thru this API match
8652ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     *            the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
8662ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     * @return the {@link WifiConfiguration} corresponding to this SSID, if any, so that we can
8672ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     *         disconnect if this is the current network.
8682ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle     */
86973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    WifiConfiguration disableEphemeralNetwork(String ssid) {
87073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (ssid == null) {
8712ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle            return null;
8722ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle        }
8732ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
87473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        WifiConfiguration foundConfig = mConfiguredNetworks.getEphemeralForCurrentUser(ssid);
8752ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
87673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mDeletedEphemeralSSIDs.add(ssid);
877646ee7704694ef70c0dd3c707170163361ed504aRandy Pan        logd("Forget ephemeral SSID " + ssid + " num=" + mDeletedEphemeralSSIDs.size());
8782ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
87931891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        if (foundConfig != null) {
880646ee7704694ef70c0dd3c707170163361ed504aRandy Pan            logd("Found ephemeral config in disableEphemeralNetwork: " + foundConfig.networkId);
8812ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle        }
8822ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
883b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        writeKnownNetworkHistory();
8842ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle        return foundConfig;
8852ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle    }
8862ce99b40c36ed0352b31aa85d5f9383d5f0506f5vandwalle
887155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
888155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Forget the specified network and save config
889155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
890155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param netId network to forget
891155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return {@code true} if it succeeds, {@code false} otherwise
892155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
893155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    boolean forgetNetwork(int netId) {
89473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (mShowNetworks) localLogNetwork("forgetNetwork", netId);
8952d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        if (!removeNetwork(netId)) {
8962d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            loge("Failed to forget network " + netId);
897155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return false;
898155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
8992d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        saveConfig();
9002d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        writeKnownNetworkHistory();
9012d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return true;
902155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
903155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
904155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
905155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Add/update a network. Note that there is no saveConfig operation.
906155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * This function is retained for compatibility with the public
907155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * API. The more powerful saveNetwork() is used by the
908155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * state machine
909155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
910155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param config wifi configuration to add/update
911155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return network Id
912155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
9132f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle    int addOrUpdateNetwork(WifiConfiguration config, int uid) {
9140fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowski        if (config == null || !WifiConfigurationUtil.isVisibleToAnyProfile(config,
91506636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan                mUserManager.getProfiles(mCurrentUserId))) {
916bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return WifiConfiguration.INVALID_NETWORK_ID;
917bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
91803e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
91973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (mShowNetworks) localLogNetwork("addOrUpdateNetwork id=", config.networkId);
920d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        if (config.isPasspoint()) {
92103e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            /* create a temporary SSID with providerFriendlyName */
92203e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            Long csum = getChecksum(config.FQDN);
92303e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            config.SSID = csum.toString();
9245f30066b5609002673289860cd1cdae49c5e83dcJan Nordqvist            config.enterpriseConfig.setDomainSuffixMatch(config.FQDN);
92503e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        }
92603e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
9270eebae7334d6129f7ca1344e4b20199794994358vandwalle        NetworkUpdateResult result = addOrUpdateNetworkNative(config, uid);
928155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
929bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            WifiConfiguration conf = mConfiguredNetworks.getForCurrentUser(result.getNetworkId());
930952d359198cb1f04c180fc0f795dc316fe97cb5evandwalle            if (conf != null) {
93173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                sendConfiguredNetworksChangedBroadcast(
93273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        conf,
93373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        result.isNewNetwork
93473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                                ? WifiManager.CHANGE_REASON_ADDED
93573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                                : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
936952d359198cb1f04c180fc0f795dc316fe97cb5evandwalle            }
937155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
93803e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
939155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return result.getNetworkId();
940155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
941155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
9422e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    public int addPasspointManagementObject(String managementObject) {
9432e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        try {
9442e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            mMOManager.addSP(managementObject);
9452e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return 0;
9462e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        } catch (IOException | SAXException e) {
9472e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return -1;
9482e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
9492e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    }
9502e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
9512e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    public int modifyPasspointMo(String fqdn, List<PasspointManagementObjectDefinition> mos) {
9522e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        try {
9532e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return mMOManager.modifySP(fqdn, mos);
9542e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        } catch (IOException | SAXException e) {
9552e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return -1;
9562e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
9572e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    }
9582e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
9592e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    public boolean queryPasspointIcon(long bssid, String fileName) {
9602e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        return mSupplicantBridge.doIconQuery(bssid, fileName);
9612e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    }
9622e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
9632e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    public int matchProviderWithCurrentNetwork(String fqdn) {
964308a06a125932081304655cda8374ffcf0772b3cSamuel Tan        ScanDetail scanDetail = null;
965308a06a125932081304655cda8374ffcf0772b3cSamuel Tan        synchronized (mActiveScanDetailLock) {
966308a06a125932081304655cda8374ffcf0772b3cSamuel Tan            scanDetail = mActiveScanDetail;
967308a06a125932081304655cda8374ffcf0772b3cSamuel Tan        }
9682e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        if (scanDetail == null) {
9692e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return PasspointMatch.None.ordinal();
9702e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
9712e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        HomeSP homeSP = mMOManager.getHomeSP(fqdn);
9722e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        if (homeSP == null) {
9732e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return PasspointMatch.None.ordinal();
9742e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
9752e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
9762e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        ANQPData anqpData = mAnqpCache.getEntry(scanDetail.getNetworkDetail());
9772e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
9782e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        Map<Constants.ANQPElementType, ANQPElement> anqpElements =
9792e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                anqpData != null ? anqpData.getANQPElements() : null;
9802e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
9812e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        return homeSP.match(scanDetail.getNetworkDetail(), anqpElements, mSIMAccessor).ordinal();
9822e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    }
983b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle
984b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle    /**
9855c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * General PnoNetwork list sorting algorithm:
9865c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * 1, Place the fully enabled networks first. Among the fully enabled networks,
9875c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * sort them in the oder determined by the return of |compareConfigurations| method
9885c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * implementation.
9895c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * 2. Next place all the temporarily disabled networks. Among the temporarily disabled
9905c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * networks, sort them in the order determined by the return of |compareConfigurations| method
9915c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * implementation.
9925c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * 3. Place the permanently disabled networks last. The order among permanently disabled
9935c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * networks doesn't matter.
994b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle     */
9955c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    private static class PnoListComparator implements Comparator<WifiConfiguration> {
9965c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius
9975c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        public final int ENABLED_NETWORK_SCORE = 3;
9985c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        public final int TEMPORARY_DISABLED_NETWORK_SCORE = 2;
9995c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        public final int PERMANENTLY_DISABLED_NETWORK_SCORE = 1;
10005c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius
10015c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        @Override
10025c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        public int compare(WifiConfiguration a, WifiConfiguration b) {
10035c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            int configAScore = getPnoNetworkSortScore(a);
10045c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            int configBScore = getPnoNetworkSortScore(b);
10055c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            if (configAScore == configBScore) {
10065c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                return compareConfigurations(a, b);
10075c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            } else {
10085c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                return Integer.compare(configBScore, configAScore);
10095c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            }
1010b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle        }
1011b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle
10125c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        // This needs to be implemented by the connected/disconnected PNO list comparator.
10135c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) {
10145c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            return 0;
1015b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle        }
1016b0b0cc202b7d7aaad7b3f69d73e9b58ea2968b05Pierre Vandwalle
10175c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        /**
10185c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius         * Returns an integer representing a score for each configuration. The scores are assigned
10195c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius         * based on the status of the configuration. The scores are assigned according to the order:
10205c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius         * Fully enabled network > Temporarily disabled network > Permanently disabled network.
10215c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius         */
10225c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        private int getPnoNetworkSortScore(WifiConfiguration config) {
10235c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            if (config.getNetworkSelectionStatus().isNetworkEnabled()) {
10245c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                return ENABLED_NETWORK_SCORE;
10255c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            } else if (config.getNetworkSelectionStatus().isNetworkTemporaryDisabled()) {
10265c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                return TEMPORARY_DISABLED_NETWORK_SCORE;
10275c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            } else {
10285c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                return PERMANENTLY_DISABLED_NETWORK_SCORE;
10295c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            }
10305c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius        }
10315c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    }
1032ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius
1033ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius    /**
10345c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * Disconnected PnoNetwork list sorting algorithm:
10355c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * Place the configurations in descending order of their |numAssociation| values. If networks
10365c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * have the same |numAssociation|, then sort them in descending order of their |priority|
1037ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * values.
1038ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     */
10395c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    private static final PnoListComparator sDisconnectedPnoListComparator =
10405c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            new PnoListComparator() {
10415c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                @Override
10425c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) {
10435c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                    if (a.numAssociation != b.numAssociation) {
10445c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                        return Long.compare(b.numAssociation, a.numAssociation);
1045ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius                    } else {
10465c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                        return Integer.compare(b.priority, a.priority);
1047ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius                    }
1048ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius                }
1049ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius            };
1050ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius
1051ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius    /**
1052ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * Retrieves an updated list of priorities for all the saved networks before
10535c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * enabling disconnected PNO (wpa_supplicant based PNO).
10545c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     *
1055ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * wpa_supplicant uses the priority of networks to build the list of SSID's to monitor
1056ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * during PNO. If there are a lot of saved networks, this list will be truncated and we
1057ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * might end up not connecting to the networks we use most frequently. So, We want the networks
1058ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * to be re-sorted based on the relative |numAssociation| values.
1059ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     *
1060ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     * @return list of networks with updated priorities.
1061ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius     */
1062329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius    public ArrayList<WifiScanner.PnoSettings.PnoNetwork> retrieveDisconnectedPnoNetworkList() {
1063329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        return retrievePnoNetworkList(sDisconnectedPnoListComparator);
10645c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    }
10655c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius
10665c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    /**
10675c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * Connected PnoNetwork list sorting algorithm:
10685c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * Place the configurations with |lastSeenInQualifiedNetworkSelection| set first. If networks
10695c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * have the same value, then sort them in descending order of their |numAssociation|
10705c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * values.
10715c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     */
10725c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    private static final PnoListComparator sConnectedPnoListComparator =
10735c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            new PnoListComparator() {
10745c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                @Override
10755c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) {
10765c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                    boolean isConfigALastSeen =
10775c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                            a.getNetworkSelectionStatus().getSeenInLastQualifiedNetworkSelection();
10785c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                    boolean isConfigBLastSeen =
10795c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                            b.getNetworkSelectionStatus().getSeenInLastQualifiedNetworkSelection();
10805c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                    if (isConfigALastSeen != isConfigBLastSeen) {
10815c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                        return Boolean.compare(isConfigBLastSeen, isConfigALastSeen);
10825c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                    } else {
10835c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                        return Long.compare(b.numAssociation, a.numAssociation);
10845c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                    }
10855c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius                }
10865c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius            };
10875c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius
10885c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    /**
10895c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * Retrieves an updated list of priorities for all the saved networks before
10905c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * enabling connected PNO (HAL based ePno).
10915c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     *
10925c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * @return list of networks with updated priorities.
10935c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     */
10948c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius    public ArrayList<WifiScanner.PnoSettings.PnoNetwork> retrieveConnectedPnoNetworkList() {
1095329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        return retrievePnoNetworkList(sConnectedPnoListComparator);
10965c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    }
10975c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius
10985c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius    /**
10998c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius     * Create a PnoNetwork object from the provided WifiConfiguration.
11008c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius     * @param config Configuration corresponding to the network.
11018c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius     * @param newPriority New priority to be assigned to the network.
11028c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius     */
11038c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius    private static WifiScanner.PnoSettings.PnoNetwork createPnoNetworkFromWifiConfiguration(
11048c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius            WifiConfiguration config, int newPriority) {
11058c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        WifiScanner.PnoSettings.PnoNetwork pnoNetwork =
11068c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius                new WifiScanner.PnoSettings.PnoNetwork(config.SSID);
11078c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        pnoNetwork.networkId = config.networkId;
11088c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        pnoNetwork.priority = newPriority;
11098c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        if (config.hiddenSSID) {
11108c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius            pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN;
11118c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        }
11128c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND;
11138c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND;
11148c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
11158c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius            pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_PSK;
11168c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)
11178c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius                || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
11188c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius            pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_EAPOL;
11198c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        } else {
11208c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius            pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN;
11218c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        }
11228c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        return pnoNetwork;
11238c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius    }
11248c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius
11258c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius    /**
11265c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * Retrieves an updated list of priorities for all the saved networks before
11275c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * enabling/disabling PNO.
11285c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     *
1129329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius     * @param pnoListComparator The comparator to use for sorting networks
11305c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     * @return list of networks with updated priorities.
11315c3c06082b24f9ff0d479e82a63b52220c86598bRoshan Pius     */
11328c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius    private ArrayList<WifiScanner.PnoSettings.PnoNetwork> retrievePnoNetworkList(
1133329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius            PnoListComparator pnoListComparator) {
11348c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius        ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoList = new ArrayList<>();
1135ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius        ArrayList<WifiConfiguration> wifiConfigurations =
11368c0c14b2c98bc26e6a09f66cff1244f0a30f44cbRoshan Pius                new ArrayList<>(mConfiguredNetworks.valuesForCurrentUser());
1137329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        Collections.sort(wifiConfigurations, pnoListComparator);
1138329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        // Let's use the network list size as the highest priority and then go down from there.
1139329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        // So, the most frequently connected network has the highest priority now.
1140329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        int priority = wifiConfigurations.size();
1141329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius        for (WifiConfiguration config : wifiConfigurations) {
1142329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius            pnoList.add(createPnoNetworkFromWifiConfiguration(config, priority));
1143329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius            priority--;
1144ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius        }
1145ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius        return pnoList;
1146ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius    }
1147ac9ad3283508db15b65b1cbb89b841278973276bRoshan Pius
1148155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1149155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Remove a network. Note that there is no saveConfig operation.
1150155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * This function is retained for compatibility with the public
1151155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * API. The more powerful forgetNetwork() is used by the
1152155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * state machine for network removal
1153155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
1154155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param netId network to be removed
1155155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return {@code true} if it succeeds, {@code false} otherwise
1156155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1157155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    boolean removeNetwork(int netId) {
115873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (mShowNetworks) localLogNetwork("removeNetwork", netId);
1159bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
1160dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        if (!removeConfigAndSendBroadcastIfNeeded(config)) {
1161bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return false;
1162bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
1163dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        if (config.isPasspoint()) {
11642d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            writePasspointConfigs(config.FQDN, null);
1165155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
11662d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return true;
1167155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1168155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
116973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    private static Long getChecksum(String source) {
117003e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        Checksum csum = new CRC32();
117103e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        csum.update(source.getBytes(), 0, source.getBytes().length);
117203e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        return csum.getValue();
117303e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande    }
117403e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
1175dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius    private boolean removeConfigWithoutBroadcast(WifiConfiguration config) {
1176dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        if (config == null) {
1177dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius            return false;
1178dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        }
1179dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        if (!mWifiConfigStore.removeNetwork(config)) {
1180dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius            loge("Failed to remove network " + config.networkId);
1181dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius            return false;
1182dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        }
118373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (config.configKey().equals(mLastSelectedConfiguration)) {
118473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            mLastSelectedConfiguration = null;
1185dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        }
1186dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        mConfiguredNetworks.remove(config.networkId);
1187dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        mScanDetailCaches.remove(config.networkId);
1188dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        return true;
1189dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius    }
1190117be607246604e875de62aa8cdd99700b77a2b4vandwalle
1191dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius    private boolean removeConfigAndSendBroadcastIfNeeded(WifiConfiguration config) {
1192dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        if (!removeConfigWithoutBroadcast(config)) {
1193dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius            return false;
1194dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        }
1195dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        String key = config.configKey();
119673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) {
1197dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius            logd("removeNetwork " + " key=" + key + " config.id=" + config.networkId);
1198dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        }
1199dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        writeIpAndProxyConfigurations();
1200dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
1201dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        if (!config.ephemeral) {
1202dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius            removeUserSelectionPreference(key);
1203dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        }
1204dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius        writeKnownNetworkHistory();
1205005c1ef113192f898499a407dd266393a8d6b076vandwalle        return true;
1206155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1207155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1208b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe    private void removeUserSelectionPreference(String configKey) {
1209b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        if (DBG) {
1210b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            Log.d(TAG, "removeUserSelectionPreference: key is " + configKey);
1211b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        }
1212b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        if (configKey == null) {
1213b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            return;
1214b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        }
1215b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1216b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
1217b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            String connectChoice = status.getConnectChoice();
1218b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            if (connectChoice != null && connectChoice.equals(configKey)) {
1219b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe                Log.d(TAG, "remove connect choice:" + connectChoice + " from " + config.SSID
1220b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe                        + " : " + config.networkId);
1221b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe                status.setConnectChoice(null);
1222b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe                status.setConnectChoiceTimestamp(WifiConfiguration.NetworkSelectionStatus
1223b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe                            .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
1224b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            }
1225b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        }
1226b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe    }
1227b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe
1228e487a4648dd41881e754f1224aaedead78a0777dSky Faber    /*
1229e487a4648dd41881e754f1224aaedead78a0777dSky Faber     * Remove all networks associated with an application
1230e487a4648dd41881e754f1224aaedead78a0777dSky Faber     *
1231e487a4648dd41881e754f1224aaedead78a0777dSky Faber     * @param packageName name of the package of networks to remove
1232e487a4648dd41881e754f1224aaedead78a0777dSky Faber     * @return {@code true} if all networks removed successfully, {@code false} otherwise
1233e487a4648dd41881e754f1224aaedead78a0777dSky Faber     */
1234faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee    boolean removeNetworksForApp(ApplicationInfo app) {
1235faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee        if (app == null || app.packageName == null) {
1236e487a4648dd41881e754f1224aaedead78a0777dSky Faber            return false;
1237e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
1238e487a4648dd41881e754f1224aaedead78a0777dSky Faber
1239e487a4648dd41881e754f1224aaedead78a0777dSky Faber        boolean success = true;
1240e487a4648dd41881e754f1224aaedead78a0777dSky Faber
1241e487a4648dd41881e754f1224aaedead78a0777dSky Faber        WifiConfiguration [] copiedConfigs =
1242bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                mConfiguredNetworks.valuesForCurrentUser().toArray(new WifiConfiguration[0]);
1243e487a4648dd41881e754f1224aaedead78a0777dSky Faber        for (WifiConfiguration config : copiedConfigs) {
1244faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            if (app.uid != config.creatorUid || !app.packageName.equals(config.creatorName)) {
1245faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                continue;
1246e487a4648dd41881e754f1224aaedead78a0777dSky Faber            }
124773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (mShowNetworks) {
1248faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                localLog("Removing network " + config.SSID
1249faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                         + ", application \"" + app.packageName + "\" uninstalled"
1250faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                         + " from user " + UserHandle.getUserId(app.uid));
1251faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            }
1252faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            success &= removeNetwork(config.networkId);
1253e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
1254e487a4648dd41881e754f1224aaedead78a0777dSky Faber
12552d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        saveConfig();
1256e487a4648dd41881e754f1224aaedead78a0777dSky Faber
1257e487a4648dd41881e754f1224aaedead78a0777dSky Faber        return success;
1258e487a4648dd41881e754f1224aaedead78a0777dSky Faber    }
1259e487a4648dd41881e754f1224aaedead78a0777dSky Faber
1260faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee    boolean removeNetworksForUser(int userId) {
1261faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee        boolean success = true;
1262faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee
1263faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee        WifiConfiguration[] copiedConfigs =
1264bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]);
1265faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee        for (WifiConfiguration config : copiedConfigs) {
1266faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            if (userId != UserHandle.getUserId(config.creatorUid)) {
1267faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                continue;
1268faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            }
1269faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            success &= removeNetwork(config.networkId);
127073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (mShowNetworks) {
1271faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                localLog("Removing network " + config.SSID
1272faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee                        + ", user " + userId + " removed");
1273faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee            }
1274faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee        }
1275faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee
1276faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee        return success;
1277faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee    }
1278faa2ce7f93eef2c436796fb1ea3574e2d1412491Robin Lee
1279155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1280155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Enable a network. Note that there is no saveConfig operation.
1281155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * This function is retained for compatibility with the public
1282155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * API. The more powerful selectNetwork()/saveNetwork() is used by the
1283155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * state machine for connecting to a network
1284155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
1285ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius     * @param config network to be enabled
1286155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return {@code true} if it succeeds, {@code false} otherwise
1287155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1288ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius    boolean enableNetwork(WifiConfiguration config, boolean disableOthers, int uid) {
1289bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        if (config == null) {
1290bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return false;
1291bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
1292ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius
1293ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius        updateNetworkSelectionStatus(
1294ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius                config, WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
1295ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius        setLatestUserSelectedConfiguration(config);
12969d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius        boolean ret = true;
1297155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (disableOthers) {
1298ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius            ret = selectNetworkWithoutBroadcast(config.networkId);
129973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (sVDBG) {
1300ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius                localLogNetwork("enableNetwork(disableOthers=true, uid=" + uid + ") ",
1301ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius                        config.networkId);
130273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            }
1303ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius            updateLastConnectUid(config, uid);
1304b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            writeKnownNetworkHistory();
1305155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            sendConfiguredNetworksChangedBroadcast();
1306155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        } else {
1307ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius            if (sVDBG) localLogNetwork("enableNetwork(disableOthers=false) ", config.networkId);
1308ad36265b6efc83414daf7e38283826482dfb5045Roshan Pius            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_CONFIG_CHANGE);
1309155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1310155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return ret;
1311155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1312155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
13139d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius    boolean selectNetworkWithoutBroadcast(int netId) {
13142d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.selectNetwork(
13152d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                mConfiguredNetworks.getForCurrentUser(netId),
13162d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                mConfiguredNetworks.valuesForCurrentUser());
13179d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius    }
1318155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
13199d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius    /**
13209d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius     * Disable a network in wpa_supplicant.
13219d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius     */
13229d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius    boolean disableNetworkNative(WifiConfiguration config) {
13232d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.disableNetwork(config);
1324155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1325155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
13269d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius    /**
13279d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius     * Disable all networks in wpa_supplicant.
13289d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius     */
13299d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius    void disableAllNetworksNative() {
13302d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.disableAllNetworks(mConfiguredNetworks.valuesForCurrentUser());
1331155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
13329d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius
1333155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1334155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Disable a network. Note that there is no saveConfig operation.
1335155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param netId network to be disabled
1336155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return {@code true} if it succeeds, {@code false} otherwise
1337155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1338155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    boolean disableNetwork(int netId) {
13392d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.disableNetwork(mConfiguredNetworks.getForCurrentUser(netId));
1340155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1341155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1342155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
13438f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Update a network according to the update reason and its current state
13448f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param netId The network ID of the network need update
13458f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param reason The reason to update the network
13468f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @return false if no change made to the input configure file, can due to error or need not
13478f0f666c8bdaf508f191f8590755140b92d970eaxinhe     *         true the input config file has been changed
1348155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
13498f0f666c8bdaf508f191f8590755140b92d970eaxinhe    boolean updateNetworkSelectionStatus(int netId, int reason) {
13508f0f666c8bdaf508f191f8590755140b92d970eaxinhe        WifiConfiguration config = getWifiConfiguration(netId);
13518f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return updateNetworkSelectionStatus(config, reason);
13528f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
1353f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
13548f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
13558f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Update a network according to the update reason and its current state
13568f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param config the network need update
13578f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param reason The reason to update the network
13588f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @return false if no change made to the input configure file, can due to error or need not
13598f0f666c8bdaf508f191f8590755140b92d970eaxinhe     *         true the input config file has been changed
13608f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
13618f0f666c8bdaf508f191f8590755140b92d970eaxinhe    boolean updateNetworkSelectionStatus(WifiConfiguration config, int reason) {
13628f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (config == null) {
13638f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return false;
13648f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
13658f0f666c8bdaf508f191f8590755140b92d970eaxinhe
13668f0f666c8bdaf508f191f8590755140b92d970eaxinhe        WifiConfiguration.NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
13678f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (reason == WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
13688f0f666c8bdaf508f191f8590755140b92d970eaxinhe            updateNetworkStatus(config, WifiConfiguration.NetworkSelectionStatus
13698f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    .NETWORK_SELECTION_ENABLE);
13708f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe            localLog("Enable network:" + config.configKey());
13718f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return true;
13728f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
13738f0f666c8bdaf508f191f8590755140b92d970eaxinhe
13748f0f666c8bdaf508f191f8590755140b92d970eaxinhe        networkStatus.incrementDisableReasonCounter(reason);
13758f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (DBG) {
13768f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe            localLog("Network:" + config.SSID + "disable counter of "
13778f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    + WifiConfiguration.NetworkSelectionStatus.getNetworkDisableReasonString(reason)
13788f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    + " is: " + networkStatus.getDisableReasonCounter(reason) + "and threshold is: "
13798f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    + NETWORK_SELECTION_DISABLE_THRESHOLD[reason]);
13808f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
13818f0f666c8bdaf508f191f8590755140b92d970eaxinhe
13828f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (networkStatus.getDisableReasonCounter(reason)
13838f0f666c8bdaf508f191f8590755140b92d970eaxinhe                >= NETWORK_SELECTION_DISABLE_THRESHOLD[reason]) {
13848f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return updateNetworkStatus(config, reason);
13858f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
13868f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return true;
13878f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
13888f0f666c8bdaf508f191f8590755140b92d970eaxinhe
13898f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
13908f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Check the config. If it is temporarily disabled, check the disable time is expired or not, If
13918f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * expired, enabled it again for qualified network selection.
13928f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param networkId the id of the network to be checked for possible unblock (due to timeout)
13938f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @return true if network status has been changed
13948f0f666c8bdaf508f191f8590755140b92d970eaxinhe     *         false network status is not changed
13958f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
1396ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius    public boolean tryEnableQualifiedNetwork(int networkId) {
13978f0f666c8bdaf508f191f8590755140b92d970eaxinhe        WifiConfiguration config = getWifiConfiguration(networkId);
13988f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (config == null) {
13998f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe            localLog("updateQualifiedNetworkstatus invalid network.");
14008f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return false;
14018f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
14028f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return tryEnableQualifiedNetwork(config);
14038f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
14048f0f666c8bdaf508f191f8590755140b92d970eaxinhe
14058f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
14068f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Check the config. If it is temporarily disabled, check the disable is expired or not, If
14078f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * expired, enabled it again for qualified network selection.
14088f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param config network to be checked for possible unblock (due to timeout)
14098f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @return true if network status has been changed
14108f0f666c8bdaf508f191f8590755140b92d970eaxinhe     *         false network status is not changed
14118f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
1412ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius    private boolean tryEnableQualifiedNetwork(WifiConfiguration config) {
14138f0f666c8bdaf508f191f8590755140b92d970eaxinhe        WifiConfiguration.NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
14148f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (networkStatus.isNetworkTemporaryDisabled()) {
14158f0f666c8bdaf508f191f8590755140b92d970eaxinhe            //time difference in minutes
1416ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius            long timeDifference =
1417ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius                    (mClock.elapsedRealtime() - networkStatus.getDisableTime()) / 1000 / 60;
14188f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (timeDifference < 0 || timeDifference
14198f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    >= NETWORK_SELECTION_DISABLE_TIMEOUT[
14208f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    networkStatus.getNetworkSelectionDisableReason()]) {
14218f0f666c8bdaf508f191f8590755140b92d970eaxinhe                updateNetworkSelectionStatus(config.networkId,
14228f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        networkStatus.NETWORK_SELECTION_ENABLE);
14238f0f666c8bdaf508f191f8590755140b92d970eaxinhe                return true;
1424f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
1425f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
14268f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return false;
14278f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
14288f0f666c8bdaf508f191f8590755140b92d970eaxinhe
14298f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
14308f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Update a network's status. Note that there is no saveConfig operation.
14318f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param config network to be updated
14328f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param reason reason code for updated
14338f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @return false if no change made to the input configure file, can due to error or need not
14348f0f666c8bdaf508f191f8590755140b92d970eaxinhe     *         true the input config file has been changed
14358f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
14368f0f666c8bdaf508f191f8590755140b92d970eaxinhe    boolean updateNetworkStatus(WifiConfiguration config, int reason) {
14378f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe        localLog("updateNetworkStatus:" + (config == null ? null : config.SSID));
14388f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (config == null) {
14398f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return false;
14408f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
14418f0f666c8bdaf508f191f8590755140b92d970eaxinhe
14428f0f666c8bdaf508f191f8590755140b92d970eaxinhe        WifiConfiguration.NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
14438f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (reason < 0 || reason >= WifiConfiguration.NetworkSelectionStatus
14448f0f666c8bdaf508f191f8590755140b92d970eaxinhe                .NETWORK_SELECTION_DISABLED_MAX) {
14458f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe            localLog("Invalid Network disable reason:" + reason);
14468f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return false;
14478f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
14488f0f666c8bdaf508f191f8590755140b92d970eaxinhe
14498f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (reason == WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) {
14508f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (networkStatus.isNetworkEnabled()) {
14518f0f666c8bdaf508f191f8590755140b92d970eaxinhe                if (DBG) {
14528f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe                    localLog("Need not change Qualified network Selection status since"
14538f0f666c8bdaf508f191f8590755140b92d970eaxinhe                            + " already enabled");
14548f0f666c8bdaf508f191f8590755140b92d970eaxinhe                }
14558f0f666c8bdaf508f191f8590755140b92d970eaxinhe                return false;
14568f0f666c8bdaf508f191f8590755140b92d970eaxinhe            }
14578f0f666c8bdaf508f191f8590755140b92d970eaxinhe            networkStatus.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
14588f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    .NETWORK_SELECTION_ENABLED);
14598f0f666c8bdaf508f191f8590755140b92d970eaxinhe            networkStatus.setNetworkSelectionDisableReason(reason);
14608f0f666c8bdaf508f191f8590755140b92d970eaxinhe            networkStatus.setDisableTime(
14618f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    WifiConfiguration.NetworkSelectionStatus
14628f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
14638f0f666c8bdaf508f191f8590755140b92d970eaxinhe            networkStatus.clearDisableReasonCounter();
14648f0f666c8bdaf508f191f8590755140b92d970eaxinhe            String disableTime = DateFormat.getDateTimeInstance().format(new Date());
14658f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (DBG) {
14668f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe                localLog("Re-enable network: " + config.SSID + " at " + disableTime);
1467537324a497615d07b67ba4582e9aaababd77afd6Vinit Deshpande            }
14688f0f666c8bdaf508f191f8590755140b92d970eaxinhe            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_CONFIG_CHANGE);
14698f0f666c8bdaf508f191f8590755140b92d970eaxinhe        } else {
14708f0f666c8bdaf508f191f8590755140b92d970eaxinhe            //disable the network
14718f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (networkStatus.isNetworkPermanentlyDisabled()) {
14728f0f666c8bdaf508f191f8590755140b92d970eaxinhe                //alreay permanent disable
14738f0f666c8bdaf508f191f8590755140b92d970eaxinhe                if (DBG) {
14748f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe                    localLog("Do nothing. Alreay permanent disabled! "
14758f0f666c8bdaf508f191f8590755140b92d970eaxinhe                            + WifiConfiguration.NetworkSelectionStatus
14768f0f666c8bdaf508f191f8590755140b92d970eaxinhe                            .getNetworkDisableReasonString(reason));
14778f0f666c8bdaf508f191f8590755140b92d970eaxinhe                }
14788f0f666c8bdaf508f191f8590755140b92d970eaxinhe                return false;
14798f0f666c8bdaf508f191f8590755140b92d970eaxinhe            } else if (networkStatus.isNetworkTemporaryDisabled()
14808f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    && reason < WifiConfiguration.NetworkSelectionStatus
14818f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    .DISABLED_TLS_VERSION_MISMATCH) {
14828f0f666c8bdaf508f191f8590755140b92d970eaxinhe                //alreay temporarily disable
14838f0f666c8bdaf508f191f8590755140b92d970eaxinhe                if (DBG) {
14848f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe                    localLog("Do nothing. Already temporarily disabled! "
14858f0f666c8bdaf508f191f8590755140b92d970eaxinhe                            + WifiConfiguration.NetworkSelectionStatus
14868f0f666c8bdaf508f191f8590755140b92d970eaxinhe                            .getNetworkDisableReasonString(reason));
14878f0f666c8bdaf508f191f8590755140b92d970eaxinhe                }
14888f0f666c8bdaf508f191f8590755140b92d970eaxinhe                return false;
14898f0f666c8bdaf508f191f8590755140b92d970eaxinhe            }
14908f0f666c8bdaf508f191f8590755140b92d970eaxinhe
14918f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (networkStatus.isNetworkEnabled()) {
14929d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius                disableNetworkNative(config);
14938f0f666c8bdaf508f191f8590755140b92d970eaxinhe                sendConfiguredNetworksChangedBroadcast(config,
14948f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        WifiManager.CHANGE_REASON_CONFIG_CHANGE);
14958f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe                localLog("Disable network " + config.SSID + " reason:"
14968f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        + WifiConfiguration.NetworkSelectionStatus
14978f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        .getNetworkDisableReasonString(reason));
14988f0f666c8bdaf508f191f8590755140b92d970eaxinhe            }
14998f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (reason < WifiConfiguration.NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) {
15008f0f666c8bdaf508f191f8590755140b92d970eaxinhe                networkStatus.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
15018f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        .NETWORK_SELECTION_TEMPORARY_DISABLED);
1502ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius                networkStatus.setDisableTime(mClock.elapsedRealtime());
15038f0f666c8bdaf508f191f8590755140b92d970eaxinhe            } else {
15048f0f666c8bdaf508f191f8590755140b92d970eaxinhe                networkStatus.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
15058f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        .NETWORK_SELECTION_PERMANENTLY_DISABLED);
15068f0f666c8bdaf508f191f8590755140b92d970eaxinhe            }
15078f0f666c8bdaf508f191f8590755140b92d970eaxinhe            networkStatus.setNetworkSelectionDisableReason(reason);
15088f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (DBG) {
15098f0f666c8bdaf508f191f8590755140b92d970eaxinhe                String disableTime = DateFormat.getDateTimeInstance().format(new Date());
15108f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe                localLog("Network:" + config.SSID + "Configure new status:"
15118f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        + networkStatus.getNetworkStatusString() + " with reason:"
15128f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        + networkStatus.getNetworkDisableReasonString() + " at: " + disableTime);
1513537324a497615d07b67ba4582e9aaababd77afd6Vinit Deshpande            }
15140eebae7334d6129f7ca1344e4b20199794994358vandwalle        }
15158f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return true;
15168f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
15178f0f666c8bdaf508f191f8590755140b92d970eaxinhe
1518155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1519155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Save the configured networks in supplicant to disk
1520155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return {@code true} if it succeeds, {@code false} otherwise
1521155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1522155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    boolean saveConfig() {
15232d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.saveConfig();
1524155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1525155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1526155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1527155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Start WPS pin method configuration with pin obtained
1528155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * from the access point
1529155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param config WPS configuration
1530155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return Wps result containing status and pin
1531155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1532155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) {
15332d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.startWpsWithPinFromAccessPoint(
15342d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                config, mConfiguredNetworks.valuesForCurrentUser());
1535155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1536155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1537155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
15388f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * Start WPS pin method configuration with obtained
1539155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * from the device
1540155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return WpsResult indicating status and pin
1541155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1542155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    WpsResult startWpsWithPinFromDevice(WpsInfo config) {
15432d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.startWpsWithPinFromDevice(
15442d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            config, mConfiguredNetworks.valuesForCurrentUser());
1545155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1546155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1547155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1548155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Start WPS push button configuration
1549155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param config WPS configuration
1550155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return WpsResult indicating status and pin
1551155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1552155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    WpsResult startWpsPbc(WpsInfo config) {
15532d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.startWpsPbc(
15542d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            config, mConfiguredNetworks.valuesForCurrentUser());
1555155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1556155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1557155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
15583b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti     * Fetch the static IP configuration for a given network id
1559155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
15603b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti    StaticIpConfiguration getStaticIpConfiguration(int netId) {
1561bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
15623b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti        if (config != null) {
15633b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti            return config.getStaticIpConfiguration();
15643b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti        }
1565155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return null;
1566155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1567155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1568155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
15693b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti     * Set the static IP configuration for a given network id
1570155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
15713b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti    void setStaticIpConfiguration(int netId, StaticIpConfiguration staticIpConfiguration) {
1572bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
1573155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (config != null) {
15743b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti            config.setStaticIpConfiguration(staticIpConfiguration);
1575155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1576155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1577155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1578155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1579f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * set default GW MAC address
1580f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
1581f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void setDefaultGwMacAddress(int netId, String macAddress) {
1582bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
1583f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (config != null) {
1584f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //update defaultGwMacAddress
1585f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            config.defaultGwMacAddress = macAddress;
1586f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
1587f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
1588f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
1589f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
1590f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /**
1591155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Fetch the proxy properties for a given network id
15928bc78bddb29cdd9e845f313fabb08c485aa40c21Jan Nordqvist     * @param netId id
1593d4d0c9ad1e3289702ec341521b9bd01b52e9c1d8Jason Monk     * @return ProxyInfo for the network id
1594155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1595d4d0c9ad1e3289702ec341521b9bd01b52e9c1d8Jason Monk    ProxyInfo getProxyProperties(int netId) {
1596bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
15973b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti        if (config != null) {
15983b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti            return config.getHttpProxy();
1599155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1600155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return null;
1601155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1602155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1603155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1604155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Return if the specified network is using static IP
16058bc78bddb29cdd9e845f313fabb08c485aa40c21Jan Nordqvist     * @param netId id
1606155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @return {@code true} if using static ip for netId
1607155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1608155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    boolean isUsingStaticIp(int netId) {
1609bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
16103ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        if (config != null && config.getIpAssignment() == IpAssignment.STATIC) {
1611155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return true;
1612155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1613155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return false;
1614155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1615155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
161686b1b52530bba4a35e81bd7c5d7d52139fa0c822Shirish Kalele    boolean isEphemeral(int netId) {
1617bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
161886b1b52530bba4a35e81bd7c5d7d52139fa0c822Shirish Kalele        return config != null && config.ephemeral;
161986b1b52530bba4a35e81bd7c5d7d52139fa0c822Shirish Kalele    }
162086b1b52530bba4a35e81bd7c5d7d52139fa0c822Shirish Kalele
16213ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin    boolean getMeteredHint(int netId) {
16223ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
16233ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin        return config != null && config.meteredHint;
16243ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin    }
16253ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin
1626155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1627155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Should be called when a single network configuration is made.
1628155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param network The network configuration that changed.
1629155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED,
1630155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE.
1631155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1632155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void sendConfiguredNetworksChangedBroadcast(WifiConfiguration network,
1633155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            int reason) {
1634155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
1635155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1636155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
1637155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network);
1638155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
1639155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1640155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1641155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1642155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
1643155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Should be called when multiple network configuration changes are made.
1644155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
1645155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void sendConfiguredNetworksChangedBroadcast() {
1646155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
1647155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1648155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true);
1649155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1650155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1651155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1652155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    void loadConfiguredNetworks() {
1653005c1ef113192f898499a407dd266393a8d6b076vandwalle
1654bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        final Map<String, WifiConfiguration> configs = new HashMap<>();
1655fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski        final SparseArray<Map<String, String>> networkExtras = new SparseArray<>();
16562d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mLastPriority = mWifiConfigStore.loadNetworks(configs, networkExtras);
1657155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1658bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        readNetworkHistory(configs);
1659bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        readPasspointConfig(configs, networkExtras);
1660bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
1661bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        // We are only now updating mConfiguredNetworks for two reasons:
1662bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        // 1) The information required to compute configKeys is spread across wpa_supplicant.conf
1663bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        //    and networkHistory.txt. Thus, we had to load both files first.
1664bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        // 2) mConfiguredNetworks caches a Passpoint network's FQDN the moment the network is added.
1665bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        //    Thus, we had to load the FQDNs first.
1666bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        mConfiguredNetworks.clear();
1667bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (Map.Entry<String, WifiConfiguration> entry : configs.entrySet()) {
1668bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            final String configKey = entry.getKey();
1669bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            final WifiConfiguration config = entry.getValue();
1670bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            if (!configKey.equals(config.configKey())) {
167173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (mShowNetworks) {
1672bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    log("Ignoring network " + config.networkId + " because the configKey loaded "
1673bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                            + "from wpa_supplicant.conf is not valid.");
1674bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                }
16752d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                mWifiConfigStore.removeNetwork(config);
1676bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                continue;
1677bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            }
1678bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            mConfiguredNetworks.put(config);
1679bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
1680bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
1681155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        readIpAndProxyConfigurations();
1682f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
1683155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        sendConfiguredNetworksChangedBroadcast();
1684155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
168573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (mShowNetworks) {
1686bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            localLog("loadConfiguredNetworks loaded " + mConfiguredNetworks.sizeForAllUsers()
1687bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    + " networks (for all users)");
168865b752f1da25f028a204a88264380c610866c027Mitchell Wills        }
1689155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1690bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        if (mConfiguredNetworks.sizeForAllUsers() == 0) {
169184649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande            // no networks? Lets log if the file contents
169284649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande            logKernelTime();
16932d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            logContents(WifiConfigStore.SUPPLICANT_CONFIG_FILE);
16942d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            logContents(WifiConfigStore.SUPPLICANT_CONFIG_FILE_BACKUP);
16952d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            logContents(WifiNetworkHistory.NETWORK_HISTORY_CONFIG_FILE);
169684649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        }
169784649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande    }
169884649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande
169984649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande    private void logContents(String file) {
170065b752f1da25f028a204a88264380c610866c027Mitchell Wills        localLogAndLogcat("--- Begin " + file + " ---");
170184649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        BufferedReader reader = null;
170284649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        try {
170384649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande            reader = new BufferedReader(new FileReader(file));
170484649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
170565b752f1da25f028a204a88264380c610866c027Mitchell Wills                localLogAndLogcat(line);
170684649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande            }
170784649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        } catch (FileNotFoundException e) {
170865b752f1da25f028a204a88264380c610866c027Mitchell Wills            localLog("Could not open " + file + ", " + e);
170965b752f1da25f028a204a88264380c610866c027Mitchell Wills            Log.w(TAG, "Could not open " + file + ", " + e);
171084649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        } catch (IOException e) {
171165b752f1da25f028a204a88264380c610866c027Mitchell Wills            localLog("Could not read " + file + ", " + e);
171265b752f1da25f028a204a88264380c610866c027Mitchell Wills            Log.w(TAG, "Could not read " + file + ", " + e);
171384649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        } finally {
1714155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            try {
171584649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande                if (reader != null) {
171684649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande                    reader.close();
1717155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
1718155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            } catch (IOException e) {
171984649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande                // Just ignore the fact that we couldn't close
1720155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
1721155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
172265b752f1da25f028a204a88264380c610866c027Mitchell Wills        localLogAndLogcat("--- End " + file + " Contents ---");
1723155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1724155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
17259878c61bbd81176561991be025af44efc67332feWenchao Tong    private Map<String, String> readNetworkVariablesFromSupplicantFile(String key) {
17262d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.readNetworkVariablesFromSupplicantFile(key);
17279878c61bbd81176561991be025af44efc67332feWenchao Tong    }
17289878c61bbd81176561991be025af44efc67332feWenchao Tong
17292fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan    private String readNetworkVariableFromSupplicantFile(String configKey, String key) {
17302fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan        long start = SystemClock.elapsedRealtimeNanos();
17312fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan        Map<String, String> data = mWifiConfigStore.readNetworkVariablesFromSupplicantFile(key);
17322fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan        long end = SystemClock.elapsedRealtimeNanos();
17332fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan
173473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) {
17352fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan            localLog("readNetworkVariableFromSupplicantFile configKey=[" + configKey + "] key="
17362fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                    + key + " duration=" + (long) (end - start));
17372fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan        }
17382fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan        return data.get(configKey);
1739155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1740155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1741155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    boolean needsUnlockedKeyStore() {
1742155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1743155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // Any network using certificates to authenticate access requires
1744155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // unlocked key store; unless the certificates can be stored with
1745155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // hardware encryption
1746155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1747bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1748155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1749155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP)
1750155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    && config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
1751155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1752155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                if (needsSoftwareBackedKeyStore(config.enterpriseConfig)) {
1753155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    return true;
1754155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
1755155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
1756155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1757155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1758155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return false;
1759155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1760155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1761bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski    void readPasspointConfig(Map<String, WifiConfiguration> configs,
1762bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            SparseArray<Map<String, String>> networkExtras) {
1763af955ffa0082189fb688429732427c333f2491ceVinit Deshpande        List<HomeSP> homeSPs;
176403e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        try {
176505d2f4e6f26834a94b53187e6121379a16749088Jan Nordqvist            homeSPs = mMOManager.loadAllSPs();
176603e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        } catch (IOException e) {
176703e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            loge("Could not read " + PPS_FILE + " : " + e);
176803e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            return;
176903e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        }
177003e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
1771fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski        int matchedConfigs = 0;
1772fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski        for (HomeSP homeSp : homeSPs) {
1773fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski            String fqdn = homeSp.getFQDN();
1774fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski            Log.d(TAG, "Looking for " + fqdn);
1775bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            for (WifiConfiguration config : configs.values()) {
1776fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                Log.d(TAG, "Testing " + config.SSID);
1777fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski
1778fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                if (config.enterpriseConfig == null) {
1779fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    continue;
1780fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                }
1781fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                final String configFqdn =
17822d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                        networkExtras.get(config.networkId).get(WifiConfigStore.ID_STRING_KEY_FQDN);
1783fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                if (configFqdn != null && configFqdn.equals(fqdn)) {
1784fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    Log.d(TAG, "Matched " + configFqdn + " with " + config.networkId);
1785fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    ++matchedConfigs;
1786fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    config.FQDN = fqdn;
1787fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    config.providerFriendlyName = homeSp.getFriendlyName();
1788fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski
1789fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    HashSet<Long> roamingConsortiumIds = homeSp.getRoamingConsortiums();
1790fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    config.roamingConsortiumIds = new long[roamingConsortiumIds.size()];
1791fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    int i = 0;
1792fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    for (long id : roamingConsortiumIds) {
1793fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                        config.roamingConsortiumIds[i] = id;
1794fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                        i++;
1795fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    }
1796fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    IMSIParameter imsiParameter = homeSp.getCredential().getImsi();
1797fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    config.enterpriseConfig.setPlmn(
1798fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                            imsiParameter != null ? imsiParameter.toString() : null);
1799fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                    config.enterpriseConfig.setRealm(homeSp.getCredential().getRealm());
1800fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski                }
1801fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski            }
1802fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski        }
1803fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski
1804fbb081b7c28c18f0644701061a1ab38a4627db27Bartosz Fabianowski        Log.d(TAG, "loaded " + matchedConfigs + " passpoint configs");
180503e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande    }
180603e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
180731891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist    public void writePasspointConfigs(final String fqdn, final HomeSP homeSP) {
180803e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        mWriter.write(PPS_FILE, new DelayedDiskWrite.Writer() {
180903e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            @Override
181003e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            public void onWriteCalled(DataOutputStream out) throws IOException {
181103e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande                try {
181231891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist                    if (homeSP != null) {
18132e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                        mMOManager.addSP(homeSP);
18148f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    } else {
18152e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                        mMOManager.removeSP(fqdn);
181631891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist                    }
181703e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande                } catch (IOException e) {
181803e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande                    loge("Could not write " + PPS_FILE + " : " + e);
181903e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande                }
182003e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande            }
18212070c02cdd4fc765747121c9b02caf1b1bab89fbJan Nordqvist        }, false);
182203e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande    }
182303e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
1824c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /**
1825c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     *  Write network history, WifiConfigurations and mScanDetailCaches to file.
1826c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     */
1827c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private void readNetworkHistory(Map<String, WifiConfiguration> configs) {
1828c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        mWifiNetworkHistory.readNetworkHistory(configs,
1829c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                mScanDetailCaches,
1830c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                mDeletedEphemeralSSIDs);
1831c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
1832f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
1833c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /**
1834c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     *  Read Network history from file, merge it into mConfiguredNetowrks and mScanDetailCaches
1835c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     */
1836c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    public void writeKnownNetworkHistory() {
18373ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        final List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
1838bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
1839f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            networks.add(new WifiConfiguration(config));
1840e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle        }
1841c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        mWifiNetworkHistory.writeKnownNetworkHistory(networks,
1842c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                mScanDetailCaches,
1843c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                mDeletedEphemeralSSIDs);
1844b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim    }
1845b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim
1846edfae468ff546b7d52f8a7693520f27eecd087e4xinhe    public void setAndEnableLastSelectedConfiguration(int netId) {
184773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) {
1848646ee7704694ef70c0dd3c707170163361ed504aRandy Pan            logd("setLastSelectedConfiguration " + Integer.toString(netId));
1849117be607246604e875de62aa8cdd99700b77a2b4vandwalle        }
1850117be607246604e875de62aa8cdd99700b77a2b4vandwalle        if (netId == WifiConfiguration.INVALID_NETWORK_ID) {
185173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            mLastSelectedConfiguration = null;
18528f0f666c8bdaf508f191f8590755140b92d970eaxinhe            mLastSelectedTimeStamp = -1;
1853117be607246604e875de62aa8cdd99700b77a2b4vandwalle        } else {
1854117be607246604e875de62aa8cdd99700b77a2b4vandwalle            WifiConfiguration selected = getWifiConfiguration(netId);
1855117be607246604e875de62aa8cdd99700b77a2b4vandwalle            if (selected == null) {
185673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                mLastSelectedConfiguration = null;
18578f0f666c8bdaf508f191f8590755140b92d970eaxinhe                mLastSelectedTimeStamp = -1;
1858117be607246604e875de62aa8cdd99700b77a2b4vandwalle            } else {
185973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                mLastSelectedConfiguration = selected.configKey();
1860ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius                mLastSelectedTimeStamp = mClock.elapsedRealtime();
18618f0f666c8bdaf508f191f8590755140b92d970eaxinhe                updateNetworkSelectionStatus(netId,
18628f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
186373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (sVDBG) {
1864646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("setLastSelectedConfiguration now: " + mLastSelectedConfiguration);
1865ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle                }
1866117be607246604e875de62aa8cdd99700b77a2b4vandwalle            }
1867117be607246604e875de62aa8cdd99700b77a2b4vandwalle        }
1868117be607246604e875de62aa8cdd99700b77a2b4vandwalle    }
1869117be607246604e875de62aa8cdd99700b77a2b4vandwalle
18708f0f666c8bdaf508f191f8590755140b92d970eaxinhe    public void setLatestUserSelectedConfiguration(WifiConfiguration network) {
18718f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (network != null) {
187273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            mLastSelectedConfiguration = network.configKey();
1873ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius            mLastSelectedTimeStamp = mClock.elapsedRealtime();
18748f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
18758f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
18768f0f666c8bdaf508f191f8590755140b92d970eaxinhe
1877117be607246604e875de62aa8cdd99700b77a2b4vandwalle    public String getLastSelectedConfiguration() {
187873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        return mLastSelectedConfiguration;
1879117be607246604e875de62aa8cdd99700b77a2b4vandwalle    }
1880117be607246604e875de62aa8cdd99700b77a2b4vandwalle
18818f0f666c8bdaf508f191f8590755140b92d970eaxinhe    public long getLastSelectedTimeStamp() {
18828f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return mLastSelectedTimeStamp;
18838f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
18848f0f666c8bdaf508f191f8590755140b92d970eaxinhe
1885c9b047b4cb480edbb490516746cfcbb4a4eedeeavandwalle    public boolean isLastSelectedConfiguration(WifiConfiguration config) {
188673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        return (mLastSelectedConfiguration != null
1887c9b047b4cb480edbb490516746cfcbb4a4eedeeavandwalle                && config != null
188873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                && mLastSelectedConfiguration.equals(config.configKey()));
1889c9b047b4cb480edbb490516746cfcbb4a4eedeeavandwalle    }
1890c9b047b4cb480edbb490516746cfcbb4a4eedeeavandwalle
18913ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim    private void writeIpAndProxyConfigurations() {
18923ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        final SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
1893bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
18948f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (!config.ephemeral) {
18953ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim                networks.put(configKey(config), config.getIpConfiguration());
18963ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            }
18973ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        }
1898f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
189973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mIpconfigStore.writeIpAndProxyConfigurations(IP_CONFIG_FILE, networks);
19003ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim    }
1901b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim
19023ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim    private void readIpAndProxyConfigurations() {
1903c1bc5a14b94276421f741eaebb54daa8e63e4a05Roshan Pius        SparseArray<IpConfiguration> networks =
190473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                mIpconfigStore.readIpAndProxyConfigurations(IP_CONFIG_FILE);
1905b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim
1906f9715cc118c446695b2a82211881c7d6c5e59761vandwalle        if (networks == null || networks.size() == 0) {
19073ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            // IpConfigStore.readIpAndProxyConfigurations has already logged an error.
19083ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            return;
19093ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        }
1910b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim
19113ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        for (int i = 0; i < networks.size(); i++) {
19124d3bff566b2cd0c3fd4d118eb6aae42ab3e9b5ddLorenzo Colitti            int id = networks.keyAt(i);
1913bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            WifiConfiguration config = mConfiguredNetworks.getByConfigKeyIDForAllUsers(id);
191431891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist            // This is the only place the map is looked up through a (dangerous) hash-value!
1915cf5b8eb8a08c45bd4a82f1f4bb789c8a1b08744fvandwalle
19168f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (config == null || config.ephemeral) {
1917646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                logd("configuration found for missing network, nid=" + id
191873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        + ", ignored, networks.size=" + Integer.toString(networks.size()));
19193ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            } else {
19203ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim                config.setIpConfiguration(networks.valueAt(i));
1921155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
1922155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1923155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
1924155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
19250eebae7334d6129f7ca1344e4b20199794994358vandwalle    private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config, int uid) {
1926155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        /*
1927155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
1928155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * network configuration. Otherwise, the networkId should
1929155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * refer to an existing configuration.
1930155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         */
1931155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
193273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) localLog("addOrUpdateNetworkNative " + config.getPrintableSsid());
193383e653cbdcb944038927e4c25837895626354e61Jan Nordqvist        if (config.isPasspoint() && !mMOManager.isEnabled()) {
1934034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist            Log.e(TAG, "Passpoint is not enabled");
1935034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist            return new NetworkUpdateResult(INVALID_NETWORK_ID);
1936034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist        }
1937155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1938155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        boolean newNetwork = false;
19391d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        boolean existingMO = false;
19402d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        WifiConfiguration currentConfig;
1941155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        // networkId of INVALID_NETWORK_ID means we want to create a new network
19422d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        if (config.networkId == INVALID_NETWORK_ID) {
19432d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            // Try to fetch the existing config using configKey
19442d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            currentConfig = mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
19452d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            if (currentConfig != null) {
19462d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius                config.networkId = currentConfig.networkId;
1947155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            } else {
194831891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist                if (mMOManager.getHomeSP(config.FQDN) != null) {
1949646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("addOrUpdateNetworkNative passpoint " + config.FQDN
195003e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande                            + " was found, but no network Id");
19511d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    existingMO = true;
195203e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande                }
1953155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                newNetwork = true;
1954155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
19552d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        } else {
19562d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            // Fetch the existing config using networkID
19572d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            currentConfig = mConfiguredNetworks.getForCurrentUser(config.networkId);
1958155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
195993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
196093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        // originalConfig is used to check for credential and config changes that would cause
196193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        // HasEverConnected to be set to false.
196293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        WifiConfiguration originalConfig = new WifiConfiguration(currentConfig);
196393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
19642d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        if (!mWifiConfigStore.addOrUpdateNetwork(config, currentConfig)) {
1965155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return new NetworkUpdateResult(INVALID_NETWORK_ID);
1966155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
19672d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        int netId = config.networkId;
196808c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius        String savedConfigKey = config.configKey();
1969155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
1970155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        /* An update of the network variables requires reading them
1971155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * back from the supplicant to update mConfiguredNetworks.
1972155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * This is because some of the variables (SSID, wep keys &
1973155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * passphrases) reflect different values when read back than
1974155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * when written. For example, wep key is stored as * irrespective
19752d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius         * of the value sent to the supplicant.
1976155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         */
1977155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (currentConfig == null) {
1978155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            currentConfig = new WifiConfiguration();
19793ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            currentConfig.setIpAssignment(IpAssignment.DHCP);
19803ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            currentConfig.setProxySettings(ProxySettings.NONE);
1981155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            currentConfig.networkId = netId;
1982992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle            if (config != null) {
19830eebae7334d6129f7ca1344e4b20199794994358vandwalle                // Carry over the creation parameters
1984992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                currentConfig.selfAdded = config.selfAdded;
1985992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                currentConfig.didSelfAdd = config.didSelfAdd;
19860eebae7334d6129f7ca1344e4b20199794994358vandwalle                currentConfig.ephemeral = config.ephemeral;
19873ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin                currentConfig.meteredHint = config.meteredHint;
1988ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin                currentConfig.useExternalScores = config.useExternalScores;
1989992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                currentConfig.lastConnectUid = config.lastConnectUid;
1990992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                currentConfig.lastUpdateUid = config.lastUpdateUid;
1991992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle                currentConfig.creatorUid = config.creatorUid;
1992e487a4648dd41881e754f1224aaedead78a0777dSky Faber                currentConfig.creatorName = config.creatorName;
1993e487a4648dd41881e754f1224aaedead78a0777dSky Faber                currentConfig.lastUpdateName = config.lastUpdateName;
19940e3c67280365eb82fc15362a3b98a2c978bde766vandwalle                currentConfig.peerWifiConfiguration = config.peerWifiConfiguration;
19950047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande                currentConfig.FQDN = config.FQDN;
19960047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande                currentConfig.providerFriendlyName = config.providerFriendlyName;
19970047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande                currentConfig.roamingConsortiumIds = config.roamingConsortiumIds;
1998e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle                currentConfig.validatedInternetAccess = config.validatedInternetAccess;
1999e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle                currentConfig.numNoInternetAccessReports = config.numNoInternetAccessReports;
2000e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle                currentConfig.updateTime = config.updateTime;
2001e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle                currentConfig.creationTime = config.creationTime;
2002bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                currentConfig.shared = config.shared;
2003992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle            }
2004992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle            if (DBG) {
200531891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist                log("created new config netId=" + Integer.toString(netId)
2006e487a4648dd41881e754f1224aaedead78a0777dSky Faber                        + " uid=" + Integer.toString(currentConfig.creatorUid)
2007e487a4648dd41881e754f1224aaedead78a0777dSky Faber                        + " name=" + currentConfig.creatorName);
2008992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle            }
2009155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2010155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
201103e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        /* save HomeSP object for passpoint networks */
201231891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        HomeSP homeSP = null;
201331891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist
20141d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (!existingMO && config.isPasspoint()) {
2015a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist            try {
2016cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                if (config.updateIdentifier == null) {   // Only create an MO for r1 networks
2017cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                    Credential credential =
2018cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                            new Credential(config.enterpriseConfig, mKeyStore, !newNetwork);
2019cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                    HashSet<Long> roamingConsortiumIds = new HashSet<Long>();
2020cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                    for (Long roamingConsortiumId : config.roamingConsortiumIds) {
2021cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                        roamingConsortiumIds.add(roamingConsortiumId);
2022cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                    }
2023d9f37b2f3df18e96246db93ec4c2a5159b5d3915Vinit Deshpande
2024cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                    homeSP = new HomeSP(Collections.<String, Long>emptyMap(), config.FQDN,
2025cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                            roamingConsortiumIds, Collections.<String>emptySet(),
2026cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                            Collections.<Long>emptySet(), Collections.<Long>emptyList(),
2027cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                            config.providerFriendlyName, null, credential);
2028a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist
2029cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                    log("created a homeSP object for " + config.networkId + ":" + config.SSID);
2030cb3aa74733cef68dd30d5e6aa8f252cd749b4143Jan Nordqvist                }
20310047ccf563baa288777e06c6fe95d3681fcf5ccdVinit Deshpande
2032d9f37b2f3df18e96246db93ec4c2a5159b5d3915Vinit Deshpande                /* fix enterprise config properties for passpoint */
2033a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist                currentConfig.enterpriseConfig.setRealm(config.enterpriseConfig.getRealm());
2034a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist                currentConfig.enterpriseConfig.setPlmn(config.enterpriseConfig.getPlmn());
203573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            } catch (IOException ioe) {
203605d2f4e6f26834a94b53187e6121379a16749088Jan Nordqvist                Log.e(TAG, "Failed to create Passpoint config: " + ioe);
2037a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist                return new NetworkUpdateResult(INVALID_NETWORK_ID);
2038a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist            }
203903e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande        }
204003e92b925a595a1a467290a2d54ca2602cce9b9eVinit Deshpande
2041f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti        if (uid != WifiConfiguration.UNKNOWN_UID) {
20420eebae7334d6129f7ca1344e4b20199794994358vandwalle            if (newNetwork) {
20430eebae7334d6129f7ca1344e4b20199794994358vandwalle                currentConfig.creatorUid = uid;
20440eebae7334d6129f7ca1344e4b20199794994358vandwalle            } else {
20450eebae7334d6129f7ca1344e4b20199794994358vandwalle                currentConfig.lastUpdateUid = uid;
20460eebae7334d6129f7ca1344e4b20199794994358vandwalle            }
20470eebae7334d6129f7ca1344e4b20199794994358vandwalle        }
20480eebae7334d6129f7ca1344e4b20199794994358vandwalle
2049e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        // For debug, record the time the configuration was modified
2050e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        StringBuilder sb = new StringBuilder();
2051e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        sb.append("time=");
2052e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        Calendar c = Calendar.getInstance();
2053ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius        c.setTimeInMillis(mClock.currentTimeMillis());
2054e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
2055e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle
2056e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle        if (newNetwork) {
2057e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle            currentConfig.creationTime = sb.toString();
2058e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        } else {
2059e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle            currentConfig.updateTime = sb.toString();
2060e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle        }
2061e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle
20620eebae7334d6129f7ca1344e4b20199794994358vandwalle        if (currentConfig.status == WifiConfiguration.Status.ENABLED) {
20630eebae7334d6129f7ca1344e4b20199794994358vandwalle            // Make sure autojoin remain in sync with user modifying the configuration
20648f0f666c8bdaf508f191f8590755140b92d970eaxinhe            updateNetworkSelectionStatus(currentConfig.networkId,
20658f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
20660eebae7334d6129f7ca1344e4b20199794994358vandwalle        }
20670eebae7334d6129f7ca1344e4b20199794994358vandwalle
206873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (currentConfig.configKey().equals(getLastSelectedConfiguration())
206973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                && currentConfig.ephemeral) {
20708639f6266cb70bf92d1561af43ac2d7b2b97298eJeff Davidson            // Make the config non-ephemeral since the user just explicitly clicked it.
20718639f6266cb70bf92d1561af43ac2d7b2b97298eJeff Davidson            currentConfig.ephemeral = false;
207273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (DBG) {
207373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                log("remove ephemeral status netId=" + Integer.toString(netId)
207473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        + " " + currentConfig.configKey());
207573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            }
20768639f6266cb70bf92d1561af43ac2d7b2b97298eJeff Davidson        }
20778639f6266cb70bf92d1561af43ac2d7b2b97298eJeff Davidson
207873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) log("will read network variables netId=" + Integer.toString(netId));
2079f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2080155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        readNetworkVariables(currentConfig);
208108c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius        // When we read back the config from wpa_supplicant, some of the default values are set
208208c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius        // which could change the configKey.
208308c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius        if (!savedConfigKey.equals(currentConfig.configKey())) {
208473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (!mWifiConfigStore.saveNetworkMetadata(currentConfig)) {
208508c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius                loge("Failed to set network metadata. Removing config " + config.networkId);
208608c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius                mWifiConfigStore.removeNetwork(config);
208708c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius                return new NetworkUpdateResult(INVALID_NETWORK_ID);
208808c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius            }
208908c939fa7f1fcd666a3076b6921864b4bf70308fRoshan Pius        }
2090155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
209193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        boolean passwordChanged = false;
209293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        // check passed in config to see if it has more than a password set.
209393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (!newNetwork && config.preSharedKey != null && !config.preSharedKey.equals("*")) {
209493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            passwordChanged = true;
209593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
209693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
209793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (newNetwork || passwordChanged || wasCredentialChange(originalConfig, currentConfig)) {
209893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            currentConfig.getNetworkSelectionStatus().setHasEverConnected(false);
209993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
210093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
2101e487a4648dd41881e754f1224aaedead78a0777dSky Faber        // Persist configuration paramaters that are not saved by supplicant.
2102e487a4648dd41881e754f1224aaedead78a0777dSky Faber        if (config.lastUpdateName != null) {
2103e487a4648dd41881e754f1224aaedead78a0777dSky Faber            currentConfig.lastUpdateName = config.lastUpdateName;
2104e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
2105f7afe8414224cb9a959c18763a489ef33a8265feLorenzo Colitti        if (config.lastUpdateUid != WifiConfiguration.UNKNOWN_UID) {
2106e487a4648dd41881e754f1224aaedead78a0777dSky Faber            currentConfig.lastUpdateUid = config.lastUpdateUid;
2107e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
2108e487a4648dd41881e754f1224aaedead78a0777dSky Faber
2109bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        mConfiguredNetworks.put(currentConfig);
2110155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2111cc018db319baff34c9d36928d04c2c420257498fRoshan Pius        NetworkUpdateResult result =
2112cc018db319baff34c9d36928d04c2c420257498fRoshan Pius                writeIpAndProxyConfigurationsOnChange(currentConfig, config, newNetwork);
2113155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        result.setIsNewNetwork(newNetwork);
2114155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        result.setNetworkId(netId);
2115e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle
211631891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        if (homeSP != null) {
211731891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist            writePasspointConfigs(null, homeSP);
211831891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        }
2119b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe
21202d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        saveConfig();
2121b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe        writeKnownNetworkHistory();
2122e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle
2123155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return result;
2124155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
2125155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
212693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein    private boolean wasBitSetUpdated(BitSet originalBitSet, BitSet currentBitSet) {
212793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (originalBitSet != null && currentBitSet != null) {
212893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            // both configs have values set, check if they are different
212993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            if (!originalBitSet.equals(currentBitSet)) {
213093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                // the BitSets are different
213193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                return true;
213293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            }
213393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        } else if (originalBitSet != null || currentBitSet != null) {
213493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
213593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
213693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        return false;
213793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein    }
213893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
213993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein    private boolean wasCredentialChange(WifiConfiguration originalConfig,
214093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            WifiConfiguration currentConfig) {
214193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        // Check if any core WifiConfiguration parameters changed that would impact new connections
214293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (originalConfig == null) {
214393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
214493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
214593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
214693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (wasBitSetUpdated(originalConfig.allowedKeyManagement,
214793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                currentConfig.allowedKeyManagement)) {
214893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
214993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
215093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
215193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (wasBitSetUpdated(originalConfig.allowedProtocols, currentConfig.allowedProtocols)) {
215293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
215393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
215493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
215593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (wasBitSetUpdated(originalConfig.allowedAuthAlgorithms,
215693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                currentConfig.allowedAuthAlgorithms)) {
215793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
215893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
215993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
216093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (wasBitSetUpdated(originalConfig.allowedPairwiseCiphers,
216193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                currentConfig.allowedPairwiseCiphers)) {
216293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
216393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
216493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
216593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (wasBitSetUpdated(originalConfig.allowedGroupCiphers,
216693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                currentConfig.allowedGroupCiphers)) {
216793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
216893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
216993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
217093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (originalConfig.wepKeys != null && currentConfig.wepKeys != null) {
217193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            if (originalConfig.wepKeys.length == currentConfig.wepKeys.length) {
217293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                for (int i = 0; i < originalConfig.wepKeys.length; i++) {
2173b2c2f85c959cb0deba238b566f39b1b942eb70a8Ningyuan Wang                    if (!Objects.equals(originalConfig.wepKeys[i], currentConfig.wepKeys[i])) {
217493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                        return true;
217593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    }
217693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                }
217793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            } else {
217893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                return true;
217993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            }
218093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
218193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
218293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (originalConfig.hiddenSSID != currentConfig.hiddenSSID) {
218393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
218493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
218593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
218693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (originalConfig.requirePMF != currentConfig.requirePMF) {
218793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
218893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
218993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
219093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (wasEnterpriseConfigChange(originalConfig.enterpriseConfig,
219193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                currentConfig.enterpriseConfig)) {
219293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            return true;
219393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
219493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        return false;
219593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein    }
219693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
219793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
219893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein    protected boolean wasEnterpriseConfigChange(WifiEnterpriseConfig originalEnterpriseConfig,
219993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            WifiEnterpriseConfig currentEnterpriseConfig) {
220093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        if (originalEnterpriseConfig != null && currentEnterpriseConfig != null) {
220193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            if (originalEnterpriseConfig.getEapMethod() != currentEnterpriseConfig.getEapMethod()) {
220293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                return true;
220393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            }
220493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
220593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            if (originalEnterpriseConfig.getPhase2Method()
220693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    != currentEnterpriseConfig.getPhase2Method()) {
220793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                return true;
220893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            }
220993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
221093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            X509Certificate[] originalCaCerts = originalEnterpriseConfig.getCaCertificates();
221193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            X509Certificate[] currentCaCerts = currentEnterpriseConfig.getCaCertificates();
221293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
221393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            if (originalCaCerts != null && currentCaCerts != null) {
221493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                if (originalCaCerts.length == currentCaCerts.length) {
221593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    for (int i = 0; i < originalCaCerts.length; i++) {
221693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                        if (!originalCaCerts[i].equals(currentCaCerts[i])) {
221793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                            return true;
221893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                        }
221993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    }
222093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                } else {
222193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    // number of aliases is different, so the configs are different
222293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    return true;
222393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                }
222493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            } else {
222593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                // one of the enterprise configs may have aliases
222693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                if (originalCaCerts != null || currentCaCerts != null) {
222793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                    return true;
222893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                }
222993332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            }
223093332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        } else {
223193332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            // One of the configs may have an enterpriseConfig
223293332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            if (originalEnterpriseConfig != null || currentEnterpriseConfig != null) {
223393332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein                return true;
223493332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein            }
223593332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        }
223693332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein        return false;
223793332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein    }
223893332917bf29ddbe853a495816e486150f49da40Rebecca Silberstein
2239d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    public WifiConfiguration getWifiConfigForHomeSP(HomeSP homeSP) {
2240bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getByFQDNForCurrentUser(homeSP.getFQDN());
224131891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        if (config == null) {
224231891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist            Log.e(TAG, "Could not find network for homeSP " + homeSP.getFQDN());
2243d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
224431891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        return config;
2245d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2246d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
22471d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public HomeSP getHomeSPForConfig(WifiConfiguration config) {
2248bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration storedConfig = mConfiguredNetworks.getForCurrentUser(config.networkId);
224973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        return storedConfig != null && storedConfig.isPasspoint()
225073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                ? mMOManager.getHomeSP(storedConfig.FQDN)
225173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                : null;
22524d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande    }
22534d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande
225425ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande    public ScanDetailCache getScanDetailCache(WifiConfiguration config) {
225525ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (config == null) return null;
225625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        ScanDetailCache cache = mScanDetailCaches.get(config.networkId);
225725ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
225825ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            cache = new ScanDetailCache(config);
225925ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            mScanDetailCaches.put(config.networkId, cache);
226025ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        }
226125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        return cache;
226225ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande    }
226325ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande
2264448c9536a302c58a79e271b1721c08b8882f800evandwalle    /**
2265448c9536a302c58a79e271b1721c08b8882f800evandwalle     * This function run thru the Saved WifiConfigurations and check if some should be linked.
2266448c9536a302c58a79e271b1721c08b8882f800evandwalle     * @param config
2267448c9536a302c58a79e271b1721c08b8882f800evandwalle     */
2268f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    public void linkConfiguration(WifiConfiguration config) {
22690fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowski        if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
227006636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan                mUserManager.getProfiles(mCurrentUserId))) {
2271646ee7704694ef70c0dd3c707170163361ed504aRandy Pan            logd("linkConfiguration: Attempting to link config " + config.configKey()
2272bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    + " that is not visible to the current user.");
2273bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return;
2274bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
2275448c9536a302c58a79e271b1721c08b8882f800evandwalle
227625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (getScanDetailCache(config) != null && getScanDetailCache(config).size() > 6) {
22778c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            // Ignore configurations with large number of BSSIDs
22788c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            return;
22798c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle        }
22808c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle        if (!config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
22818c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            // Only link WPA_PSK config
22828c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            return;
22838c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle        }
2284bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration link : mConfiguredNetworks.valuesForCurrentUser()) {
2285f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            boolean doLink = false;
2286f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2287f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (link.configKey().equals(config.configKey())) {
2288f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
2289f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
2290f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
22918f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (link.ephemeral) {
22920e3c67280365eb82fc15362a3b98a2c978bde766vandwalle                continue;
22930e3c67280365eb82fc15362a3b98a2c978bde766vandwalle            }
22940e3c67280365eb82fc15362a3b98a2c978bde766vandwalle
22958c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            // Autojoin will be allowed to dynamically jump from a linked configuration
22968c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            // to another, hence only link configurations that have equivalent level of security
2297d2569dc2b19c401200fd2672acf83cfc35f1eb12vandwalle            if (!link.allowedKeyManagement.equals(config.allowedKeyManagement)) {
2298d2569dc2b19c401200fd2672acf83cfc35f1eb12vandwalle                continue;
2299d2569dc2b19c401200fd2672acf83cfc35f1eb12vandwalle            }
2300d2569dc2b19c401200fd2672acf83cfc35f1eb12vandwalle
230125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            ScanDetailCache linkedScanDetailCache = getScanDetailCache(link);
230225ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            if (linkedScanDetailCache != null && linkedScanDetailCache.size() > 6) {
23038c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                // Ignore configurations with large number of BSSIDs
23048c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                continue;
23058c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            }
23068c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle
2307f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (config.defaultGwMacAddress != null && link.defaultGwMacAddress != null) {
2308448c9536a302c58a79e271b1721c08b8882f800evandwalle                // If both default GW are known, link only if they are equal
2309f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (config.defaultGwMacAddress.equals(link.defaultGwMacAddress)) {
231073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    if (sVDBG) {
2311646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                        logd("linkConfiguration link due to same gw " + link.SSID
231273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                                + " and " + config.SSID + " GW " + config.defaultGwMacAddress);
2313f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
2314f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    doLink = true;
2315f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
2316f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else {
23178c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                // We do not know BOTH default gateways hence we will try to link
23188c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                // hoping that WifiConfigurations are indeed behind the same gateway.
23198c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                // once both WifiConfiguration have been tried and thus once both efault gateways
23208c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                // are known we will revisit the choice of linking them
232125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                if ((getScanDetailCache(config) != null)
232225ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                        && (getScanDetailCache(config).size() <= 6)) {
232325ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande
232425ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                    for (String abssid : getScanDetailCache(config).keySet()) {
232525ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                        for (String bbssid : linkedScanDetailCache.keySet()) {
232673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                            if (sVVDBG) {
2327646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                                logd("linkConfiguration try to link due to DBDC BSSID match "
232873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                                        + link.SSID + " and " + config.SSID + " bssida " + abssid
23298c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                                        + " bssidb " + bbssid);
23308c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                            }
23318c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                            if (abssid.regionMatches(true, 0, bbssid, 0, 16)) {
23328c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                                // If first 16 ascii characters of BSSID matches,
23338c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                                // we assume this is a DBDC
23348c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                                doLink = true;
23358c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                            }
23368c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle                        }
2337f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
2338f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
2339f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
2340f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
234173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (doLink && mOnlyLinkSameCredentialConfigurations) {
23422fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                String apsk =
23432fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                        readNetworkVariableFromSupplicantFile(link.configKey(), "psk");
23442fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                String bpsk =
23452fc3d4dcabb6ddcd72dc335d908aa192c38c5e5fSamuel Tan                        readNetworkVariableFromSupplicantFile(config.configKey(), "psk");
2346e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                if (apsk == null || bpsk == null
2347e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                        || TextUtils.isEmpty(apsk) || TextUtils.isEmpty(apsk)
23481ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle                        || apsk.equals("*") || apsk.equals(DELETED_CONFIG_PSK)
2349e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                        || !apsk.equals(bpsk)) {
2350448c9536a302c58a79e271b1721c08b8882f800evandwalle                    doLink = false;
2351448c9536a302c58a79e271b1721c08b8882f800evandwalle                }
2352448c9536a302c58a79e271b1721c08b8882f800evandwalle            }
2353448c9536a302c58a79e271b1721c08b8882f800evandwalle
2354f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (doLink) {
235573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (sVDBG) {
2356646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("linkConfiguration: will link " + link.configKey()
2357b86f76f28ae06442e458a8cd4d7ddca210a102efxinhe                            + " and " + config.configKey());
23580888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle                }
2359f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (link.linkedConfigurations == null) {
2360f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    link.linkedConfigurations = new HashMap<String, Integer>();
2361f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
2362f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (config.linkedConfigurations == null) {
2363f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    config.linkedConfigurations = new HashMap<String, Integer>();
2364f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
2365e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                if (link.linkedConfigurations.get(config.configKey()) == null) {
2366e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                    link.linkedConfigurations.put(config.configKey(), Integer.valueOf(1));
2367e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                }
2368e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                if (config.linkedConfigurations.get(link.configKey()) == null) {
2369e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                    config.linkedConfigurations.put(link.configKey(), Integer.valueOf(1));
2370e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle                }
2371f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else {
23729f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                if (link.linkedConfigurations != null
23739f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                        && (link.linkedConfigurations.get(config.configKey()) != null)) {
237473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    if (sVDBG) {
2375646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                        logd("linkConfiguration: un-link " + config.configKey()
23769f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                                + " from " + link.configKey());
23779f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                    }
2378be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                    link.linkedConfigurations.remove(config.configKey());
2379be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                }
23809f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                if (config.linkedConfigurations != null
23819f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                        && (config.linkedConfigurations.get(link.configKey()) != null)) {
238273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    if (sVDBG) {
2383646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                        logd("linkConfiguration: un-link " + link.configKey()
23849f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                                + " from " + config.configKey());
23859f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                    }
2386be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                    config.linkedConfigurations.remove(link.configKey());
2387be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                }
2388f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
2389f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
2390f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
2391f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2392304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan    public HashSet<Integer> makeChannelList(WifiConfiguration config, int age) {
239373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (config == null) {
23944dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            return null;
239573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        }
2396ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius        long now_ms = mClock.currentTimeMillis();
23974dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle
23984dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        HashSet<Integer> channels = new HashSet<Integer>();
23994dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle
24004dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        //get channels for this configuration, if there are at least 2 BSSIDs
240125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (getScanDetailCache(config) == null && config.linkedConfigurations == null) {
24024dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            return null;
24034dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        }
24044dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle
240573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) {
24064dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            StringBuilder dbg = new StringBuilder();
24078c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle            dbg.append("makeChannelList age=" + Integer.toString(age)
24087b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle                    + " for " + config.configKey()
240973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    + " max=" + mMaxNumActiveChannelsForPartialScans);
241025ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            if (getScanDetailCache(config) != null) {
241125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                dbg.append(" bssids=" + getScanDetailCache(config).size());
24124dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            }
24134dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            if (config.linkedConfigurations != null) {
24144dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                dbg.append(" linked=" + config.linkedConfigurations.size());
24154dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            }
2416646ee7704694ef70c0dd3c707170163361ed504aRandy Pan            logd(dbg.toString());
24174dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        }
2418b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle
24199f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle        int numChannels = 0;
242025ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (getScanDetailCache(config) != null && getScanDetailCache(config).size() > 0) {
242125ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            for (ScanDetail scanDetail : getScanDetailCache(config).values()) {
242225ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                ScanResult result = scanDetail.getScanResult();
24239f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                //TODO : cout active and passive channels separately
242473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (numChannels > mMaxNumActiveChannelsForPartialScans.get()) {
24259f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                    break;
24269f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                }
242773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (sVDBG) {
2428b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle                    boolean test = (now_ms - result.seen) < age;
2429646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("has " + result.BSSID + " freq=" + Integer.toString(result.frequency)
2430b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle                            + " age=" + Long.toString(now_ms - result.seen) + " ?=" + test);
2431b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle                }
2432304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan                if (((now_ms - result.seen) < age)) {
24334dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                    channels.add(result.frequency);
24349f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                    numChannels++;
24354dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                }
24364dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            }
24374dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        }
2438b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle
24394dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        //get channels for linked configurations
24404dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        if (config.linkedConfigurations != null) {
24414dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            for (String key : config.linkedConfigurations.keySet()) {
24424dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                WifiConfiguration linked = getWifiConfiguration(key);
244373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                if (linked == null) {
24444dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                    continue;
244573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                }
244625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                if (getScanDetailCache(linked) == null) {
2447b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle                    continue;
24484dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                }
244925ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                for (ScanDetail scanDetail : getScanDetailCache(linked).values()) {
245025ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                    ScanResult result = scanDetail.getScanResult();
245173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    if (sVDBG) {
2452646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                        logd("has link: " + result.BSSID
2453c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle                                + " freq=" + Integer.toString(result.frequency)
2454b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle                                + " age=" + Long.toString(now_ms - result.seen));
2455b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle                    }
245673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    if (numChannels > mMaxNumActiveChannelsForPartialScans.get()) {
24579f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                        break;
24589f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                    }
2459304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan                    if (((now_ms - result.seen) < age)) {
24604dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                        channels.add(result.frequency);
24619f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle                        numChannels++;
24624dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                    }
24634dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle                }
24644dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle            }
24654dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        }
24664dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle        return channels;
24674dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle    }
2468f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2469d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    private Map<HomeSP, PasspointMatch> matchPasspointNetworks(ScanDetail scanDetail) {
2470034205ec8ee3d608546ab9327fb650d9a259efadJan Nordqvist        if (!mMOManager.isConfigured()) {
24712e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            if (mEnableOsuQueries) {
24721d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                NetworkDetail networkDetail = scanDetail.getNetworkDetail();
24731d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                List<Constants.ANQPElementType> querySet =
24741d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                        ANQPFactory.buildQueryList(networkDetail, false, true);
24751d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
24761d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                if (networkDetail.queriable(querySet)) {
24771d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    querySet = mAnqpCache.initiate(networkDetail, querySet);
24781d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    if (querySet != null) {
24792e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                        mSupplicantBridge.startANQP(scanDetail, querySet);
24801d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    }
24811d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    updateAnqpCache(scanDetail, networkDetail.getANQPElements());
24821d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                }
24831d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            }
24845bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist            return null;
24855bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist        }
2486d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2487a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist        if (!networkDetail.hasInterworking()) {
2488d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            return null;
2489d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2490d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        updateAnqpCache(scanDetail, networkDetail.getANQPElements());
2491d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
24925bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist        Map<HomeSP, PasspointMatch> matches = matchNetwork(scanDetail, true);
249373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        Log.d(Utils.hs2LogTag(getClass()), scanDetail.getSSID()
249473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                + " pass 1 matches: " + toMatchString(matches));
2495d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        return matches;
2496d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2497d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2498d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    private Map<HomeSP, PasspointMatch> matchNetwork(ScanDetail scanDetail, boolean query) {
2499d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2500d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2501d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        ANQPData anqpData = mAnqpCache.getEntry(networkDetail);
2502d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2503d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        Map<Constants.ANQPElementType, ANQPElement> anqpElements =
2504d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                anqpData != null ? anqpData.getANQPElements() : null;
2505d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2506d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        boolean queried = !query;
250731891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist        Collection<HomeSP> homeSPs = mMOManager.getLoadedSPs().values();
2508d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        Map<HomeSP, PasspointMatch> matches = new HashMap<>(homeSPs.size());
250973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        Log.d(Utils.hs2LogTag(getClass()), "match nwk " + scanDetail.toKeyString()
251073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                + ", anqp " + (anqpData != null ? "present" : "missing")
251173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                + ", query " + query + ", home sps: " + homeSPs.size());
251231891afce40b903ada9b24ec12e3648ae6aa27b2Jan Nordqvist
2513d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        for (HomeSP homeSP : homeSPs) {
251407a3f9d97394b97965e6754271fb66c1d6bd1753Jan Nordqvist            PasspointMatch match = homeSP.match(networkDetail, anqpElements, mSIMAccessor);
2515d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
251673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            Log.d(Utils.hs2LogTag(getClass()), " -- "
251773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    + homeSP.getFQDN() + ": match " + match + ", queried " + queried);
2518d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
25192e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            if ((match == PasspointMatch.Incomplete || mEnableOsuQueries) && !queried) {
25201d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                boolean matchSet = match == PasspointMatch.Incomplete;
25212e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                boolean osu = mEnableOsuQueries;
25221d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                List<Constants.ANQPElementType> querySet =
25231d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                        ANQPFactory.buildQueryList(networkDetail, matchSet, osu);
25241d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                if (networkDetail.queriable(querySet)) {
25251d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    querySet = mAnqpCache.initiate(networkDetail, querySet);
25261d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    if (querySet != null) {
25272e814680f4dd27a5f825afab189843582235cedcJan Nordqvist                        mSupplicantBridge.startANQP(scanDetail, querySet);
25281d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    }
2529d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                }
2530d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                queried = true;
2531d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            }
2532d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            matches.put(homeSP, match);
2533d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2534d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        return matches;
2535d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2536d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
25371d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public Map<Constants.ANQPElementType, ANQPElement> getANQPData(NetworkDetail network) {
25381d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        ANQPData data = mAnqpCache.getEntry(network);
25391d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return data != null ? data.getANQPElements() : null;
25401d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
25411d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
25421d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public SIMAccessor getSIMAccessor() {
25431d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return mSIMAccessor;
25441d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
25451d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
2546d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    public void notifyANQPDone(Long bssid, boolean success) {
2547d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        mSupplicantBridge.notifyANQPDone(bssid, success);
2548d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2549d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
25506dd42662e45750910d8743f7f154269c2755df93Jan Nordqvist    public void notifyIconReceived(IconEvent iconEvent) {
25512e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        Intent intent = new Intent(WifiManager.PASSPOINT_ICON_RECEIVED_ACTION);
25522e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
25532e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_BSSID, iconEvent.getBSSID());
25542e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_FILE, iconEvent.getFileName());
25552e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        try {
2556c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius            intent.putExtra(WifiManager.EXTRA_PASSPOINT_ICON_DATA,
2557c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius                    mSupplicantBridge.retrieveIcon(iconEvent));
25582e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        } catch (IOException ioe) {
25592e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            /* Simply omit the icon data as a failure indication */
25602e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
25612e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
25622e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
25636dd42662e45750910d8743f7f154269c2755df93Jan Nordqvist    }
25646dd42662e45750910d8743f7f154269c2755df93Jan Nordqvist
2565d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    private void updateAnqpCache(ScanDetail scanDetail,
256673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                                 Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
2567d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2568d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2569d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        if (anqpElements == null) {
25705bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist            // Try to pull cached data if query failed.
2571d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            ANQPData data = mAnqpCache.getEntry(networkDetail);
2572d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            if (data != null) {
2573d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                scanDetail.propagateANQPInfo(data.getANQPElements());
2574d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            }
2575d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            return;
2576d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2577d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2578d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        mAnqpCache.update(networkDetail, anqpElements);
2579d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2580d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2581d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    private static String toMatchString(Map<HomeSP, PasspointMatch> matches) {
2582d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        StringBuilder sb = new StringBuilder();
2583d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        for (Map.Entry<HomeSP, PasspointMatch> entry : matches.entrySet()) {
2584d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            sb.append(' ').append(entry.getKey().getFQDN()).append("->").append(entry.getValue());
2585d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2586d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        return sb.toString();
2587d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2588d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
25894d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande    private void cacheScanResultForPasspointConfigs(ScanDetail scanDetail,
25908f0f666c8bdaf508f191f8590755140b92d970eaxinhe            Map<HomeSP, PasspointMatch> matches,
25918f0f666c8bdaf508f191f8590755140b92d970eaxinhe            List<WifiConfiguration> associatedWifiConfigurations) {
2592d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2593d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        for (Map.Entry<HomeSP, PasspointMatch> entry : matches.entrySet()) {
2594a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande            PasspointMatch match = entry.getValue();
2595a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande            if (match == PasspointMatch.HomeProvider || match == PasspointMatch.RoamingProvider) {
2596a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande                WifiConfiguration config = getWifiConfigForHomeSP(entry.getKey());
2597a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande                if (config != null) {
2598a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande                    cacheScanResultForConfig(config, scanDetail, entry.getValue());
25998f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    if (associatedWifiConfigurations != null) {
26008f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        associatedWifiConfigurations.add(config);
26018f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    }
2602a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande                } else {
260373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    Log.w(Utils.hs2LogTag(getClass()), "Failed to find config for '"
260473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                            + entry.getKey().getFQDN() + "'");
2605a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande                    /* perhaps the configuration was deleted?? */
2606a547460e835d6dfde84eda72df470846d11ba807Vinit Deshpande                }
2607b151395e1d4de62ea8a9254e69e1878d3d1cde28Vinit Deshpande            }
2608d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2609d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2610d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
26114d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande    private void cacheScanResultForConfig(
26124d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande            WifiConfiguration config, ScanDetail scanDetail, PasspointMatch passpointMatch) {
2613d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2614d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        ScanResult scanResult = scanDetail.getScanResult();
2615d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
261625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        ScanDetailCache scanDetailCache = getScanDetailCache(config);
261725ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        if (scanDetailCache == null) {
261825ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            Log.w(TAG, "Could not allocate scan cache for " + config.SSID);
261925ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande            return;
2620d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2621d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2622d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        // Adding a new BSSID
262325ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande        ScanResult result = scanDetailCache.get(scanResult.BSSID);
2624c55fc72b3c2fa2f47a52138e53a86460ba87a1c5Pierre Vandwalle        if (result != null) {
2625d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            // transfer the black list status
2626d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            scanResult.blackListTimestamp = result.blackListTimestamp;
2627d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            scanResult.numIpConfigFailures = result.numIpConfigFailures;
2628d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            scanResult.numConnection = result.numConnection;
2629d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            scanResult.isAutoJoinCandidate = result.isAutoJoinCandidate;
2630d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2631d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2632d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        if (config.ephemeral) {
2633d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            // For an ephemeral Wi-Fi config, the ScanResult should be considered
2634d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            // untrusted.
2635d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            scanResult.untrusted = true;
2636d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2637d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
263873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (scanDetailCache.size() > (MAX_NUM_SCAN_CACHE_ENTRIES + 64)) {
2639d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            long now_dbg = 0;
264073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (sVVDBG) {
2641646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                logd(" Will trim config " + config.configKey()
264225ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                        + " size " + scanDetailCache.size());
2643d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
264425ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                for (ScanDetail sd : scanDetailCache.values()) {
2645646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("     " + sd.getBSSIDString() + " " + sd.getSeen());
2646d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                }
2647d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                now_dbg = SystemClock.elapsedRealtimeNanos();
2648d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            }
264973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            // Trim the scan result cache to MAX_NUM_SCAN_CACHE_ENTRIES entries max
2650d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            // Since this operation is expensive, make sure it is not performed
2651d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            // until the cache has grown significantly above the trim treshold
265273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            scanDetailCache.trim(MAX_NUM_SCAN_CACHE_ENTRIES);
265373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (sVVDBG) {
2654d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                long diff = SystemClock.elapsedRealtimeNanos() - now_dbg;
2655646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                logd(" Finished trimming config, time(ns) " + diff);
265625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande                for (ScanDetail sd : scanDetailCache.values()) {
2657646ee7704694ef70c0dd3c707170163361ed504aRandy Pan                    logd("     " + sd.getBSSIDString() + " " + sd.getSeen());
2658d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande                }
2659d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande            }
2660d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
2661d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
2662d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        // Add the scan result to this WifiConfiguration
266373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (passpointMatch != null) {
26644d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande            scanDetailCache.put(scanDetail, passpointMatch, getHomeSPForConfig(config));
266573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        } else {
26664d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande            scanDetailCache.put(scanDetail);
266773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        }
26684d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande
2669d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        // Since we added a scan result to this configuration, re-attempt linking
2670d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        linkConfiguration(config);
2671d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    }
2672d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
26738f0f666c8bdaf508f191f8590755140b92d970eaxinhe    private boolean isEncryptionWep(String encryption) {
26748f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return encryption.contains("WEP");
26758f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
26768f0f666c8bdaf508f191f8590755140b92d970eaxinhe
26778f0f666c8bdaf508f191f8590755140b92d970eaxinhe    private boolean isEncryptionPsk(String encryption) {
26788f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return encryption.contains("PSK");
26798f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
26808f0f666c8bdaf508f191f8590755140b92d970eaxinhe
26818f0f666c8bdaf508f191f8590755140b92d970eaxinhe    private boolean isEncryptionEap(String encryption) {
26828f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return encryption.contains("EAP");
26838f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
26848f0f666c8bdaf508f191f8590755140b92d970eaxinhe
26858f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe    public boolean isOpenNetwork(String encryption) {
26868f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (!isEncryptionWep(encryption) && !isEncryptionPsk(encryption)
26878f0f666c8bdaf508f191f8590755140b92d970eaxinhe                && !isEncryptionEap(encryption)) {
26888f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return true;
26898f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
26908f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return false;
26918f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
2692d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande
26938f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe    public boolean isOpenNetwork(ScanResult scan) {
26948f0f666c8bdaf508f191f8590755140b92d970eaxinhe        String scanResultEncrypt = scan.capabilities;
26958f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return isOpenNetwork(scanResultEncrypt);
26968f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
26978f0f666c8bdaf508f191f8590755140b92d970eaxinhe
26988f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe    public boolean isOpenNetwork(WifiConfiguration config) {
26998f0f666c8bdaf508f191f8590755140b92d970eaxinhe        String configEncrypt = config.configKey();
27008f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return isOpenNetwork(configEncrypt);
27018f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
27028f0f666c8bdaf508f191f8590755140b92d970eaxinhe
27038f0f666c8bdaf508f191f8590755140b92d970eaxinhe    /**
2704f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     * Get saved WifiConfiguration associated with a scan detail.
27058f0f666c8bdaf508f191f8590755140b92d970eaxinhe     * @param scanDetail input a scanDetail from the scan result
2706f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     * @return WifiConfiguration WifiConfiguration associated with this scanDetail, null if none
27078f0f666c8bdaf508f191f8590755140b92d970eaxinhe     */
2708f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius    public List<WifiConfiguration> getSavedNetworkFromScanDetail(ScanDetail scanDetail) {
2709d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        ScanResult scanResult = scanDetail.getScanResult();
271073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (scanResult == null) {
27118f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return null;
271273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        }
2713f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        List<WifiConfiguration> savedWifiConfigurations = new ArrayList<>();
271473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        String ssid = "\"" + scanResult.SSID + "\"";
2715bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
271673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (config.SSID == null || !config.SSID.equals(ssid)) {
27177b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle                continue;
27187b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle            }
27198f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (DBG) {
2720f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius                localLog("getSavedNetworkFromScanDetail(): try " + config.configKey()
27218f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        + " SSID=" + config.SSID + " " + scanResult.SSID + " "
27228f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        + scanResult.capabilities);
27237b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle            }
27248f0f666c8bdaf508f191f8590755140b92d970eaxinhe            String scanResultEncrypt = scanResult.capabilities;
27258f0f666c8bdaf508f191f8590755140b92d970eaxinhe            String configEncrypt = config.configKey();
27268f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if (isEncryptionWep(scanResultEncrypt) && isEncryptionWep(configEncrypt)
27278f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    || (isEncryptionPsk(scanResultEncrypt) && isEncryptionPsk(configEncrypt))
27288f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    || (isEncryptionEap(scanResultEncrypt) && isEncryptionEap(configEncrypt))
27298f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    || (isOpenNetwork(scanResultEncrypt) && isOpenNetwork(configEncrypt))) {
2730f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius                savedWifiConfigurations.add(config);
27317b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle            }
2732f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        }
2733f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        return savedWifiConfigurations;
2734f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius    }
27357b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle
2736f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius    /**
2737f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     * Create a mapping between the scandetail and the Wificonfiguration it associated with
2738f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     * because Passpoint, one BSSID can associated with multiple SSIDs
2739f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     * @param scanDetail input a scanDetail from the scan result
27401e5f0667515826cdc9c85a63a82c4c48cad446c2Ningyuan Wang     * @param isConnectingOrConnected input a boolean to indicate if WiFi is connecting or conncted
27411e5f0667515826cdc9c85a63a82c4c48cad446c2Ningyuan Wang     * This is used for avoiding ANQP request
2742f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     * @return List<WifiConfiguration> a list of WifiConfigurations associated to this scanDetail
2743f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius     */
27441e5f0667515826cdc9c85a63a82c4c48cad446c2Ningyuan Wang    public List<WifiConfiguration> updateSavedNetworkWithNewScanDetail(ScanDetail scanDetail,
27451e5f0667515826cdc9c85a63a82c4c48cad446c2Ningyuan Wang            boolean isConnectingOrConnected) {
2746f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        ScanResult scanResult = scanDetail.getScanResult();
2747f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        if (scanResult == null) {
2748f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius            return null;
2749f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        }
2750f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2751f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        List<WifiConfiguration> associatedWifiConfigurations = new ArrayList<>();
27521e5f0667515826cdc9c85a63a82c4c48cad446c2Ningyuan Wang        if (networkDetail.hasInterworking() && !isConnectingOrConnected) {
2753f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius            Map<HomeSP, PasspointMatch> matches = matchPasspointNetworks(scanDetail);
2754f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius            if (matches != null) {
2755f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius                cacheScanResultForPasspointConfigs(scanDetail, matches,
2756f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius                        associatedWifiConfigurations);
2757f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius                //Do not return here. A BSSID can belong to both passpoint network and non-passpoint
2758f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius                //Network
2759f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius            }
2760f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        }
2761f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        List<WifiConfiguration> savedConfigurations = getSavedNetworkFromScanDetail(scanDetail);
2762f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius        if (savedConfigurations != null) {
2763f799eff77d81ae0509b8b890a7c6068d5c6cda6eRoshan Pius            for (WifiConfiguration config : savedConfigurations) {
27644d381bc39f5263effdae73ec99065eb299b806caVinit Deshpande                cacheScanResultForConfig(config, scanDetail, null);
27658f0f666c8bdaf508f191f8590755140b92d970eaxinhe                associatedWifiConfigurations.add(config);
27667b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle            }
27678f0f666c8bdaf508f191f8590755140b92d970eaxinhe        }
27688f0f666c8bdaf508f191f8590755140b92d970eaxinhe        if (associatedWifiConfigurations.size() == 0) {
27698f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return null;
27708f0f666c8bdaf508f191f8590755140b92d970eaxinhe        } else {
27718f0f666c8bdaf508f191f8590755140b92d970eaxinhe            return associatedWifiConfigurations;
27727b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle        }
2773f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
2774f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2775bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski    /**
2776bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * Handles the switch to a different foreground user:
2777bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Removes all ephemeral networks
2778bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Disables private network configurations belonging to the previous foreground user
2779bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Enables private network configurations belonging to the new foreground user
2780bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     *
278106636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan     * @param userId The identifier of the new foreground user, after the switch.
278206636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan     *
27837be46e76ac639934f19e84f897cbe8b698e56dffBartosz Fabianowski     * TODO(b/26785736): Terminate background users if the new foreground user has one or more
2784bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * private network configurations.
2785bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     */
278606636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    public void handleUserSwitch(int userId) {
278706636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        mCurrentUserId = userId;
2788bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        Set<WifiConfiguration> ephemeralConfigs = new HashSet<>();
2789bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
2790bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            if (config.ephemeral) {
2791bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                ephemeralConfigs.add(config);
2792bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            }
2793bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
2794bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        if (!ephemeralConfigs.isEmpty()) {
2795bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            for (WifiConfiguration config : ephemeralConfigs) {
2796dc61ad4fe8a84909a288af50a8b187c98e2194b6Roshan Pius                removeConfigWithoutBroadcast(config);
2797bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            }
27982d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius            saveConfig();
2799b50356194ccfdaf5e127d9f705f99713d6f1e98cxinhe            writeKnownNetworkHistory();
2800bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
2801bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
2802bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        final List<WifiConfiguration> hiddenConfigurations =
280306636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan                mConfiguredNetworks.handleUserSwitch(mCurrentUserId);
2804bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        for (WifiConfiguration network : hiddenConfigurations) {
28059d7489491984e86915b2cf4fac38a882de1c8cdbRoshan Pius            disableNetworkNative(network);
2806bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        }
2807bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        enableAllNetworks();
2808bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
28097be46e76ac639934f19e84f897cbe8b698e56dffBartosz Fabianowski        // TODO(b/26785746): This broadcast is unnecessary if either of the following is true:
2810bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        // * The user switch did not change the list of visible networks
2811bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        // * The user switch revealed additional networks that were temporarily disabled and got
2812bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        //   re-enabled now (because enableAllNetworks() sent the same broadcast already).
2813bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        sendConfiguredNetworksChangedBroadcast();
2814bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski    }
2815bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
281606636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    public int getCurrentUserId() {
281706636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        return mCurrentUserId;
281806636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    }
281906636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan
282006636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    public boolean isCurrentUserProfile(int userId) {
282106636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        if (userId == mCurrentUserId) {
282206636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan            return true;
282306636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        }
282406636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        final UserInfo parent = mUserManager.getProfileParent(userId);
282506636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan        return parent != null && parent.id == mCurrentUserId;
282606636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan    }
282706636d2de935ad5d2e8fb6483c406fe922c75ff2Samuel Tan
2828155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /* Compare current and new configuration and write to file on change */
2829155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private NetworkUpdateResult writeIpAndProxyConfigurationsOnChange(
2830155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            WifiConfiguration currentConfig,
2831cc018db319baff34c9d36928d04c2c420257498fRoshan Pius            WifiConfiguration newConfig,
2832cc018db319baff34c9d36928d04c2c420257498fRoshan Pius            boolean isNewNetwork) {
2833155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        boolean ipChanged = false;
2834155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        boolean proxyChanged = false;
2835155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
28363ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        switch (newConfig.getIpAssignment()) {
2837155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case STATIC:
28383b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                if (currentConfig.getIpAssignment() != newConfig.getIpAssignment()) {
2839155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    ipChanged = true;
28403b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                } else {
28413b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                    ipChanged = !Objects.equals(
28423b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                            currentConfig.getStaticIpConfiguration(),
28433b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                            newConfig.getStaticIpConfiguration());
2844155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
2845155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2846155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case DHCP:
28473ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim                if (currentConfig.getIpAssignment() != newConfig.getIpAssignment()) {
2848155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    ipChanged = true;
2849155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
2850155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2851155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case UNASSIGNED:
2852155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                /* Ignore */
2853155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2854155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            default:
2855155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                loge("Ignore invalid ip assignment during write");
2856155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2857155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2858155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
28593ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim        switch (newConfig.getProxySettings()) {
2860155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case STATIC:
2861155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case PAC:
28623b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                ProxyInfo newHttpProxy = newConfig.getHttpProxy();
28633b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                ProxyInfo currentHttpProxy = currentConfig.getHttpProxy();
2864155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2865155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                if (newHttpProxy != null) {
2866155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    proxyChanged = !newHttpProxy.equals(currentHttpProxy);
2867155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                } else {
2868155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    proxyChanged = (currentHttpProxy != null);
2869155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
2870155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2871155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case NONE:
28723ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim                if (currentConfig.getProxySettings() != newConfig.getProxySettings()) {
2873155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    proxyChanged = true;
2874155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
2875155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2876155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case UNASSIGNED:
2877155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                /* Ignore */
2878155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2879155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            default:
2880155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                loge("Ignore invalid proxy configuration during write");
2881155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
2882155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2883155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
28843b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti        if (ipChanged) {
28853ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            currentConfig.setIpAssignment(newConfig.getIpAssignment());
28863b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti            currentConfig.setStaticIpConfiguration(newConfig.getStaticIpConfiguration());
28870ebd6d71cecb5147fad1ca7a7f807aec7ffeddd9Lorenzo Colitti            log("IP config changed SSID = " + currentConfig.SSID);
28880ebd6d71cecb5147fad1ca7a7f807aec7ffeddd9Lorenzo Colitti            if (currentConfig.getStaticIpConfiguration() != null) {
288973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                log(" static configuration: "
289073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        + currentConfig.getStaticIpConfiguration().toString());
28910ebd6d71cecb5147fad1ca7a7f807aec7ffeddd9Lorenzo Colitti            }
2892155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2893155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
28943b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti        if (proxyChanged) {
28953ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim            currentConfig.setProxySettings(newConfig.getProxySettings());
28963b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti            currentConfig.setHttpProxy(newConfig.getHttpProxy());
2897155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            log("proxy changed SSID = " + currentConfig.SSID);
28983b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti            if (currentConfig.getHttpProxy() != null) {
28993b26801d62a06475b722bbf29cba7f48f376654eLorenzo Colitti                log(" proxyProperties: " + currentConfig.getHttpProxy().toString());
2900155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
2901155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2902155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2903cc018db319baff34c9d36928d04c2c420257498fRoshan Pius        if (ipChanged || proxyChanged || isNewNetwork) {
290473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan            if (sVDBG) {
290573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                logd("writeIpAndProxyConfigurationsOnChange: " + currentConfig.SSID + " -> "
290673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                        + newConfig.SSID + " path: " + IP_CONFIG_FILE);
2907cc018db319baff34c9d36928d04c2c420257498fRoshan Pius            }
2908155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            writeIpAndProxyConfigurations();
2909155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2910155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return new NetworkUpdateResult(ipChanged, proxyChanged);
2911155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
2912155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2913155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /**
2914155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * Read the variables from the supplicant daemon that are needed to
2915155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * fill in the WifiConfiguration object.
2916155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *
2917155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * @param config the {@link WifiConfiguration} object to be filled in.
2918155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
2919155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void readNetworkVariables(WifiConfiguration config) {
29202d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.readNetworkVariables(config);
2921155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
2922155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2923f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* return the allowed key management based on a scan result */
2924f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
29258f0f666c8bdaf508f191f8590755140b92d970eaxinhe    public WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) {
292625ee2d5d30434712b28aef6eec9460035101e493Vinit Deshpande
2927f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration config = new WifiConfiguration();
2928f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2929f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        config.SSID = "\"" + result.SSID + "\"";
2930f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
293173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (sVDBG) {
2932646ee7704694ef70c0dd3c707170163361ed504aRandy Pan            logd("WifiConfiguration from scan results "
293373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                    + config.SSID + " cap " + result.capabilities);
2934f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
2935f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
293637cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan        if (result.capabilities.contains("PSK") || result.capabilities.contains("EAP")
293737cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                || result.capabilities.contains("WEP")) {
293837cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            if (result.capabilities.contains("PSK")) {
293937cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
294037cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            }
2941f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
294237cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            if (result.capabilities.contains("EAP")) {
294337cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
294437cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
294537cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            }
2946f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
294737cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            if (result.capabilities.contains("WEP")) {
294837cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                config.allowedKeyManagement.set(KeyMgmt.NONE);
294937cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
295037cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
295137cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            }
295237cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan        } else {
295337cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan            config.allowedKeyManagement.set(KeyMgmt.NONE);
295437cc4a769e6a2b81f3b99941187cdfd95fc6f713Randy Pan        }
2955f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2956f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return config;
2957f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
2958f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
29598f0f666c8bdaf508f191f8590755140b92d970eaxinhe    public WifiConfiguration wifiConfigurationFromScanResult(ScanDetail scanDetail) {
29608f0f666c8bdaf508f191f8590755140b92d970eaxinhe        ScanResult result = scanDetail.getScanResult();
29618f0f666c8bdaf508f191f8590755140b92d970eaxinhe        return wifiConfigurationFromScanResult(result);
29628f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
2963f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
2964155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /* Returns a unique for a given configuration */
2965155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private static int configKey(WifiConfiguration config) {
2966f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String key = config.configKey();
2967155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return key.hashCode();
2968155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
2969155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2970155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2971c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius        pw.println("Dump of WifiConfigManager");
2972155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        pw.println("mLastPriority " + mLastPriority);
2973155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        pw.println("Configured networks");
2974d9dcc7c6d03a0d93c50bada805ad4047aab8642aPierre Vandwalle        for (WifiConfiguration conf : getAllConfiguredNetworks()) {
2975155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            pw.println(conf);
2976155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
2977155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        pw.println();
2978e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        if (mLostConfigsDbg != null && mLostConfigsDbg.size() > 0) {
2979e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle            pw.println("LostConfigs: ");
2980e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle            for (String s : mLostConfigsDbg) {
2981e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle                pw.println(s);
2982e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle            }
2983e63336e926e60ba9b0cf0702be9bec2718de27d8Pierre Vandwalle        }
2984155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (mLocalLog != null) {
2985c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius            pw.println("WifiConfigManager - Log Begin ----");
2986155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mLocalLog.dump(fd, pw, args);
2987c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius            pw.println("WifiConfigManager - Log End ----");
2988155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
29899f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist        if (mMOManager.isConfigured()) {
29909f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist            pw.println("Begin dump of ANQP Cache");
29919f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist            mAnqpCache.dump(pw);
29929f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist            pw.println("End dump of ANQP Cache");
29939f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist        }
2994155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
2995155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
2996155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    public String getConfigFile() {
299773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        return IP_CONFIG_FILE;
2998155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
2999155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3000bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski    protected void logd(String s) {
3001bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        Log.d(TAG, s);
3002bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski    }
3003bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski
30043ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim    protected void loge(String s) {
30050888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        loge(s, false);
30060888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle    }
30070888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle
30080888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle    protected void loge(String s, boolean stack) {
30090888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        if (stack) {
30100888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle            Log.e(TAG, s + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
30110888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle                    + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
30120888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle                    + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
30130888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle                    + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
30140888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        } else {
30150888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle            Log.e(TAG, s);
30160888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        }
3017b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim    }
3018b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim
301984649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande    private void logKernelTime() {
302073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        long kernelTimeMs = System.nanoTime() / (1000 * 1000);
302184649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        StringBuilder builder = new StringBuilder();
302273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        builder.append("kernel time = ")
302373a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                .append(kernelTimeMs / 1000)
302473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                .append(".")
302573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                .append(kernelTimeMs % 1000)
302673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan                .append("\n");
302784649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande        localLog(builder.toString());
302884649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande    }
302984649ea634d480be6bee19f155a1da5a4ec93e60Vinit Deshpande
30303ecf5a032e94b6538a56f94a5b33e50cbc464007Jaewan Kim    protected void log(String s) {
3031b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim        Log.d(TAG, s);
3032b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim    }
3033b872cd1d58e1666a9066b136e28c49ed62f825edJaewan Kim
3034155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void localLog(String s) {
3035155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (mLocalLog != null) {
3036155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mLocalLog.log(s);
3037155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3038155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
3039155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
304065b752f1da25f028a204a88264380c610866c027Mitchell Wills    private void localLogAndLogcat(String s) {
30417b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle        localLog(s);
304265b752f1da25f028a204a88264380c610866c027Mitchell Wills        Log.d(TAG, s);
30437b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle    }
30447b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle
304565b752f1da25f028a204a88264380c610866c027Mitchell Wills    private void localLogNetwork(String s, int netId) {
3046155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (mLocalLog == null) {
3047155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return;
3048155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3049155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3050155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        WifiConfiguration config;
305173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        synchronized (mConfiguredNetworks) {             // !!! Useless synchronization
3052bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            config = mConfiguredNetworks.getForAllUsers(netId);
3053155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3054155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3055155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (config != null) {
3056e0ba94ba9abde13173ae0de8c8939aa4eb9a9085vandwalle            mLocalLog.log(s + " " + config.getPrintableSsid() + " " + netId
3057e0ba94ba9abde13173ae0de8c8939aa4eb9a9085vandwalle                    + " status=" + config.status
3058e0ba94ba9abde13173ae0de8c8939aa4eb9a9085vandwalle                    + " key=" + config.configKey());
3059155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        } else {
3060155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mLocalLog.log(s + " " + netId);
3061155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3062155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
3063155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3064155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    static boolean needsSoftwareBackedKeyStore(WifiEnterpriseConfig config) {
3065155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        String client = config.getClientCertificateAlias();
3066155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (!TextUtils.isEmpty(client)) {
3067155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            // a valid client certificate is configured
3068155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3069155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            // BUGBUG: keyStore.get() never returns certBytes; because it is not
3070155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            // taking WIFI_UID as a parameter. It always looks for certificate
3071155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            // with SYSTEM_UID, and never finds any Wifi certificates. Assuming that
3072155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            // all certificates need software keystore until we get the get() API
3073155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            // fixed.
3074155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3075155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return true;
3076155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3077155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3078155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        /*
3079155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        try {
3080155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3081155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (DBG) Slog.d(TAG, "Loading client certificate " + Credentials
3082155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    .USER_CERTIFICATE + client);
3083155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3084155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            CertificateFactory factory = CertificateFactory.getInstance("X.509");
3085155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (factory == null) {
3086155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                Slog.e(TAG, "Error getting certificate factory");
3087155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                return;
3088155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
3089155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3090155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            byte[] certBytes = keyStore.get(Credentials.USER_CERTIFICATE + client);
3091155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (certBytes != null) {
3092155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                Certificate cert = (X509Certificate) factory.generateCertificate(
3093155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        new ByteArrayInputStream(certBytes));
3094155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3095155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                if (cert != null) {
3096155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    mNeedsSoftwareKeystore = hasHardwareBackedKey(cert);
3097155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3098155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    if (DBG) Slog.d(TAG, "Loaded client certificate " + Credentials
3099155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                            .USER_CERTIFICATE + client);
3100155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    if (DBG) Slog.d(TAG, "It " + (mNeedsSoftwareKeystore ? "needs" :
3101155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                            "does not need" ) + " software key store");
3102155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                } else {
3103155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    Slog.d(TAG, "could not generate certificate");
3104155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                }
3105155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            } else {
3106155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                Slog.e(TAG, "Could not load client certificate " + Credentials
3107155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        .USER_CERTIFICATE + client);
3108155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                mNeedsSoftwareKeystore = true;
3109155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
3110155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3111155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        } catch(CertificateException e) {
3112155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            Slog.e(TAG, "Could not read certificates");
3113155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mCaCert = null;
3114155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mClientCertificate = null;
3115155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
3116155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        */
3117155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
3118155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        return false;
3119155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
3120155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
31212d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    /**
31222d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius     * Checks if the network is a sim config.
31232d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius     * @param config Config corresponding to the network.
31242d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius     * @return true if it is a sim config, false otherwise.
31252d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius     */
31262d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    public boolean isSimConfig(WifiConfiguration config) {
31272d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.isSimConfig(config);
31282ada3ea8a48bfc8202d692a70bde6bc14708b4b5Vinit Deshpande    }
31292ada3ea8a48bfc8202d692a70bde6bc14708b4b5Vinit Deshpande
31302d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    /**
31312d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius     * Resets all sim networks from the network list.
31322d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius     */
31332d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    public void resetSimNetworks() {
31342d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.resetSimNetworks(mConfiguredNetworks.valuesForCurrentUser());
31352ada3ea8a48bfc8202d692a70bde6bc14708b4b5Vinit Deshpande    }
31362ada3ea8a48bfc8202d692a70bde6bc14708b4b5Vinit Deshpande
3137e487a4648dd41881e754f1224aaedead78a0777dSky Faber    boolean isNetworkConfigured(WifiConfiguration config) {
3138e487a4648dd41881e754f1224aaedead78a0777dSky Faber        // Check if either we have a network Id or a WifiConfiguration
3139e487a4648dd41881e754f1224aaedead78a0777dSky Faber        // matching the one we are trying to add.
3140e487a4648dd41881e754f1224aaedead78a0777dSky Faber
314173a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (config.networkId != INVALID_NETWORK_ID) {
3142bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            return (mConfiguredNetworks.getForCurrentUser(config.networkId) != null);
3143e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
3144e487a4648dd41881e754f1224aaedead78a0777dSky Faber
3145bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        return (mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey()) != null);
3146e487a4648dd41881e754f1224aaedead78a0777dSky Faber    }
3147e487a4648dd41881e754f1224aaedead78a0777dSky Faber
3148e487a4648dd41881e754f1224aaedead78a0777dSky Faber    /**
3149e487a4648dd41881e754f1224aaedead78a0777dSky Faber     * Checks if uid has access to modify the configuration corresponding to networkId.
3150e487a4648dd41881e754f1224aaedead78a0777dSky Faber     *
3151bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * The conditions checked are, in descending priority order:
3152bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Disallow modification if the the configuration is not visible to the uid.
3153bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Allow modification if the uid represents the Device Owner app.
3154bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Allow modification if both of the following are true:
3155bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     *   - The uid represents the configuration's creator or an app holding OVERRIDE_CONFIG_WIFI.
3156bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     *   - The modification is only for administrative annotation (e.g. when connecting) or the
3157bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     *     configuration is not lockdown eligible (which currently means that it was not last
3158bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     *     updated by the DO).
3159bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - Allow modification if configuration lockdown is explicitly disabled and the uid represents
3160bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     *   an app holding OVERRIDE_CONFIG_WIFI.
3161bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski     * - In all other cases, disallow modification.
3162e487a4648dd41881e754f1224aaedead78a0777dSky Faber     */
31631a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban    boolean canModifyNetwork(int uid, int networkId, boolean onlyAnnotate) {
3164bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(networkId);
3165e487a4648dd41881e754f1224aaedead78a0777dSky Faber
3166e487a4648dd41881e754f1224aaedead78a0777dSky Faber        if (config == null) {
3167e487a4648dd41881e754f1224aaedead78a0777dSky Faber            loge("canModifyNetwork: cannot find config networkId " + networkId);
3168e487a4648dd41881e754f1224aaedead78a0777dSky Faber            return false;
3169e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
3170e487a4648dd41881e754f1224aaedead78a0777dSky Faber
317150bb8f65526b16ca8a354fd485d2ed7a343e97aeZoltan Szatmary-Ban        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
317250bb8f65526b16ca8a354fd485d2ed7a343e97aeZoltan Szatmary-Ban                DevicePolicyManagerInternal.class);
31731a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban
31741a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
31751a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban                DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
31761a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban
31771a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        if (isUidDeviceOwner) {
31781a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban            return true;
317950bb8f65526b16ca8a354fd485d2ed7a343e97aeZoltan Szatmary-Ban        }
318050bb8f65526b16ca8a354fd485d2ed7a343e97aeZoltan Szatmary-Ban
31811a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        final boolean isCreator = (config.creatorUid == uid);
31821a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban
31831a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        if (onlyAnnotate) {
31841a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban            return isCreator || checkConfigOverridePermission(uid);
31851a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        }
31861a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban
31871a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        // Check if device has DPM capability. If it has and dpmi is still null, then we
31881a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        // treat this case with suspicion and bail out.
31891a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)
31901a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban                && dpmi == null) {
31911a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban            return false;
31921a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        }
31931a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban
31941a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        // WiFi config lockdown related logic. At this point we know uid NOT to be a Device Owner.
31951a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban
31961a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
31971a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban                config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
31981a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        if (!isConfigEligibleForLockdown) {
31991a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban            return isCreator || checkConfigOverridePermission(uid);
3200e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
3201e487a4648dd41881e754f1224aaedead78a0777dSky Faber
32021a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        final ContentResolver resolver = mContext.getContentResolver();
32031a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
32041a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban                Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
32051a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        return !isLockdownFeatureEnabled && checkConfigOverridePermission(uid);
3206e487a4648dd41881e754f1224aaedead78a0777dSky Faber    }
3207e487a4648dd41881e754f1224aaedead78a0777dSky Faber
3208e487a4648dd41881e754f1224aaedead78a0777dSky Faber    /**
3209e487a4648dd41881e754f1224aaedead78a0777dSky Faber     * Checks if uid has access to modify config.
3210e487a4648dd41881e754f1224aaedead78a0777dSky Faber     */
32111a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban    boolean canModifyNetwork(int uid, WifiConfiguration config, boolean onlyAnnotate) {
3212e487a4648dd41881e754f1224aaedead78a0777dSky Faber        if (config == null) {
3213e487a4648dd41881e754f1224aaedead78a0777dSky Faber            loge("canModifyNetowrk recieved null configuration");
3214e487a4648dd41881e754f1224aaedead78a0777dSky Faber            return false;
3215e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
3216e487a4648dd41881e754f1224aaedead78a0777dSky Faber
3217e487a4648dd41881e754f1224aaedead78a0777dSky Faber        // Resolve the correct network id.
3218e487a4648dd41881e754f1224aaedead78a0777dSky Faber        int netid;
321973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        if (config.networkId != INVALID_NETWORK_ID) {
3220e487a4648dd41881e754f1224aaedead78a0777dSky Faber            netid = config.networkId;
3221e487a4648dd41881e754f1224aaedead78a0777dSky Faber        } else {
3222bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski            WifiConfiguration test =
3223bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski                    mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
3224d03a9283285bb7adef6c687eb3a91fa4a8c4b502Vinit Deshpande            if (test == null) {
3225d03a9283285bb7adef6c687eb3a91fa4a8c4b502Vinit Deshpande                return false;
3226e487a4648dd41881e754f1224aaedead78a0777dSky Faber            } else {
3227d03a9283285bb7adef6c687eb3a91fa4a8c4b502Vinit Deshpande                netid = test.networkId;
3228e487a4648dd41881e754f1224aaedead78a0777dSky Faber            }
3229e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
3230e487a4648dd41881e754f1224aaedead78a0777dSky Faber
32311a86f1f7c11aaa9070a356ed2606c2a5d8d19adbZoltan Szatmary-Ban        return canModifyNetwork(uid, netid, onlyAnnotate);
3232e487a4648dd41881e754f1224aaedead78a0777dSky Faber    }
3233e487a4648dd41881e754f1224aaedead78a0777dSky Faber
3234e487a4648dd41881e754f1224aaedead78a0777dSky Faber    boolean checkConfigOverridePermission(int uid) {
3235611048d11641d9f8136cf2a7065aedbd57095cb9Jeff Sharkey        try {
32360fb9cf43830d67894b519c9a6271320c4842a5c0Bartosz Fabianowski            return (mFacade.checkUidPermission(
3237611048d11641d9f8136cf2a7065aedbd57095cb9Jeff Sharkey                    android.Manifest.permission.OVERRIDE_WIFI_CONFIG, uid)
3238611048d11641d9f8136cf2a7065aedbd57095cb9Jeff Sharkey                    == PackageManager.PERMISSION_GRANTED);
3239611048d11641d9f8136cf2a7065aedbd57095cb9Jeff Sharkey        } catch (RemoteException e) {
3240611048d11641d9f8136cf2a7065aedbd57095cb9Jeff Sharkey            return false;
3241e487a4648dd41881e754f1224aaedead78a0777dSky Faber        }
3242e487a4648dd41881e754f1224aaedead78a0777dSky Faber    }
3243e487a4648dd41881e754f1224aaedead78a0777dSky Faber
324427355a942653264388e909a4276196ee63e57811vandwalle    /** called when CS ask WiFistateMachine to disconnect the current network
324527355a942653264388e909a4276196ee63e57811vandwalle     * because the score is bad.
324627355a942653264388e909a4276196ee63e57811vandwalle     */
324727355a942653264388e909a4276196ee63e57811vandwalle    void handleBadNetworkDisconnectReport(int netId, WifiInfo info) {
324827355a942653264388e909a4276196ee63e57811vandwalle        /* TODO verify the bad network is current */
3249bcdabb1fa1894fcca610692ec94459fe623afa74Bartosz Fabianowski        WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
325027355a942653264388e909a4276196ee63e57811vandwalle        if (config != null) {
32518f0f666c8bdaf508f191f8590755140b92d970eaxinhe            if ((info.is24GHz() && info.getRssi()
32528f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND)
32538f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    || (info.is5GHz() && info.getRssi()
32548f0f666c8bdaf508f191f8590755140b92d970eaxinhe                    <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND)) {
32558f0f666c8bdaf508f191f8590755140b92d970eaxinhe                // We do not block due to bad RSSI since network selection should not select bad
32568f0f666c8bdaf508f191f8590755140b92d970eaxinhe                // RSSI candidate
325727355a942653264388e909a4276196ee63e57811vandwalle            } else {
3258be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle                // We got disabled but RSSI is good, so disable hard
32598f0f666c8bdaf508f191f8590755140b92d970eaxinhe                updateNetworkSelectionStatus(config,
32608f0f666c8bdaf508f191f8590755140b92d970eaxinhe                        WifiConfiguration.NetworkSelectionStatus.DISABLED_BAD_LINK);
326127355a942653264388e909a4276196ee63e57811vandwalle            }
326227355a942653264388e909a4276196ee63e57811vandwalle        }
32631ec92c57244311c7fca3ab6b244a06c2b2b58902vandwalle        // Record last time Connectivity Service switched us away from WiFi and onto Cell
3264ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius        mLastUnwantedNetworkDisconnectTimestamp = mClock.currentTimeMillis();
326527355a942653264388e909a4276196ee63e57811vandwalle    }
326640ff222cec1bd05879edb53abc75c6deead734cavandwalle
3267c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle    int getMaxDhcpRetries() {
3268c94a64a292925a00c33413c81a46941093495b3epkanwar        return mFacade.getIntegerSetting(mContext,
3269c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle                Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
3270c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle                DEFAULT_MAX_DHCP_RETRIES);
3271c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle    }
3272c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle
32739ccffbb6c3fe8eaa7d70cc3076d0dc3c6a9073e7Pierre Vandwalle    void clearBssidBlacklist() {
32742d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.clearBssidBlacklist();
32759ccffbb6c3fe8eaa7d70cc3076d0dc3c6a9073e7Pierre Vandwalle    }
32769ccffbb6c3fe8eaa7d70cc3076d0dc3c6a9073e7Pierre Vandwalle
32772d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius    void blackListBssid(String bssid) {
32782d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        mWifiConfigStore.blackListBssid(bssid);
32799ccffbb6c3fe8eaa7d70cc3076d0dc3c6a9073e7Pierre Vandwalle    }
32809ccffbb6c3fe8eaa7d70cc3076d0dc3c6a9073e7Pierre Vandwalle
32818f3ec73d1ce52b3f23e4cccd6a202b5707874f46xinhe    public boolean isBssidBlacklisted(String bssid) {
32822d65b9aaaa740ecf66bf4734c12aea3df88e352aRoshan Pius        return mWifiConfigStore.isBssidBlacklisted(bssid);
32838f0f666c8bdaf508f191f8590755140b92d970eaxinhe    }
3284e0aa0a004d161173992a0e9af1b431fae91f4a71vandwalle
328573a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    public boolean getEnableAutoJoinWhenAssociated() {
328673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        return mEnableAutoJoinWhenAssociated.get();
328773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan    }
328873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan
328943eba5ba17a9af5d9a050a4ba5e12e93c92f722dSamuel Tan    public void setEnableAutoJoinWhenAssociated(boolean enabled) {
329073a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan        mEnableAutoJoinWhenAssociated.set(enabled);
3291f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
3292308a06a125932081304655cda8374ffcf0772b3cSamuel Tan
3293308a06a125932081304655cda8374ffcf0772b3cSamuel Tan    public void setActiveScanDetail(ScanDetail activeScanDetail) {
3294308a06a125932081304655cda8374ffcf0772b3cSamuel Tan        synchronized (mActiveScanDetailLock) {
3295308a06a125932081304655cda8374ffcf0772b3cSamuel Tan            mActiveScanDetail = activeScanDetail;
3296308a06a125932081304655cda8374ffcf0772b3cSamuel Tan        }
3297308a06a125932081304655cda8374ffcf0772b3cSamuel Tan    }
3298a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius
3299a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius    /**
3300a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius     * Check if the provided ephemeral network was deleted by the user or not.
3301a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius     * @param ssid ssid of the network
3302a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius     * @return true if network was deleted, false otherwise.
3303a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius     */
3304a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius    public boolean wasEphemeralNetworkDeleted(String ssid) {
3305a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius        return mDeletedEphemeralSSIDs.contains(ssid);
3306a6b66a48b231f5729b8015d3446feb4c2fa0a9d1Roshan Pius    }
3307155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande}
3308