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