1c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne/*
2c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * Copyright (C) 2016 The Android Open Source Project
3c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne *
4c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * Licensed under the Apache License, Version 2.0 (the "License");
5c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * you may not use this file except in compliance with the License.
6c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * You may obtain a copy of the License at
7c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne *
8c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne *      http://www.apache.org/licenses/LICENSE-2.0
9c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne *
10c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * Unless required by applicable law or agreed to in writing, software
11c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * distributed under the License is distributed on an "AS IS" BASIS,
12c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * See the License for the specific language governing permissions and
14c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * limitations under the License.
15c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne */
16c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
17c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhnepackage com.android.server.wifi;
18c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
19c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.content.Context;
20c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
21c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.net.wifi.ScanResult;
22c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
23c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.net.wifi.WifiConfiguration;
240195dc3dabc52cfb1455308109625a23ee126880Roshan Piusimport android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
25c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.net.wifi.WifiSsid;
26c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.os.Environment;
27c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.os.Process;
28c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.text.TextUtils;
29c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
30c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.util.LocalLog;
31c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport android.util.Log;
32c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
33c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport com.android.server.net.DelayedDiskWrite;
34c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
35c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.io.BufferedInputStream;
36c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.io.DataInputStream;
37c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.io.DataOutputStream;
38c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.io.EOFException;
39c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.io.FileInputStream;
40c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.io.IOException;
41c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.text.DateFormat;
42c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.util.BitSet;
43c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.util.HashMap;
44c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.util.HashSet;
45c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.util.List;
46c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.util.Map;
47c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhneimport java.util.Set;
48adf70a7b3856bed24be4ddaf3a7d69da37c1f952Randy Panimport java.util.concurrent.ConcurrentHashMap;
49c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
50c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne/**
51c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * Provides an API to read and write the network history from WifiConfigurations to file
52c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne * This is largely separate and extra to the supplicant config file.
53c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne */
54c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhnepublic class WifiNetworkHistory {
55c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    public static final String TAG = "WifiNetworkHistory";
56c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final boolean DBG = true;
57c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final boolean VDBG = true;
58c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    static final String NETWORK_HISTORY_CONFIG_FILE = Environment.getDataDirectory()
59c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            + "/misc/wifi/networkHistory.txt";
60c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /* Network History Keys */
61c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String SSID_KEY = "SSID";
62c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    static final String CONFIG_KEY = "CONFIG";
63c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String CONFIG_BSSID_KEY = "CONFIG_BSSID";
64c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String CHOICE_KEY = "CHOICE";
65c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String CHOICE_TIME_KEY = "CHOICE_TIME";
66c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String LINK_KEY = "LINK";
67c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String BSSID_KEY = "BSSID";
68c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String BSSID_KEY_END = "/BSSID";
69c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String RSSI_KEY = "RSSI";
70c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String FREQ_KEY = "FREQ";
71c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String DATE_KEY = "DATE";
72c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String MILLI_KEY = "MILLI";
73c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String NETWORK_ID_KEY = "ID";
74c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String PRIORITY_KEY = "PRIORITY";
75c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String DEFAULT_GW_KEY = "DEFAULT_GW";
76c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String AUTH_KEY = "AUTH";
77c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String BSSID_STATUS_KEY = "BSSID_STATUS";
78c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String SELF_ADDED_KEY = "SELF_ADDED";
79c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String FAILURE_KEY = "FAILURE";
80c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String DID_SELF_ADD_KEY = "DID_SELF_ADD";
81c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String PEER_CONFIGURATION_KEY = "PEER_CONFIGURATION";
82c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    static final String CREATOR_UID_KEY = "CREATOR_UID_KEY";
83c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String CONNECT_UID_KEY = "CONNECT_UID_KEY";
84c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String UPDATE_UID_KEY = "UPDATE_UID";
85c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String FQDN_KEY = "FQDN";
86c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String SCORER_OVERRIDE_KEY = "SCORER_OVERRIDE";
87c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String SCORER_OVERRIDE_AND_SWITCH_KEY = "SCORER_OVERRIDE_AND_SWITCH";
88c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String VALIDATED_INTERNET_ACCESS_KEY = "VALIDATED_INTERNET_ACCESS";
89c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String NO_INTERNET_ACCESS_REPORTS_KEY = "NO_INTERNET_ACCESS_REPORTS";
903ea09e080a9ab3ed594356d8f3e498ec61a4d0fbJack Tian    private static final String NO_INTERNET_ACCESS_EXPECTED_KEY = "NO_INTERNET_ACCESS_EXPECTED";
91c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String EPHEMERAL_KEY = "EPHEMERAL";
92ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin    private static final String USE_EXTERNAL_SCORES_KEY = "USE_EXTERNAL_SCORES";
933ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin    private static final String METERED_HINT_KEY = "METERED_HINT";
94c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String NUM_ASSOCIATION_KEY = "NUM_ASSOCIATION";
95c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String DELETED_EPHEMERAL_KEY = "DELETED_EPHEMERAL";
96c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String CREATOR_NAME_KEY = "CREATOR_NAME";
97c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String UPDATE_NAME_KEY = "UPDATE_NAME";
98c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String USER_APPROVED_KEY = "USER_APPROVED";
99c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String CREATION_TIME_KEY = "CREATION_TIME";
100c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String UPDATE_TIME_KEY = "UPDATE_TIME";
101c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    static final String SHARED_KEY = "SHARED";
102c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String NETWORK_SELECTION_STATUS_KEY = "NETWORK_SELECTION_STATUS";
103c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String NETWORK_SELECTION_DISABLE_REASON_KEY =
104c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            "NETWORK_SELECTION_DISABLE_REASON";
10511b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein    private static final String HAS_EVER_CONNECTED_KEY = "HAS_EVER_CONNECTED";
106c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
107c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String SEPARATOR = ":  ";
108c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static final String NL = "\n";
109c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
110c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    protected final DelayedDiskWrite mWriter;
111c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    Context mContext;
112c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private final LocalLog mLocalLog;
113c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /*
114c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * Lost config list, whenever we read a config from networkHistory.txt that was not in
115c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * wpa_supplicant.conf
116c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     */
117c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    HashSet<String> mLostConfigsDbg = new HashSet<String>();
118c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
119c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    public WifiNetworkHistory(Context c, LocalLog localLog, DelayedDiskWrite writer) {
120c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        mContext = c;
121c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        mWriter = writer;
122c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        mLocalLog = localLog;
123c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
124c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
125c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /**
126c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * Write network history to file, for configured networks
127c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     *
128c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * @param networks List of ConfiguredNetworks to write to NetworkHistory
129c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     */
130c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    public void writeKnownNetworkHistory(final List<WifiConfiguration> networks,
131adf70a7b3856bed24be4ddaf3a7d69da37c1f952Randy Pan            final ConcurrentHashMap<Integer, ScanDetailCache> scanDetailCaches,
132c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            final Set<String> deletedEphemeralSSIDs) {
133c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
134c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        /* Make a copy */
135c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        //final List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
136c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
137c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        //for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
138c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        //    networks.add(new WifiConfiguration(config));
139c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        //}
140c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
141c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        mWriter.write(NETWORK_HISTORY_CONFIG_FILE, new DelayedDiskWrite.Writer() {
142c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            public void onWriteCalled(DataOutputStream out) throws IOException {
143c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                for (WifiConfiguration config : networks) {
144c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    //loge("onWriteCalled write SSID: " + config.SSID);
145c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                   /* if (config.getLinkProperties() != null)
146c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        loge(" lp " + config.getLinkProperties().toString());
147c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    else
148c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        loge("attempt config w/o lp");
149c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    */
1500195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                    NetworkSelectionStatus status = config.getNetworkSelectionStatus();
151c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (VDBG) {
152c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        int numlink = 0;
153c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        if (config.linkedConfigurations != null) {
154c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            numlink = config.linkedConfigurations.size();
155c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        }
156c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        String disableTime;
157c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        if (config.getNetworkSelectionStatus().isNetworkEnabled()) {
158c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            disableTime = "";
159c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        } else {
160c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            disableTime = "Disable time: " + DateFormat.getInstance().format(
161c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    config.getNetworkSelectionStatus().getDisableTime());
162c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        }
163f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne                        logd("saving network history: " + config.configKey()  + " gw: "
164c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + config.defaultGwMacAddress + " Network Selection-status: "
165c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + status.getNetworkStatusString()
166c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + disableTime + " ephemeral=" + config.ephemeral
167c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + " choice:" + status.getConnectChoice()
168c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + " link:" + numlink
169c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + " status:" + config.status
17011b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                                + " nid:" + config.networkId
17111b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                                + " hasEverConnected: " + status.getHasEverConnected());
172c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
173c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
174c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (!isValid(config)) {
175c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        continue;
176c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
177c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
178c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.SSID == null) {
179c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        if (VDBG) {
180f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne                            logv("writeKnownNetworkHistory trying to write config with null SSID");
181c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        }
182c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        continue;
183c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
184c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (VDBG) {
185f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne                        logv("writeKnownNetworkHistory write config " + config.configKey());
186c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
187c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(CONFIG_KEY + SEPARATOR + config.configKey() + NL);
188c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
189c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.SSID != null) {
190c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(SSID_KEY + SEPARATOR + config.SSID + NL);
191c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
192c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.BSSID != null) {
193c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(CONFIG_BSSID_KEY + SEPARATOR + config.BSSID + NL);
194c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    } else {
195c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(CONFIG_BSSID_KEY + SEPARATOR + "null" + NL);
196c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
197c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.FQDN != null) {
198c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(FQDN_KEY + SEPARATOR + config.FQDN + NL);
199c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
200c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
201c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(PRIORITY_KEY + SEPARATOR + Integer.toString(config.priority) + NL);
202c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NETWORK_ID_KEY + SEPARATOR
203c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.networkId) + NL);
204c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(SELF_ADDED_KEY + SEPARATOR
205c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Boolean.toString(config.selfAdded) + NL);
206c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(DID_SELF_ADD_KEY + SEPARATOR
207c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Boolean.toString(config.didSelfAdd) + NL);
208c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NO_INTERNET_ACCESS_REPORTS_KEY + SEPARATOR
209c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.numNoInternetAccessReports) + NL);
210c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(VALIDATED_INTERNET_ACCESS_KEY + SEPARATOR
211c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Boolean.toString(config.validatedInternetAccess) + NL);
2123ea09e080a9ab3ed594356d8f3e498ec61a4d0fbJack Tian                    out.writeUTF(NO_INTERNET_ACCESS_EXPECTED_KEY + SEPARATOR +
2133ea09e080a9ab3ed594356d8f3e498ec61a4d0fbJack Tian                            Boolean.toString(config.noInternetAccessExpected) + NL);
214c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(EPHEMERAL_KEY + SEPARATOR
215c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Boolean.toString(config.ephemeral) + NL);
2163ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin                    out.writeUTF(METERED_HINT_KEY + SEPARATOR
2173ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin                            + Boolean.toString(config.meteredHint) + NL);
218ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin                    out.writeUTF(USE_EXTERNAL_SCORES_KEY + SEPARATOR
219ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin                            + Boolean.toString(config.useExternalScores) + NL);
220c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.creationTime != null) {
221c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(CREATION_TIME_KEY + SEPARATOR + config.creationTime + NL);
222c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
223c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.updateTime != null) {
224c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(UPDATE_TIME_KEY + SEPARATOR + config.updateTime + NL);
225c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
226c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.peerWifiConfiguration != null) {
227c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(PEER_CONFIGURATION_KEY + SEPARATOR
228c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + config.peerWifiConfiguration + NL);
229c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
230c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(SCORER_OVERRIDE_KEY + SEPARATOR
231c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.numScorerOverride) + NL);
232c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(SCORER_OVERRIDE_AND_SWITCH_KEY + SEPARATOR
233c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.numScorerOverrideAndSwitchedNetwork) + NL);
234c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NUM_ASSOCIATION_KEY + SEPARATOR
235c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.numAssociation) + NL);
236c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(CREATOR_UID_KEY + SEPARATOR
237c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.creatorUid) + NL);
238c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(CONNECT_UID_KEY + SEPARATOR
239c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.lastConnectUid) + NL);
240c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(UPDATE_UID_KEY + SEPARATOR
241c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.lastUpdateUid) + NL);
242c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(CREATOR_NAME_KEY + SEPARATOR
243c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + config.creatorName + NL);
244c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(UPDATE_NAME_KEY + SEPARATOR
245c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + config.lastUpdateName + NL);
246c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(USER_APPROVED_KEY + SEPARATOR
247c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + Integer.toString(config.userApproved) + NL);
248c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(SHARED_KEY + SEPARATOR + Boolean.toString(config.shared) + NL);
249c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    String allowedKeyManagementString =
250c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            makeString(config.allowedKeyManagement,
251c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    WifiConfiguration.KeyMgmt.strings);
252c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(AUTH_KEY + SEPARATOR
253c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + allowedKeyManagementString + NL);
254c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NETWORK_SELECTION_STATUS_KEY + SEPARATOR
255c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + status.getNetworkSelectionStatus() + NL);
256c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NETWORK_SELECTION_DISABLE_REASON_KEY + SEPARATOR
257c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            + status.getNetworkSelectionDisableReason() + NL);
258c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
259c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (status.getConnectChoice() != null) {
260c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(CHOICE_KEY + SEPARATOR + status.getConnectChoice() + NL);
261c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(CHOICE_TIME_KEY + SEPARATOR
262c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + status.getConnectChoiceTimestamp() + NL);
263c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
264c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
265c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.linkedConfigurations != null) {
266c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        log("writeKnownNetworkHistory write linked "
267c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + config.linkedConfigurations.size());
268c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
269c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        for (String key : config.linkedConfigurations.keySet()) {
270c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            out.writeUTF(LINK_KEY + SEPARATOR + key + NL);
271c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        }
272c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
273c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
274c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    String macAddress = config.defaultGwMacAddress;
275c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (macAddress != null) {
276c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(DEFAULT_GW_KEY + SEPARATOR + macAddress + NL);
277c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
278c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
279c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (getScanDetailCache(config, scanDetailCaches) != null) {
280c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        for (ScanDetail scanDetail : getScanDetailCache(config,
281c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    scanDetailCaches).values()) {
282c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            ScanResult result = scanDetail.getScanResult();
283c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            out.writeUTF(BSSID_KEY + SEPARATOR
284c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    + result.BSSID + NL);
285c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            out.writeUTF(FREQ_KEY + SEPARATOR
286c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    + Integer.toString(result.frequency) + NL);
287c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
288c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            out.writeUTF(RSSI_KEY + SEPARATOR
289c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    + Integer.toString(result.level) + NL);
290c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
291c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            out.writeUTF(BSSID_KEY_END + NL);
292c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        }
293c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
294c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config.lastFailure != null) {
295c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(FAILURE_KEY + SEPARATOR + config.lastFailure + NL);
296c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
29711b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                    out.writeUTF(HAS_EVER_CONNECTED_KEY + SEPARATOR
29811b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                            + Boolean.toString(status.getHasEverConnected()) + NL);
299c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NL);
300c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    // Add extra blank lines for clarity
301c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NL);
302c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    out.writeUTF(NL);
303c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                }
304c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                if (deletedEphemeralSSIDs != null && deletedEphemeralSSIDs.size() > 0) {
305c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    for (String ssid : deletedEphemeralSSIDs) {
306c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(DELETED_EPHEMERAL_KEY);
307c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(ssid);
308c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        out.writeUTF(NL);
309c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
310c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                }
311c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            }
312c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        });
313c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
314c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
315c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /**
316c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * Adds information stored in networkHistory.txt to the given configs. The configs are provided
317c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * as a mapping from configKey to WifiConfiguration, because the WifiConfigurations themselves
318c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * do not contain sufficient information to compute their configKeys until after the information
319c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * that is stored in networkHistory.txt has been added to them.
320c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     *
321c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * @param configs mapping from configKey to a WifiConfiguration that contains the information
322c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     *         information read from wpa_supplicant.conf
323c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     */
324c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    public void readNetworkHistory(Map<String, WifiConfiguration> configs,
325adf70a7b3856bed24be4ddaf3a7d69da37c1f952Randy Pan            ConcurrentHashMap<Integer, ScanDetailCache> scanDetailCaches,
326c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            Set<String> deletedEphemeralSSIDs) {
327c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        localLog("readNetworkHistory() path:" + NETWORK_HISTORY_CONFIG_FILE);
328c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
329c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        try (DataInputStream in =
330c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                     new DataInputStream(new BufferedInputStream(
331c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             new FileInputStream(NETWORK_HISTORY_CONFIG_FILE)))) {
332c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
333c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            String bssid = null;
334c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            String ssid = null;
335c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
336c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            int freq = 0;
337c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            int status = 0;
338c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            long seen = 0;
339c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            int rssi = WifiConfiguration.INVALID_RSSI;
340c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            String caps = null;
341c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
342c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            WifiConfiguration config = null;
343c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            while (true) {
344c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                String line = in.readUTF();
345c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                if (line == null) {
346c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    break;
347c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                }
348c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                int colon = line.indexOf(':');
349c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                if (colon < 0) {
350c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    continue;
351c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                }
352c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
353c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                String key = line.substring(0, colon).trim();
354c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                String value = line.substring(colon + 1).trim();
355c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
356c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                if (key.equals(CONFIG_KEY)) {
357c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    config = configs.get(value);
358c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
359c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    // skip reading that configuration data
360c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    // since we don't have a corresponding network ID
361c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    if (config == null) {
362c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        localLog("readNetworkHistory didnt find netid for hash="
363c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + Integer.toString(value.hashCode())
364c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                + " key: " + value);
365c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        mLostConfigsDbg.add(value);
366c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        continue;
367c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    } else {
368c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        // After an upgrade count old connections as owned by system
369c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        if (config.creatorName == null || config.lastUpdateName == null) {
370c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.creatorName =
371c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                mContext.getPackageManager().getNameForUid(Process.SYSTEM_UID);
372c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.lastUpdateName = config.creatorName;
373c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
374c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            if (DBG) {
375c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                Log.w(TAG, "Upgrading network " + config.networkId
376c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                        + " to " + config.creatorName);
377c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            }
378c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        }
379c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
380c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                } else if (config != null) {
3810195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                    NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
382c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    switch (key) {
383c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case SSID_KEY:
384c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            if (config.isPasspoint()) {
385c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                break;
386c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            }
387c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            ssid = value;
388c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            if (config.SSID != null && !config.SSID.equals(ssid)) {
389c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                loge("Error parsing network history file, mismatched SSIDs");
390c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                config = null; //error
391c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                ssid = null;
392c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            } else {
393c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                config.SSID = ssid;
394c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            }
395c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
396c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CONFIG_BSSID_KEY:
397c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.BSSID = value.equals("null") ? null : value;
398c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
399c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case FQDN_KEY:
400c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            // Check for literal 'null' to be backwards compatible.
401c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.FQDN = value.equals("null") ? null : value;
402c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
403c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case DEFAULT_GW_KEY:
404c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.defaultGwMacAddress = value;
405c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
406c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case SELF_ADDED_KEY:
407c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.selfAdded = Boolean.parseBoolean(value);
408c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
409c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case DID_SELF_ADD_KEY:
410c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.didSelfAdd = Boolean.parseBoolean(value);
411c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
412c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case NO_INTERNET_ACCESS_REPORTS_KEY:
413c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.numNoInternetAccessReports = Integer.parseInt(value);
414c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
415c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case VALIDATED_INTERNET_ACCESS_KEY:
416c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.validatedInternetAccess = Boolean.parseBoolean(value);
417c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
4183ea09e080a9ab3ed594356d8f3e498ec61a4d0fbJack Tian                        case NO_INTERNET_ACCESS_EXPECTED_KEY:
4193ea09e080a9ab3ed594356d8f3e498ec61a4d0fbJack Tian                            config.noInternetAccessExpected = Boolean.parseBoolean(value);
4203ea09e080a9ab3ed594356d8f3e498ec61a4d0fbJack Tian                            break;
421c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CREATION_TIME_KEY:
422c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.creationTime = value;
423c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
424c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case UPDATE_TIME_KEY:
425c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.updateTime = value;
426c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
427c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case EPHEMERAL_KEY:
428c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.ephemeral = Boolean.parseBoolean(value);
429c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
4303ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin                        case METERED_HINT_KEY:
4313ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin                            config.meteredHint = Boolean.parseBoolean(value);
4323ab8ec5cfa986b07e1c948af0f45bd333edef24cJeremy Joslin                            break;
433ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin                        case USE_EXTERNAL_SCORES_KEY:
434ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin                            config.useExternalScores = Boolean.parseBoolean(value);
435ea2048738be95ae9d5367a42ba798503a7039a6bJeremy Joslin                            break;
436c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CREATOR_UID_KEY:
437c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.creatorUid = Integer.parseInt(value);
438c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
439c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case SCORER_OVERRIDE_KEY:
440c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.numScorerOverride = Integer.parseInt(value);
441c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
442c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case SCORER_OVERRIDE_AND_SWITCH_KEY:
443c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.numScorerOverrideAndSwitchedNetwork = Integer.parseInt(value);
444c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
445c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case NUM_ASSOCIATION_KEY:
446c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.numAssociation = Integer.parseInt(value);
447c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
448c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CONNECT_UID_KEY:
449c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.lastConnectUid = Integer.parseInt(value);
450c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
451c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case UPDATE_UID_KEY:
452c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.lastUpdateUid = Integer.parseInt(value);
453c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
454c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case FAILURE_KEY:
455c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.lastFailure = value;
456c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
457c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case PEER_CONFIGURATION_KEY:
458c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.peerWifiConfiguration = value;
459c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
460c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case NETWORK_SELECTION_STATUS_KEY:
4610195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                            int networkStatusValue = Integer.parseInt(value);
4620195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                            // Reset temporarily disabled network status
4630195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                            if (networkStatusValue ==
4640195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                                    NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED) {
4650195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                                networkStatusValue =
4660195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                                        NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
4670195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                            }
4680195dc3dabc52cfb1455308109625a23ee126880Roshan Pius                            networkStatus.setNetworkSelectionStatus(networkStatusValue);
469c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
470c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case NETWORK_SELECTION_DISABLE_REASON_KEY:
471c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            networkStatus.setNetworkSelectionDisableReason(Integer.parseInt(value));
472c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
473c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CHOICE_KEY:
474c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            networkStatus.setConnectChoice(value);
475c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
476c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CHOICE_TIME_KEY:
477c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            networkStatus.setConnectChoiceTimestamp(Long.parseLong(value));
478c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
479c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case LINK_KEY:
480c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            if (config.linkedConfigurations == null) {
481c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                config.linkedConfigurations = new HashMap<>();
482c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            } else {
483c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                config.linkedConfigurations.put(value, -1);
484c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            }
485c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
486c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case BSSID_KEY:
487c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            status = 0;
488c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            ssid = null;
489c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            bssid = null;
490c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            freq = 0;
491c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            seen = 0;
492c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            rssi = WifiConfiguration.INVALID_RSSI;
493c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            caps = "";
494c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
495c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case RSSI_KEY:
496c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            rssi = Integer.parseInt(value);
497c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
498c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case FREQ_KEY:
499c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            freq = Integer.parseInt(value);
500c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
501c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case DATE_KEY:
502c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            /*
503c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             * when reading the configuration from file we don't update the date
504c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             * so as to avoid reading back stale or non-sensical data that would
505c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             * depend on network time.
506c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             * The date of a WifiConfiguration should only come from actual scan
507c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             * result.
508c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                             *
509c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            String s = key.replace(FREQ_KEY, "");
510c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            seen = Integer.getInteger(s);
511c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            */
512c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
513c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case BSSID_KEY_END:
514c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            if ((bssid != null) && (ssid != null)) {
515c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                if (getScanDetailCache(config, scanDetailCaches) != null) {
516c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    WifiSsid wssid = WifiSsid.createFromAsciiEncoded(ssid);
517c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    ScanDetail scanDetail = new ScanDetail(wssid, bssid,
518c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                            caps, rssi, freq, (long) 0, seen);
519c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                    getScanDetailCache(config, scanDetailCaches).put(scanDetail);
520c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                }
521c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            }
522c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
523c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case DELETED_EPHEMERAL_KEY:
524c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            if (!TextUtils.isEmpty(value)) {
525c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                                deletedEphemeralSSIDs.add(value);
526c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            }
527c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
528c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case CREATOR_NAME_KEY:
529c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.creatorName = value;
530c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
531c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case UPDATE_NAME_KEY:
532c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.lastUpdateName = value;
533c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
534c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case USER_APPROVED_KEY:
535c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.userApproved = Integer.parseInt(value);
536c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
537c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                        case SHARED_KEY:
538c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            config.shared = Boolean.parseBoolean(value);
539c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                            break;
54011b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                        case HAS_EVER_CONNECTED_KEY:
54111b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                            networkStatus.setHasEverConnected(Boolean.parseBoolean(value));
54211b4c4c3c813237826117270741c63faa0d312aaRebecca Silberstein                            break;
543c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    }
544c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                }
545c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            }
546c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        } catch (NumberFormatException e) {
547c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            Log.e(TAG, "readNetworkHistory: failed to read, revert to default, " + e, e);
548c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        } catch (EOFException e) {
549c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            // do nothing
550c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        } catch (IOException e) {
551c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            Log.e(TAG, "readNetworkHistory: No config file, revert to default, " + e, e);
552c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
553c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
554c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
555c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    /**
556c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * Ported this out of WifiServiceImpl, I have no idea what it's doing
557c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * <TODO> figure out what/why this is doing
558c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     * <TODO> Port it into WifiConfiguration, then remove all the silly business from ServiceImpl
559c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne     */
560c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    public boolean isValid(WifiConfiguration config) {
561c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (config.allowedKeyManagement == null) {
562c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            return false;
563c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
564c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (config.allowedKeyManagement.cardinality() > 1) {
565c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            if (config.allowedKeyManagement.cardinality() != 2) {
566c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                return false;
567c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            }
568c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) {
569c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                return false;
570c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            }
571c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            if ((!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X))
572c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    && (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK))) {
573c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                return false;
574c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            }
575c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
576c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        return true;
577c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
578c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
579c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private static String makeString(BitSet set, String[] strings) {
580c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        StringBuffer buf = new StringBuffer();
581c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        int nextSetBit = -1;
582c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
583c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        /* Make sure all set bits are in [0, strings.length) to avoid
584c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne         * going out of bounds on strings.  (Shouldn't happen, but...) */
585c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        set = set.get(0, strings.length);
586c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
587c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
588c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
589c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
590c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
591c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        // remove trailing space
592c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (set.cardinality() > 0) {
593c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            buf.setLength(buf.length() - 1);
594c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
595c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
596c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        return buf.toString();
597c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
598c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
599f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne    protected void logv(String s) {
600f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne        Log.v(TAG, s);
601f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne    }
602f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne    protected void logd(String s) {
603f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne        Log.d(TAG, s);
604f99504e885ef365adb0c54263dcf7fecfedf9f1cGlen Kuhne    }
605c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    protected void log(String s) {
606c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        Log.d(TAG, s);
607c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
608c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    protected void loge(String s) {
609c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        loge(s, false);
610c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
611c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    protected void loge(String s, boolean stack) {
612c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (stack) {
613c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            Log.e(TAG, s + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
614c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
615c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
616c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne                    + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
617c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        } else {
618c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            Log.e(TAG, s);
619c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
620c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
621c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
622c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private void localLog(String s) {
623c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (mLocalLog != null) {
624c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            mLocalLog.log(s);
625c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
626c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
627c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne
628c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    private ScanDetailCache getScanDetailCache(WifiConfiguration config,
629adf70a7b3856bed24be4ddaf3a7d69da37c1f952Randy Pan            ConcurrentHashMap<Integer, ScanDetailCache> scanDetailCaches) {
630c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (config == null || scanDetailCaches == null) return null;
631c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        ScanDetailCache cache = scanDetailCaches.get(config.networkId);
632c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
633c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            cache = new ScanDetailCache(config);
634c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne            scanDetailCaches.put(config.networkId, cache);
635c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        }
636c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne        return cache;
637c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne    }
638c485ebf64d1049d17db8108b85653f53fcdc8949Glen Kuhne}
639