WifiNative.java revision 30f34829e0e7e49dc09c897c72dd0ded7d9805eb
137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/*
237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * Copyright (C) 2008 The Android Open Source Project
337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *
437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
5ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * you may not use this file except in compliance with the License.
637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * You may obtain a copy of the License at
737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *
837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *      http://www.apache.org/licenses/LICENSE-2.0
937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *
1037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * Unless required by applicable law or agreed to in writing, software
1137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
1237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * See the License for the specific language governing permissions and
1437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * limitations under the License.
1537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines */
1637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
1737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinespackage com.android.server.wifi;
1837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
1937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.annotation.Nullable;
2037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.apf.ApfCapabilities;
2137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.IApInterface;
2237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.IClientInterface;
2337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.RttManager;
2437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.RttManager.ResponderConfig;
2537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.ScanResult;
2637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.WifiConfiguration;
2737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.WifiLinkLayerStats;
2837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.WifiScanner;
2937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.net.wifi.WifiWakeReasonAndCounts;
3037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.os.SystemClock;
3137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.util.Log;
3237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport android.util.SparseArray;
3337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
3437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport com.android.internal.annotations.Immutable;
3537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport com.android.internal.util.HexDump;
3637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport com.android.server.connectivity.KeepalivePacketData;
3737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport com.android.server.wifi.util.FrameParser;
3837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
3937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.io.PrintWriter;
4037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.io.StringWriter;
4137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.nio.ByteBuffer;
4237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.nio.CharBuffer;
4337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.nio.charset.CharacterCodingException;
4437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.nio.charset.CharsetDecoder;
4537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.nio.charset.StandardCharsets;
4637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.text.SimpleDateFormat;
4737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.util.ArrayList;
4837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.util.Date;
4937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.util.Map;
5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.util.Objects;
5137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.util.Set;
5237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimport java.util.TimeZone;
5337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
5437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
5537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/**
5637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * Native calls for bring up/shut down of the supplicant daemon and for
5737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * sending requests to the supplicant daemon
5837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *
5937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * {@hide}
6037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines */
6137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinespublic class WifiNative {
6237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    private final String mTAG;
6337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    private final String mInterfaceName;
6437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    private final SupplicantStaIfaceHal mSupplicantStaIfaceHal;
6537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    private final WifiVendorHal mWifiVendorHal;
6637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    private final WificondControl mWificondControl;
6737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
6837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public WifiNative(String interfaceName, WifiVendorHal vendorHal,
6937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                      SupplicantStaIfaceHal staIfaceHal, WificondControl condControl) {
7037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mTAG = "WifiNative-" + interfaceName;
7137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mInterfaceName = interfaceName;
7237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mWifiVendorHal = vendorHal;
7337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mSupplicantStaIfaceHal = staIfaceHal;
7437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mWificondControl = condControl;
7537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
7637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
7737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public String getInterfaceName() {
7837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        return mInterfaceName;
7937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
8037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
8137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    /**
8237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * Enable verbose logging for all sub modules.
8337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     */
8437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public void enableVerboseLogging(int verbose) {
8537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mWificondControl.enableVerboseLogging(verbose > 0 ? true : false);
8637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mSupplicantStaIfaceHal.enableVerboseLogging(verbose > 0);
8737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        mWifiVendorHal.enableVerboseLogging(verbose > 0);
8837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
8937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
9037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines   /********************************************************
9137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * Native Initialization/Deinitialization
9237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    ********************************************************/
9337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
9437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines   /**
9537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * Setup wifi native for Client mode operations.
9637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    *
9737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * 1. Starts the Wifi HAL and configures it in client/STA mode.
9837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * 2. Setup Wificond to operate in client mode and retrieve the handle to use for client
9937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * operations.
10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    *
10137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * @return An IClientInterface as wificond client interface binder handler.
10237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    * Returns null on failure.
10337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    */
10437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public IClientInterface setupForClientMode() {
10537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        if (!startHalIfNecessary(true)) {
10637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            Log.e(mTAG, "Failed to start HAL for client mode");
107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            return null;
108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        }
10937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        return mWificondControl.setupDriverForClientMode();
11037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
11137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
11237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    /**
11337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * Setup wifi native for AP mode operations.
11437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     *
11537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * 1. Starts the Wifi HAL and configures it in AP mode.
116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     * 2. Setup Wificond to operate in AP mode and retrieve the handle to use for ap operations.
11737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     *
11837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * @return An IApInterface as wificond Ap interface binder handler.
11937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * Returns null on failure.
12037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     */
12137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public IApInterface setupForSoftApMode() {
12237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        if (!startHalIfNecessary(false)) {
12337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            Log.e(mTAG, "Failed to start HAL for AP mode");
12437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            return null;
12537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        }
12637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        return mWificondControl.setupDriverForSoftApMode();
12737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
12837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
12937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    /**
13037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * Teardown all mode configurations in wifi native.
13137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     *
13237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * 1. Tears down all the interfaces from Wificond.
13337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * 2. Stops the Wifi HAL.
13437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     *
13537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     * @return Returns true on success.
13637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines     */
13737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public boolean tearDown() {
13837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        if (!mWificondControl.tearDownInterfaces()) {
13937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            // TODO(b/34859006): Handle failures.
14037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            Log.e(mTAG, "Failed to teardown interfaces from Wificond");
141            return false;
142        }
143        stopHalIfNecessary();
144        return true;
145    }
146
147    /********************************************************
148     * Wificond operations
149     ********************************************************/
150    /**
151     * Result of a signal poll.
152     */
153    public static class SignalPollResult {
154        // RSSI value in dBM.
155        public int currentRssi;
156        //Transmission bit rate in Mbps.
157        public int txBitrate;
158        // Association frequency in MHz.
159        public int associationFrequency;
160    }
161
162    /**
163     * WiFi interface transimission counters.
164     */
165    public static class TxPacketCounters {
166        // Number of successfully transmitted packets.
167        public int txSucceeded;
168        // Number of tramsmission failures.
169        public int txFailed;
170    }
171
172    /**
173    * Disable wpa_supplicant via wificond.
174    * @return Returns true on success.
175    */
176    public boolean disableSupplicant() {
177        return mWificondControl.disableSupplicant();
178    }
179
180    /**
181    * Enable wpa_supplicant via wificond.
182    * @return Returns true on success.
183    */
184    public boolean enableSupplicant() {
185        return mWificondControl.enableSupplicant();
186    }
187
188    /**
189    * Request signal polling to wificond.
190    * Returns an SignalPollResult object.
191    * Returns null on failure.
192    */
193    public SignalPollResult signalPoll() {
194        return mWificondControl.signalPoll();
195    }
196
197    /**
198     * Fetch TX packet counters on current connection from wificond.
199    * Returns an TxPacketCounters object.
200    * Returns null on failure.
201    */
202    public TxPacketCounters getTxPacketCounters() {
203        return mWificondControl.getTxPacketCounters();
204    }
205
206    /**
207     * Start a scan using wificond for the given parameters.
208     * @param freqs list of frequencies to scan for, if null scan all supported channels.
209     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
210     * @return Returns true on success.
211     */
212    public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
213        return mWificondControl.scan(freqs, hiddenNetworkSSIDs);
214    }
215
216    /**
217     * Fetch the latest scan result from kernel via wificond.
218     * @return Returns an ArrayList of ScanDetail.
219     * Returns an empty ArrayList on failure.
220     */
221    public ArrayList<ScanDetail> getScanResults() {
222        return mWificondControl.getScanResults();
223    }
224
225    /**
226     * Start PNO scan.
227     * @param pnoSettings Pno scan configuration.
228     * @return true on success.
229     */
230    public boolean startPnoScan(PnoSettings pnoSettings) {
231        return mWificondControl.startPnoScan(pnoSettings);
232    }
233
234    /**
235     * Stop PNO scan.
236     * @return true on success.
237     */
238    public boolean stopPnoScan() {
239        return mWificondControl.stopPnoScan();
240    }
241
242    /********************************************************
243     * Supplicant operations
244     ********************************************************/
245
246    /**
247     * This method is called repeatedly until the connection to wpa_supplicant is established.
248     *
249     * @return true if connection is established, false otherwise.
250     * TODO: Add unit tests for these once we remove the legacy code.
251     */
252    public boolean connectToSupplicant() {
253        // Start initialization if not already started.
254        if (!mSupplicantStaIfaceHal.isInitializationStarted()
255                && !mSupplicantStaIfaceHal.initialize()) {
256            return false;
257        }
258        // Check if the initialization is complete.
259        return mSupplicantStaIfaceHal.isInitializationComplete();
260    }
261
262    /**
263     * Close supplicant connection.
264     */
265    public void closeSupplicantConnection() {
266        // Nothing to do for HIDL.
267    }
268
269    /**
270     * Set supplicant log level
271     *
272     * @param turnOnVerbose Whether to turn on verbose logging or not.
273     */
274    public void setSupplicantLogLevel(boolean turnOnVerbose) {
275        mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose);
276    }
277
278    /**
279     * Trigger a reconnection if the iface is disconnected.
280     *
281     * @return true if request is sent successfully, false otherwise.
282     */
283    public boolean reconnect() {
284        return mSupplicantStaIfaceHal.reconnect();
285    }
286
287    /**
288     * Trigger a reassociation even if the iface is currently connected.
289     *
290     * @return true if request is sent successfully, false otherwise.
291     */
292    public boolean reassociate() {
293        return mSupplicantStaIfaceHal.reassociate();
294    }
295
296    /**
297     * Trigger a disconnection from the currently connected network.
298     *
299     * @return true if request is sent successfully, false otherwise.
300     */
301    public boolean disconnect() {
302        return mSupplicantStaIfaceHal.disconnect();
303    }
304
305    /**
306     * Makes a callback to HIDL to getMacAddress from supplicant
307     *
308     * @return string containing the MAC address, or null on a failed call
309     */
310    public String getMacAddress() {
311        return mSupplicantStaIfaceHal.getMacAddress();
312    }
313
314    public static final int RX_FILTER_TYPE_V4_MULTICAST = 0;
315    public static final int RX_FILTER_TYPE_V6_MULTICAST = 1;
316    /**
317     * Start filtering out Multicast V4 packets
318     * @return {@code true} if the operation succeeded, {@code false} otherwise
319     *
320     * Multicast filtering rules work as follows:
321     *
322     * The driver can filter multicast (v4 and/or v6) and broadcast packets when in
323     * a power optimized mode (typically when screen goes off).
324     *
325     * In order to prevent the driver from filtering the multicast/broadcast packets, we have to
326     * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
327     *
328     * DRIVER RXFILTER-ADD Num
329     *   where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
330     *
331     * and DRIVER RXFILTER-START
332     * In order to stop the usage of these rules, we do
333     *
334     * DRIVER RXFILTER-STOP
335     * DRIVER RXFILTER-REMOVE Num
336     *   where Num is as described for RXFILTER-ADD
337     *
338     * The  SETSUSPENDOPT driver command overrides the filtering rules
339     */
340    public boolean startFilteringMulticastV4Packets() {
341        return mSupplicantStaIfaceHal.stopRxFilter()
342                && mSupplicantStaIfaceHal.removeRxFilter(
343                RX_FILTER_TYPE_V4_MULTICAST)
344                && mSupplicantStaIfaceHal.startRxFilter();
345    }
346
347    /**
348     * Stop filtering out Multicast V4 packets.
349     * @return {@code true} if the operation succeeded, {@code false} otherwise
350     */
351    public boolean stopFilteringMulticastV4Packets() {
352        return mSupplicantStaIfaceHal.stopRxFilter()
353                && mSupplicantStaIfaceHal.addRxFilter(
354                RX_FILTER_TYPE_V4_MULTICAST)
355                && mSupplicantStaIfaceHal.startRxFilter();
356    }
357
358    /**
359     * Start filtering out Multicast V6 packets
360     * @return {@code true} if the operation succeeded, {@code false} otherwise
361     */
362    public boolean startFilteringMulticastV6Packets() {
363        return mSupplicantStaIfaceHal.stopRxFilter()
364                && mSupplicantStaIfaceHal.removeRxFilter(
365                RX_FILTER_TYPE_V6_MULTICAST)
366                && mSupplicantStaIfaceHal.startRxFilter();
367    }
368
369    /**
370     * Stop filtering out Multicast V6 packets.
371     * @return {@code true} if the operation succeeded, {@code false} otherwise
372     */
373    public boolean stopFilteringMulticastV6Packets() {
374        return mSupplicantStaIfaceHal.stopRxFilter()
375                && mSupplicantStaIfaceHal.addRxFilter(
376                RX_FILTER_TYPE_V6_MULTICAST)
377                && mSupplicantStaIfaceHal.startRxFilter();
378    }
379
380    public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED  = 0;
381    public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
382    public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE    = 2;
383    /**
384      * Sets the bluetooth coexistence mode.
385      *
386      * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
387      *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
388      *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
389      * @return Whether the mode was successfully set.
390      */
391    public boolean setBluetoothCoexistenceMode(int mode) {
392        return mSupplicantStaIfaceHal.setBtCoexistenceMode(mode);
393    }
394
395    /**
396     * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
397     * some of the low-level scan parameters used by the driver are changed to
398     * reduce interference with A2DP streaming.
399     *
400     * @param setCoexScanMode whether to enable or disable this mode
401     * @return {@code true} if the command succeeded, {@code false} otherwise.
402     */
403    public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) {
404        return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled(setCoexScanMode);
405    }
406
407    /**
408     * Enable or disable suspend mode optimizations.
409     *
410     * @param enabled true to enable, false otherwise.
411     * @return true if request is sent successfully, false otherwise.
412     */
413    public boolean setSuspendOptimizations(boolean enabled) {
414        return mSupplicantStaIfaceHal.setSuspendModeEnabled(enabled);
415    }
416
417    /**
418     * Set country code.
419     *
420     * @param countryCode 2 byte ASCII string. For ex: US, CA.
421     * @return true if request is sent successfully, false otherwise.
422     */
423    public boolean setCountryCode(String countryCode) {
424        return mSupplicantStaIfaceHal.setCountryCode(countryCode);
425    }
426
427    /**
428     * Initiate TDLS discover and setup or teardown with the specified peer.
429     *
430     * @param macAddr MAC Address of the peer.
431     * @param enable true to start discovery and setup, false to teardown.
432     */
433    public void startTdls(String macAddr, boolean enable) {
434        if (enable) {
435            mSupplicantStaIfaceHal.initiateTdlsDiscover(macAddr);
436            mSupplicantStaIfaceHal.initiateTdlsSetup(macAddr);
437        } else {
438            mSupplicantStaIfaceHal.initiateTdlsTeardown(macAddr);
439        }
440    }
441
442    /**
443     * Start WPS pin display operation with the specified peer.
444     *
445     * @param bssid BSSID of the peer.
446     * @return true if request is sent successfully, false otherwise.
447     */
448    public boolean startWpsPbc(String bssid) {
449        return mSupplicantStaIfaceHal.startWpsPbc(bssid);
450    }
451
452    /**
453     * Start WPS pin keypad operation with the specified pin.
454     *
455     * @param pin Pin to be used.
456     * @return true if request is sent successfully, false otherwise.
457     */
458    public boolean startWpsPinKeypad(String pin) {
459        return mSupplicantStaIfaceHal.startWpsPinKeypad(pin);
460    }
461
462    /**
463     * Start WPS pin display operation with the specified peer.
464     *
465     * @param bssid BSSID of the peer.
466     * @return new pin generated on success, null otherwise.
467     */
468    public String startWpsPinDisplay(String bssid) {
469        return mSupplicantStaIfaceHal.startWpsPinDisplay(bssid);
470    }
471
472    /**
473     * Sets whether to use external sim for SIM/USIM processing.
474     *
475     * @param external true to enable, false otherwise.
476     * @return true if request is sent successfully, false otherwise.
477     */
478    public boolean setExternalSim(boolean external) {
479        return mSupplicantStaIfaceHal.setExternalSim(external);
480    }
481
482    /**
483     * Sim auth response types.
484     */
485    public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH";
486    public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH";
487    public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS";
488
489    /**
490     * Send the sim auth response for the currently configured network.
491     *
492     * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|.
493     * @param response Response params.
494     * @return true if succeeds, false otherwise.
495     */
496    public boolean simAuthResponse(int id, String type, String response) {
497        if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) {
498            return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse(response);
499        } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) {
500            return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse(response);
501        } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) {
502            return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse(response);
503        } else {
504            return false;
505        }
506    }
507
508    /**
509     * Send the eap sim gsm auth failure for the currently configured network.
510     *
511     * @return true if succeeds, false otherwise.
512     */
513    public boolean simAuthFailedResponse(int id) {
514        return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure();
515    }
516
517    /**
518     * Send the eap sim umts auth failure for the currently configured network.
519     *
520     * @return true if succeeds, false otherwise.
521     */
522    public boolean umtsAuthFailedResponse(int id) {
523        return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure();
524    }
525
526    /**
527     * Send the eap identity response for the currently configured network.
528     *
529     * @param response String to send.
530     * @return true if succeeds, false otherwise.
531     */
532    public boolean simIdentityResponse(int id, String response) {
533        return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(response);
534    }
535
536    /**
537     * This get anonymous identity from supplicant and returns it as a string.
538     *
539     * @return anonymous identity string if succeeds, null otherwise.
540     */
541    public String getEapAnonymousIdentity() {
542        return mSupplicantStaIfaceHal.getCurrentNetworkEapAnonymousIdentity();
543    }
544
545    /**
546     * Start WPS pin registrar operation with the specified peer and pin.
547     *
548     * @param bssid BSSID of the peer.
549     * @param pin Pin to be used.
550     * @return true if request is sent successfully, false otherwise.
551     */
552    public boolean startWpsRegistrar(String bssid, String pin) {
553        return mSupplicantStaIfaceHal.startWpsRegistrar(bssid, pin);
554    }
555
556    /**
557     * Cancels any ongoing WPS requests.
558     *
559     * @return true if request is sent successfully, false otherwise.
560     */
561    public boolean cancelWps() {
562        return mSupplicantStaIfaceHal.cancelWps();
563    }
564
565    /**
566     * Set WPS device name.
567     *
568     * @param name String to be set.
569     * @return true if request is sent successfully, false otherwise.
570     */
571    public boolean setDeviceName(String name) {
572        return mSupplicantStaIfaceHal.setWpsDeviceName(name);
573    }
574
575    /**
576     * Set WPS device type.
577     *
578     * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
579     * @return true if request is sent successfully, false otherwise.
580     */
581    public boolean setDeviceType(String type) {
582        return mSupplicantStaIfaceHal.setWpsDeviceType(type);
583    }
584
585    /**
586     * Set WPS config methods
587     *
588     * @param cfg List of config methods.
589     * @return true if request is sent successfully, false otherwise.
590     */
591    public boolean setConfigMethods(String cfg) {
592        return mSupplicantStaIfaceHal.setWpsConfigMethods(cfg);
593    }
594
595    /**
596     * Set WPS manufacturer.
597     *
598     * @param value String to be set.
599     * @return true if request is sent successfully, false otherwise.
600     */
601    public boolean setManufacturer(String value) {
602        return mSupplicantStaIfaceHal.setWpsManufacturer(value);
603    }
604
605    /**
606     * Set WPS model name.
607     *
608     * @param value String to be set.
609     * @return true if request is sent successfully, false otherwise.
610     */
611    public boolean setModelName(String value) {
612        return mSupplicantStaIfaceHal.setWpsModelName(value);
613    }
614
615    /**
616     * Set WPS model number.
617     *
618     * @param value String to be set.
619     * @return true if request is sent successfully, false otherwise.
620     */
621    public boolean setModelNumber(String value) {
622        return mSupplicantStaIfaceHal.setWpsModelNumber(value);
623    }
624
625    /**
626     * Set WPS serial number.
627     *
628     * @param value String to be set.
629     * @return true if request is sent successfully, false otherwise.
630     */
631    public boolean setSerialNumber(String value) {
632        return mSupplicantStaIfaceHal.setWpsSerialNumber(value);
633    }
634
635    /**
636     * Enable or disable power save mode.
637     *
638     * @param enabled true to enable, false to disable.
639     */
640    public void setPowerSave(boolean enabled) {
641        mSupplicantStaIfaceHal.setPowerSave(enabled);
642    }
643
644    /**
645     * Set concurrency priority between P2P & STA operations.
646     *
647     * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations,
648     *                            false otherwise.
649     * @return true if request is sent successfully, false otherwise.
650     */
651    public boolean setConcurrencyPriority(boolean isStaHigherPriority) {
652        return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority);
653    }
654
655    /**
656     * Enable/Disable auto reconnect functionality in wpa_supplicant.
657     *
658     * @param enable true to enable auto reconnecting, false to disable.
659     * @return true if request is sent successfully, false otherwise.
660     */
661    public boolean enableStaAutoReconnect(boolean enable) {
662        return mSupplicantStaIfaceHal.enableAutoReconnect(enable);
663    }
664
665    /**
666     * Migrate all the configured networks from wpa_supplicant.
667     *
668     * @param configs       Map of configuration key to configuration objects corresponding to all
669     *                      the networks.
670     * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf
671     * @return Max priority of all the configs.
672     */
673    public boolean migrateNetworksFromSupplicant(Map<String, WifiConfiguration> configs,
674                                                 SparseArray<Map<String, String>> networkExtras) {
675        return mSupplicantStaIfaceHal.loadNetworks(configs, networkExtras);
676    }
677
678    /**
679     * Add the provided network configuration to wpa_supplicant and initiate connection to it.
680     * This method does the following:
681     * 1. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect).
682     * 2. Add a new network to wpa_supplicant.
683     * 3. Save the provided configuration to wpa_supplicant.
684     * 4. Select the new network in wpa_supplicant.
685     * 5. Triggers reconnect command to wpa_supplicant.
686     *
687     * @param configuration WifiConfiguration parameters for the provided network.
688     * @return {@code true} if it succeeds, {@code false} otherwise
689     */
690    public boolean connectToNetwork(WifiConfiguration configuration) {
691        return mSupplicantStaIfaceHal.connectToNetwork(configuration);
692    }
693
694    /**
695     * Initiates roaming to the already configured network in wpa_supplicant. If the network
696     * configuration provided does not match the already configured network, then this triggers
697     * a new connection attempt (instead of roam).
698     * 1. First check if we're attempting to connect to the same network as we currently have
699     * configured.
700     * 2. Set the new bssid for the network in wpa_supplicant.
701     * 3. Triggers reassociate command to wpa_supplicant.
702     *
703     * @param configuration WifiConfiguration parameters for the provided network.
704     * @return {@code true} if it succeeds, {@code false} otherwise
705     */
706    public boolean roamToNetwork(WifiConfiguration configuration) {
707        return mSupplicantStaIfaceHal.roamToNetwork(configuration);
708    }
709
710    /**
711     * Get the framework network ID corresponding to the provided supplicant network ID for the
712     * network configured in wpa_supplicant.
713     *
714     * @param supplicantNetworkId network ID in wpa_supplicant for the network.
715     * @return Corresponding framework network ID if found, -1 if network not found.
716     */
717    public int getFrameworkNetworkId(int supplicantNetworkId) {
718        return supplicantNetworkId;
719    }
720
721    /**
722     * Remove all the networks.
723     *
724     * @return {@code true} if it succeeds, {@code false} otherwise
725     */
726    public boolean removeAllNetworks() {
727        return mSupplicantStaIfaceHal.removeAllNetworks();
728    }
729
730    /**
731     * Set the BSSID for the currently configured network in wpa_supplicant.
732     *
733     * @return true if successful, false otherwise.
734     */
735    public boolean setConfiguredNetworkBSSID(String bssid) {
736        return mSupplicantStaIfaceHal.setCurrentNetworkBssid(bssid);
737    }
738
739    /**
740     * Initiate ANQP query.
741     *
742     * @param bssid BSSID of the AP to be queried
743     * @param anqpIds Set of anqp IDs.
744     * @param hs20Subtypes Set of HS20 subtypes.
745     * @return true on success, false otherwise.
746     */
747    public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) {
748        if (bssid == null || ((anqpIds == null || anqpIds.isEmpty())
749                && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) {
750            Log.e(mTAG, "Invalid arguments for ANQP request.");
751            return false;
752        }
753        ArrayList<Short> anqpIdList = new ArrayList<>();
754        for (Integer anqpId : anqpIds) {
755            anqpIdList.add(anqpId.shortValue());
756        }
757        ArrayList<Integer> hs20SubtypeList = new ArrayList<>();
758        hs20SubtypeList.addAll(hs20Subtypes);
759        return mSupplicantStaIfaceHal.initiateAnqpQuery(bssid, anqpIdList, hs20SubtypeList);
760    }
761
762    /**
763     * Request a passpoint icon file |filename| from the specified AP |bssid|.
764     * @param bssid BSSID of the AP
765     * @param fileName name of the icon file
766     * @return true if request is sent successfully, false otherwise
767     */
768    public boolean requestIcon(String  bssid, String fileName) {
769        if (bssid == null || fileName == null) {
770            Log.e(mTAG, "Invalid arguments for Icon request.");
771            return false;
772        }
773        return mSupplicantStaIfaceHal.initiateHs20IconQuery(bssid, fileName);
774    }
775
776    /**
777     * Get the currently configured network's WPS NFC token.
778     *
779     * @return Hex string corresponding to the WPS NFC token.
780     */
781    public String getCurrentNetworkWpsNfcConfigurationToken() {
782        return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken();
783    }
784    /********************************************************
785     * Vendor HAL operations
786     ********************************************************/
787    /**
788     * Callback to notify vendor HAL death.
789     */
790    public interface VendorHalDeathEventHandler {
791        /**
792         * Invoked when the vendor HAL dies.
793         */
794        void onDeath();
795    }
796
797    /**
798     * Initializes the vendor HAL. This is just used to initialize the {@link HalDeviceManager}.
799     */
800    public boolean initializeVendorHal(VendorHalDeathEventHandler handler) {
801        return mWifiVendorHal.initialize(handler);
802    }
803
804    /**
805     * Bring up the Vendor HAL and configure for STA mode or AP mode, if vendor HAL is supported.
806     *
807     * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
808     * @return false if the HAL start fails, true if successful or if vendor HAL not supported.
809     */
810    private boolean startHalIfNecessary(boolean isStaMode) {
811        if (!mWifiVendorHal.isVendorHalSupported()) {
812            Log.i(mTAG, "Vendor HAL not supported, Ignore start...");
813            return true;
814        }
815        return mWifiVendorHal.startVendorHal(isStaMode);
816    }
817
818    /**
819     * Stops the HAL, if vendor HAL is supported.
820     */
821    private void stopHalIfNecessary() {
822        if (!mWifiVendorHal.isVendorHalSupported()) {
823            Log.i(mTAG, "Vendor HAL not supported, Ignore stop...");
824            return;
825        }
826        mWifiVendorHal.stopVendorHal();
827    }
828
829    /**
830     * Tests whether the HAL is running or not
831     */
832    public boolean isHalStarted() {
833        return mWifiVendorHal.isHalStarted();
834    }
835
836    // TODO: Change variable names to camel style.
837    public static class ScanCapabilities {
838        public int  max_scan_cache_size;
839        public int  max_scan_buckets;
840        public int  max_ap_cache_per_scan;
841        public int  max_rssi_sample_size;
842        public int  max_scan_reporting_threshold;
843    }
844
845    /**
846     * Gets the scan capabilities
847     *
848     * @param capabilities object to be filled in
849     * @return true for success. false for failure
850     */
851    public boolean getBgScanCapabilities(ScanCapabilities capabilities) {
852        return mWifiVendorHal.getBgScanCapabilities(capabilities);
853    }
854
855    public static class ChannelSettings {
856        public int frequency;
857        public int dwell_time_ms;
858        public boolean passive;
859    }
860
861    public static class BucketSettings {
862        public int bucket;
863        public int band;
864        public int period_ms;
865        public int max_period_ms;
866        public int step_count;
867        public int report_events;
868        public int num_channels;
869        public ChannelSettings[] channels;
870    }
871
872    /**
873     * Network parameters for hidden networks to be scanned for.
874     */
875    public static class HiddenNetwork {
876        public String ssid;
877
878        @Override
879        public boolean equals(Object otherObj) {
880            if (this == otherObj) {
881                return true;
882            } else if (otherObj == null || getClass() != otherObj.getClass()) {
883                return false;
884            }
885            HiddenNetwork other = (HiddenNetwork) otherObj;
886            return Objects.equals(ssid, other.ssid);
887        }
888
889        @Override
890        public int hashCode() {
891            return (ssid == null ? 0 : ssid.hashCode());
892        }
893    }
894
895    public static class ScanSettings {
896        public int base_period_ms;
897        public int max_ap_per_scan;
898        public int report_threshold_percent;
899        public int report_threshold_num_scans;
900        public int num_buckets;
901        /* Not used for bg scans. Only works for single scans. */
902        public HiddenNetwork[] hiddenNetworks;
903        public BucketSettings[] buckets;
904    }
905
906    /**
907     * Network parameters to start PNO scan.
908     */
909    public static class PnoNetwork {
910        public String ssid;
911        public byte flags;
912        public byte auth_bit_field;
913
914        @Override
915        public boolean equals(Object otherObj) {
916            if (this == otherObj) {
917                return true;
918            } else if (otherObj == null || getClass() != otherObj.getClass()) {
919                return false;
920            }
921            PnoNetwork other = (PnoNetwork) otherObj;
922            return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags)
923                    && (auth_bit_field == other.auth_bit_field));
924        }
925
926        @Override
927        public int hashCode() {
928            int result = (ssid == null ? 0 : ssid.hashCode());
929            result ^= ((int) flags * 31) + ((int) auth_bit_field << 8);
930            return result;
931        }
932    }
933
934    /**
935     * Parameters to start PNO scan. This holds the list of networks which are going to used for
936     * PNO scan.
937     */
938    public static class PnoSettings {
939        public int min5GHzRssi;
940        public int min24GHzRssi;
941        public int initialScoreMax;
942        public int currentConnectionBonus;
943        public int sameNetworkBonus;
944        public int secureBonus;
945        public int band5GHzBonus;
946        public int periodInMs;
947        public boolean isConnected;
948        public PnoNetwork[] networkList;
949    }
950
951    public static interface ScanEventHandler {
952        /**
953         * Called for each AP as it is found with the entire contents of the beacon/probe response.
954         * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified.
955         */
956        void onFullScanResult(ScanResult fullScanResult, int bucketsScanned);
957        /**
958         * Callback on an event during a gscan scan.
959         * See WifiNative.WIFI_SCAN_* for possible values.
960         */
961        void onScanStatus(int event);
962        /**
963         * Called with the current cached scan results when gscan is paused.
964         */
965        void onScanPaused(WifiScanner.ScanData[] data);
966        /**
967         * Called with the current cached scan results when gscan is resumed.
968         */
969        void onScanRestarted();
970    }
971
972    /**
973     * Handler to notify the occurrence of various events during PNO scan.
974     */
975    public interface PnoEventHandler {
976        /**
977         * Callback to notify when one of the shortlisted networks is found during PNO scan.
978         * @param results List of Scan results received.
979         */
980        void onPnoNetworkFound(ScanResult[] results);
981
982        /**
983         * Callback to notify when the PNO scan schedule fails.
984         */
985        void onPnoScanFailed();
986    }
987
988    public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
989    public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
990    public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
991    public static final int WIFI_SCAN_FAILED = 3;
992
993    /**
994     * Starts a background scan.
995     * Any ongoing scan will be stopped first
996     *
997     * @param settings     to control the scan
998     * @param eventHandler to call with the results
999     * @return true for success
1000     */
1001    public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) {
1002        return mWifiVendorHal.startBgScan(settings, eventHandler);
1003    }
1004
1005    /**
1006     * Stops any ongoing backgound scan
1007     */
1008    public void stopBgScan() {
1009        mWifiVendorHal.stopBgScan();
1010    }
1011
1012    /**
1013     * Pauses an ongoing backgound scan
1014     */
1015    public void pauseBgScan() {
1016        mWifiVendorHal.pauseBgScan();
1017    }
1018
1019    /**
1020     * Restarts a paused scan
1021     */
1022    public void restartBgScan() {
1023        mWifiVendorHal.restartBgScan();
1024    }
1025
1026    /**
1027     * Gets the latest scan results received.
1028     */
1029    public WifiScanner.ScanData[] getBgScanResults() {
1030        return mWifiVendorHal.getBgScanResults();
1031    }
1032
1033    public WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
1034        return mWifiVendorHal.getWifiLinkLayerStats();
1035    }
1036
1037    /**
1038     * Get the supported features
1039     *
1040     * @return bitmask defined by WifiManager.WIFI_FEATURE_*
1041     */
1042    public int getSupportedFeatureSet() {
1043        return mWifiVendorHal.getSupportedFeatureSet();
1044    }
1045
1046    public static interface RttEventHandler {
1047        void onRttResults(RttManager.RttResult[] result);
1048    }
1049
1050    /**
1051     * Starts a new rtt request
1052     *
1053     * @param params RTT request params. Refer to {@link RttManager#RttParams}.
1054     * @param handler Callback to be invoked to notify any results.
1055     * @return true if the request was successful, false otherwise.
1056     */
1057    public boolean requestRtt(
1058            RttManager.RttParams[] params, RttEventHandler handler) {
1059        return mWifiVendorHal.requestRtt(params, handler);
1060    }
1061
1062    /**
1063     * Cancels an outstanding rtt request
1064     *
1065     * @param params RTT request params. Refer to {@link RttManager#RttParams}
1066     * @return true if there was an outstanding request and it was successfully cancelled
1067     */
1068    public boolean cancelRtt(RttManager.RttParams[] params) {
1069        return mWifiVendorHal.cancelRtt(params);
1070    }
1071
1072    /**
1073     * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder
1074     * role is successfully enabled, {@code null} otherwise.
1075     *
1076     * @param timeoutSeconds timeout to use for the responder.
1077     */
1078    @Nullable
1079    public ResponderConfig enableRttResponder(int timeoutSeconds) {
1080        return mWifiVendorHal.enableRttResponder(timeoutSeconds);
1081    }
1082
1083    /**
1084     * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled,
1085     * {@code false} otherwise.
1086     */
1087    public boolean disableRttResponder() {
1088        return mWifiVendorHal.disableRttResponder();
1089    }
1090
1091    /**
1092     * Set the MAC OUI during scanning.
1093     * An OUI {Organizationally Unique Identifier} is a 24-bit number that
1094     * uniquely identifies a vendor or manufacturer.
1095     *
1096     * @param oui OUI to set.
1097     * @return true for success
1098     */
1099    public boolean setScanningMacOui(byte[] oui) {
1100        return mWifiVendorHal.setScanningMacOui(oui);
1101    }
1102
1103    /**
1104     * Query the list of valid frequencies for the provided band.
1105     * The result depends on the on the country code that has been set.
1106     *
1107     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
1108     * @return frequencies vector of valid frequencies (MHz), or null for error.
1109     * @throws IllegalArgumentException if band is not recognized.
1110     */
1111    public int [] getChannelsForBand(int band) {
1112        return mWifiVendorHal.getChannelsForBand(band);
1113    }
1114
1115    /**
1116     * Indicates whether getChannelsForBand is supported.
1117     *
1118     * @return true if it is.
1119     */
1120    public boolean isGetChannelsForBandSupported() {
1121        return mWifiVendorHal.isGetChannelsForBandSupported();
1122    }
1123
1124    /**
1125     * RTT (Round Trip Time) measurement capabilities of the device.
1126     */
1127    public RttManager.RttCapabilities getRttCapabilities() {
1128        return mWifiVendorHal.getRttCapabilities();
1129    }
1130
1131    /**
1132     * Get the APF (Android Packet Filter) capabilities of the device
1133     */
1134    public ApfCapabilities getApfCapabilities() {
1135        return mWifiVendorHal.getApfCapabilities();
1136    }
1137
1138    /**
1139     * Installs an APF program on this iface, replacing any existing program.
1140     *
1141     * @param filter is the android packet filter program
1142     * @return true for success
1143     */
1144    public boolean installPacketFilter(byte[] filter) {
1145        return mWifiVendorHal.installPacketFilter(filter);
1146    }
1147
1148    /**
1149     * Set country code for this AP iface.
1150     *
1151     * @param countryCode - two-letter country code (as ISO 3166)
1152     * @return true for success
1153     */
1154    public boolean setCountryCodeHal(String countryCode) {
1155        return mWifiVendorHal.setCountryCodeHal(countryCode);
1156    }
1157
1158    //---------------------------------------------------------------------------------
1159    /* Wifi Logger commands/events */
1160    public static interface WifiLoggerEventHandler {
1161        void onRingBufferData(RingBufferStatus status, byte[] buffer);
1162        void onWifiAlert(int errorCode, byte[] buffer);
1163    }
1164
1165    /**
1166     * Registers the logger callback and enables alerts.
1167     * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked.
1168     *
1169     * @param handler Callback to be invoked.
1170     * @return true on success, false otherwise.
1171     */
1172    public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
1173        return mWifiVendorHal.setLoggingEventHandler(handler);
1174    }
1175
1176    /**
1177     * Control debug data collection
1178     *
1179     * @param verboseLevel 0 to 3, inclusive. 0 stops logging.
1180     * @param flags        Ignored.
1181     * @param maxInterval  Maximum interval between reports; ignore if 0.
1182     * @param minDataSize  Minimum data size in buffer for report; ignore if 0.
1183     * @param ringName     Name of the ring for which data collection is to start.
1184     * @return true for success, false otherwise.
1185     */
1186    public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
1187            int minDataSize, String ringName){
1188        return mWifiVendorHal.startLoggingRingBuffer(
1189                verboseLevel, flags, maxInterval, minDataSize, ringName);
1190    }
1191
1192    /**
1193     * Logger features exposed.
1194     * This is a no-op now, will always return -1.
1195     *
1196     * @return true on success, false otherwise.
1197     */
1198    public int getSupportedLoggerFeatureSet() {
1199        return mWifiVendorHal.getSupportedLoggerFeatureSet();
1200    }
1201
1202    /**
1203     * Stops all logging and resets the logger callback.
1204     * This stops both the alerts and ring buffer data collection.
1205     * @return true on success, false otherwise.
1206     */
1207    public boolean resetLogHandler() {
1208        return mWifiVendorHal.resetLogHandler();
1209    }
1210
1211    /**
1212     * Vendor-provided wifi driver version string
1213     *
1214     * @return String returned from the HAL.
1215     */
1216    public String getDriverVersion() {
1217        return mWifiVendorHal.getDriverVersion();
1218    }
1219
1220    /**
1221     * Vendor-provided wifi firmware version string
1222     *
1223     * @return String returned from the HAL.
1224     */
1225    public String getFirmwareVersion() {
1226        return mWifiVendorHal.getFirmwareVersion();
1227    }
1228
1229    public static class RingBufferStatus{
1230        String name;
1231        int flag;
1232        int ringBufferId;
1233        int ringBufferByteSize;
1234        int verboseLevel;
1235        int writtenBytes;
1236        int readBytes;
1237        int writtenRecords;
1238
1239        // Bit masks for interpreting |flag|
1240        public static final int HAS_BINARY_ENTRIES = (1 << 0);
1241        public static final int HAS_ASCII_ENTRIES = (1 << 1);
1242        public static final int HAS_PER_PACKET_ENTRIES = (1 << 2);
1243
1244        @Override
1245        public String toString() {
1246            return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
1247                    " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
1248                    " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
1249                    " writtenRecords: " + writtenRecords;
1250        }
1251    }
1252
1253    /**
1254     * API to get the status of all ring buffers supported by driver
1255     */
1256    public RingBufferStatus[] getRingBufferStatus() {
1257        return mWifiVendorHal.getRingBufferStatus();
1258    }
1259
1260    /**
1261     * Indicates to driver that all the data has to be uploaded urgently
1262     *
1263     * @param ringName Name of the ring buffer requested.
1264     * @return true on success, false otherwise.
1265     */
1266    public boolean getRingBufferData(String ringName) {
1267        return mWifiVendorHal.getRingBufferData(ringName);
1268    }
1269
1270    /**
1271     * Request vendor debug info from the firmware
1272     *
1273     * @return Raw data obtained from the HAL.
1274     */
1275    public byte[] getFwMemoryDump() {
1276        return mWifiVendorHal.getFwMemoryDump();
1277    }
1278
1279    /**
1280     * Request vendor debug info from the driver
1281     *
1282     * @return Raw data obtained from the HAL.
1283     */
1284    public byte[] getDriverStateDump() {
1285        return mWifiVendorHal.getDriverStateDump();
1286    }
1287
1288    //---------------------------------------------------------------------------------
1289    /* Packet fate API */
1290
1291    @Immutable
1292    abstract static class FateReport {
1293        final static int USEC_PER_MSEC = 1000;
1294        // The driver timestamp is a 32-bit counter, in microseconds. This field holds the
1295        // maximal value of a driver timestamp in milliseconds.
1296        final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000);
1297        final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
1298
1299        final byte mFate;
1300        final long mDriverTimestampUSec;
1301        final byte mFrameType;
1302        final byte[] mFrameBytes;
1303        final long mEstimatedWallclockMSec;
1304
1305        FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1306            mFate = fate;
1307            mDriverTimestampUSec = driverTimestampUSec;
1308            mEstimatedWallclockMSec =
1309                    convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec);
1310            mFrameType = frameType;
1311            mFrameBytes = frameBytes;
1312        }
1313
1314        public String toTableRowString() {
1315            StringWriter sw = new StringWriter();
1316            PrintWriter pw = new PrintWriter(sw);
1317            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1318            dateFormatter.setTimeZone(TimeZone.getDefault());
1319            pw.format("%-15s  %12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1320                    mDriverTimestampUSec,
1321                    dateFormatter.format(new Date(mEstimatedWallclockMSec)),
1322                    directionToString(), fateToString(), parser.mMostSpecificProtocolString,
1323                    parser.mTypeString, parser.mResultString);
1324            return sw.toString();
1325        }
1326
1327        public String toVerboseStringWithPiiAllowed() {
1328            StringWriter sw = new StringWriter();
1329            PrintWriter pw = new PrintWriter(sw);
1330            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1331            pw.format("Frame direction: %s\n", directionToString());
1332            pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
1333            pw.format("Frame fate: %s\n", fateToString());
1334            pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
1335            pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
1336            pw.format("Frame protocol type: %s\n", parser.mTypeString);
1337            pw.format("Frame length: %d\n", mFrameBytes.length);
1338            pw.append("Frame bytes");
1339            pw.append(HexDump.dumpHexString(mFrameBytes));  // potentially contains PII
1340            pw.append("\n");
1341            return sw.toString();
1342        }
1343
1344        /* Returns a header to match the output of toTableRowString(). */
1345        public static String getTableHeader() {
1346            StringWriter sw = new StringWriter();
1347            PrintWriter pw = new PrintWriter(sw);
1348            pw.format("\n%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1349                    "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result");
1350            pw.format("%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1351                    "---------", "--------", "---------", "----", "--------", "----", "------");
1352            return sw.toString();
1353        }
1354
1355        protected abstract String directionToString();
1356
1357        protected abstract String fateToString();
1358
1359        private static String frameTypeToString(byte frameType) {
1360            switch (frameType) {
1361                case WifiLoggerHal.FRAME_TYPE_UNKNOWN:
1362                    return "unknown";
1363                case WifiLoggerHal.FRAME_TYPE_ETHERNET_II:
1364                    return "data";
1365                case WifiLoggerHal.FRAME_TYPE_80211_MGMT:
1366                    return "802.11 management";
1367                default:
1368                    return Byte.toString(frameType);
1369            }
1370        }
1371
1372        /**
1373         * Converts a driver timestamp to a wallclock time, based on the current
1374         * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of
1375         * microseconds, with the same base as BOOTTIME.
1376         */
1377        private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) {
1378            final long wallclockMillisNow = System.currentTimeMillis();
1379            final long boottimeMillisNow = SystemClock.elapsedRealtime();
1380            final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC;
1381
1382            long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC;
1383            if (boottimeTimestampMillis < driverTimestampMillis) {
1384                // The 32-bit microsecond count has wrapped between the time that the driver
1385                // recorded the packet, and the call to this function. Adjust the BOOTTIME
1386                // timestamp, to compensate.
1387                //
1388                // Note that overflow is not a concern here, since the result is less than
1389                // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above,
1390                // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since
1391                // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit
1392                // within a long.
1393                boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC;
1394            }
1395
1396            final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis;
1397            return wallclockMillisNow - millisSincePacketTimestamp;
1398        }
1399    }
1400
1401    /**
1402     * Represents the fate information for one outbound packet.
1403     */
1404    @Immutable
1405    public static final class TxFateReport extends FateReport {
1406        TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1407            super(fate, driverTimestampUSec, frameType, frameBytes);
1408        }
1409
1410        @Override
1411        protected String directionToString() {
1412            return "TX";
1413        }
1414
1415        @Override
1416        protected String fateToString() {
1417            switch (mFate) {
1418                case WifiLoggerHal.TX_PKT_FATE_ACKED:
1419                    return "acked";
1420                case WifiLoggerHal.TX_PKT_FATE_SENT:
1421                    return "sent";
1422                case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED:
1423                    return "firmware queued";
1424                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID:
1425                    return "firmware dropped (invalid frame)";
1426                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS:
1427                    return "firmware dropped (no bufs)";
1428                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER:
1429                    return "firmware dropped (other)";
1430                case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED:
1431                    return "driver queued";
1432                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID:
1433                    return "driver dropped (invalid frame)";
1434                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS:
1435                    return "driver dropped (no bufs)";
1436                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER:
1437                    return "driver dropped (other)";
1438                default:
1439                    return Byte.toString(mFate);
1440            }
1441        }
1442    }
1443
1444    /**
1445     * Represents the fate information for one inbound packet.
1446     */
1447    @Immutable
1448    public static final class RxFateReport extends FateReport {
1449        RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1450            super(fate, driverTimestampUSec, frameType, frameBytes);
1451        }
1452
1453        @Override
1454        protected String directionToString() {
1455            return "RX";
1456        }
1457
1458        @Override
1459        protected String fateToString() {
1460            switch (mFate) {
1461                case WifiLoggerHal.RX_PKT_FATE_SUCCESS:
1462                    return "success";
1463                case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED:
1464                    return "firmware queued";
1465                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER:
1466                    return "firmware dropped (filter)";
1467                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID:
1468                    return "firmware dropped (invalid frame)";
1469                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS:
1470                    return "firmware dropped (no bufs)";
1471                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER:
1472                    return "firmware dropped (other)";
1473                case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED:
1474                    return "driver queued";
1475                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER:
1476                    return "driver dropped (filter)";
1477                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID:
1478                    return "driver dropped (invalid frame)";
1479                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS:
1480                    return "driver dropped (no bufs)";
1481                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER:
1482                    return "driver dropped (other)";
1483                default:
1484                    return Byte.toString(mFate);
1485            }
1486        }
1487    }
1488
1489    /**
1490     * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started.
1491     *
1492     * @return true for success, false otherwise.
1493     */
1494    public boolean startPktFateMonitoring() {
1495        return mWifiVendorHal.startPktFateMonitoring();
1496    }
1497
1498    /**
1499     * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started.
1500     *
1501     * @return true for success, false otherwise.
1502     */
1503    public boolean getTxPktFates(TxFateReport[] reportBufs) {
1504        return mWifiVendorHal.getTxPktFates(reportBufs);
1505    }
1506
1507    /**
1508     * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started.
1509     */
1510    public boolean getRxPktFates(RxFateReport[] reportBufs) {
1511        return mWifiVendorHal.getRxPktFates(reportBufs);
1512    }
1513
1514    /**
1515     * Set the PNO settings & the network list in HAL to start PNO.
1516     * @param settings PNO settings and network list.
1517     * @param eventHandler Handler to receive notifications back during PNO scan.
1518     * @return true if success, false otherwise
1519     */
1520    public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) {
1521        Log.e(mTAG, "setPnoList not supported");
1522        return false;
1523    }
1524
1525    /**
1526     * Reset the PNO settings in HAL to stop PNO.
1527     * @return true if success, false otherwise
1528     */
1529    public boolean resetPnoList() {
1530        Log.e(mTAG, "resetPnoList not supported");
1531        return false;
1532    }
1533
1534    /**
1535     * Start sending the specified keep alive packets periodically.
1536     *
1537     * @param slot Integer used to identify each request.
1538     * @param keepAlivePacket Raw packet contents to send.
1539     * @param period Period to use for sending these packets.
1540     * @return 0 for success, -1 for error
1541     */
1542    public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket,
1543                                           int period) {
1544        String[] macAddrStr = getMacAddress().split(":");
1545        byte[] srcMac = new byte[6];
1546        for (int i = 0; i < 6; i++) {
1547            Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
1548            srcMac[i] = hexVal.byteValue();
1549        }
1550        return mWifiVendorHal.startSendingOffloadedPacket(
1551                slot, srcMac, keepAlivePacket, period);
1552    }
1553
1554    /**
1555     * Stop sending the specified keep alive packets.
1556     *
1557     * @param slot id - same as startSendingOffloadedPacket call.
1558     * @return 0 for success, -1 for error
1559     */
1560    public int stopSendingOffloadedPacket(int slot) {
1561        return mWifiVendorHal.stopSendingOffloadedPacket(slot);
1562    }
1563
1564    public static interface WifiRssiEventHandler {
1565        void onRssiThresholdBreached(byte curRssi);
1566    }
1567
1568    /**
1569     * Start RSSI monitoring on the currently connected access point.
1570     *
1571     * @param maxRssi          Maximum RSSI threshold.
1572     * @param minRssi          Minimum RSSI threshold.
1573     * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
1574     * @return 0 for success, -1 for failure
1575     */
1576    public int startRssiMonitoring(byte maxRssi, byte minRssi,
1577                                   WifiRssiEventHandler rssiEventHandler) {
1578        return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler);
1579    }
1580
1581    public int stopRssiMonitoring() {
1582        return mWifiVendorHal.stopRssiMonitoring();
1583    }
1584
1585    /**
1586     * Fetch the host wakeup reasons stats from wlan driver.
1587     *
1588     * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
1589     */
1590    public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
1591        return mWifiVendorHal.getWlanWakeReasonCount();
1592    }
1593
1594    /**
1595     * Enable/Disable Neighbour discovery offload functionality in the firmware.
1596     *
1597     * @param enabled true to enable, false to disable.
1598     * @return true for success, false otherwise.
1599     */
1600    public boolean configureNeighborDiscoveryOffload(boolean enabled) {
1601        return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled);
1602    }
1603
1604    // Firmware roaming control.
1605
1606    /**
1607     * Class to retrieve firmware roaming capability parameters.
1608     */
1609    public static class RoamingCapabilities {
1610        public int  maxBlacklistSize;
1611        public int  maxWhitelistSize;
1612    }
1613
1614    /**
1615     * Query the firmware roaming capabilities.
1616     * @return true for success, false otherwise.
1617     */
1618    public boolean getRoamingCapabilities(RoamingCapabilities capabilities) {
1619        return mWifiVendorHal.getRoamingCapabilities(capabilities);
1620    }
1621
1622    /**
1623     * Macros for controlling firmware roaming.
1624     */
1625    public static final int DISABLE_FIRMWARE_ROAMING = 0;
1626    public static final int ENABLE_FIRMWARE_ROAMING = 1;
1627
1628    /**
1629     * Enable/disable firmware roaming.
1630     *
1631     * @return error code returned from HAL.
1632     */
1633    public int enableFirmwareRoaming(int state) {
1634        return mWifiVendorHal.enableFirmwareRoaming(state);
1635    }
1636
1637    /**
1638     * Class for specifying the roaming configurations.
1639     */
1640    public static class RoamingConfig {
1641        public ArrayList<String> blacklistBssids;
1642        public ArrayList<String> whitelistSsids;
1643    }
1644
1645    /**
1646     * Set firmware roaming configurations.
1647     */
1648    public boolean configureRoaming(RoamingConfig config) {
1649        Log.d(mTAG, "configureRoaming ");
1650        return mWifiVendorHal.configureRoaming(config);
1651    }
1652
1653    /**
1654     * Reset firmware roaming configuration.
1655     */
1656    public boolean resetRoamingConfiguration() {
1657        // Pass in an empty RoamingConfig object which translates to zero size
1658        // blacklist and whitelist to reset the firmware roaming configuration.
1659        return mWifiVendorHal.configureRoaming(new RoamingConfig());
1660    }
1661
1662    /********************************************************
1663     * JNI operations
1664     ********************************************************/
1665    /* Register native functions */
1666    static {
1667        /* Native functions are defined in libwifi-service.so */
1668        System.loadLibrary("wifi-service");
1669        registerNatives();
1670    }
1671
1672    private static native int registerNatives();
1673    /* kernel logging support */
1674    private static native byte[] readKernelLogNative();
1675
1676    /**
1677     * Fetches the latest kernel logs.
1678     */
1679    public synchronized String readKernelLog() {
1680        byte[] bytes = readKernelLogNative();
1681        if (bytes != null) {
1682            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
1683            try {
1684                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
1685                return decoded.toString();
1686            } catch (CharacterCodingException cce) {
1687                return new String(bytes, StandardCharsets.ISO_8859_1);
1688            }
1689        } else {
1690            return "*** failed to read kernel log ***";
1691        }
1692    }
1693}
1694