WifiNative.java revision eb37292950237a906c4220acfc03406db2ef44cb
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        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     * Start WPS pin registrar operation with the specified peer and pin.
538     *
539     * @param bssid BSSID of the peer.
540     * @param pin Pin to be used.
541     * @return true if request is sent successfully, false otherwise.
542     */
543    public boolean startWpsRegistrar(String bssid, String pin) {
544        return mSupplicantStaIfaceHal.startWpsRegistrar(bssid, pin);
545    }
546
547    /**
548     * Cancels any ongoing WPS requests.
549     *
550     * @return true if request is sent successfully, false otherwise.
551     */
552    public boolean cancelWps() {
553        return mSupplicantStaIfaceHal.cancelWps();
554    }
555
556    /**
557     * Set WPS device name.
558     *
559     * @param name String to be set.
560     * @return true if request is sent successfully, false otherwise.
561     */
562    public boolean setDeviceName(String name) {
563        return mSupplicantStaIfaceHal.setWpsDeviceName(name);
564    }
565
566    /**
567     * Set WPS device type.
568     *
569     * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
570     * @return true if request is sent successfully, false otherwise.
571     */
572    public boolean setDeviceType(String type) {
573        return mSupplicantStaIfaceHal.setWpsDeviceType(type);
574    }
575
576    /**
577     * Set WPS config methods
578     *
579     * @param cfg List of config methods.
580     * @return true if request is sent successfully, false otherwise.
581     */
582    public boolean setConfigMethods(String cfg) {
583        return mSupplicantStaIfaceHal.setWpsConfigMethods(cfg);
584    }
585
586    /**
587     * Set WPS manufacturer.
588     *
589     * @param value String to be set.
590     * @return true if request is sent successfully, false otherwise.
591     */
592    public boolean setManufacturer(String value) {
593        return mSupplicantStaIfaceHal.setWpsManufacturer(value);
594    }
595
596    /**
597     * Set WPS model name.
598     *
599     * @param value String to be set.
600     * @return true if request is sent successfully, false otherwise.
601     */
602    public boolean setModelName(String value) {
603        return mSupplicantStaIfaceHal.setWpsModelName(value);
604    }
605
606    /**
607     * Set WPS model number.
608     *
609     * @param value String to be set.
610     * @return true if request is sent successfully, false otherwise.
611     */
612    public boolean setModelNumber(String value) {
613        return mSupplicantStaIfaceHal.setWpsModelNumber(value);
614    }
615
616    /**
617     * Set WPS serial number.
618     *
619     * @param value String to be set.
620     * @return true if request is sent successfully, false otherwise.
621     */
622    public boolean setSerialNumber(String value) {
623        return mSupplicantStaIfaceHal.setWpsSerialNumber(value);
624    }
625
626    /**
627     * Enable or disable power save mode.
628     *
629     * @param enabled true to enable, false to disable.
630     */
631    public void setPowerSave(boolean enabled) {
632        mSupplicantStaIfaceHal.setPowerSave(enabled);
633    }
634
635    /**
636     * Set concurrency priority between P2P & STA operations.
637     *
638     * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations,
639     *                            false otherwise.
640     * @return true if request is sent successfully, false otherwise.
641     */
642    public boolean setConcurrencyPriority(boolean isStaHigherPriority) {
643        return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority);
644    }
645
646    /**
647     * Enable/Disable auto reconnect functionality in wpa_supplicant.
648     *
649     * @param enable true to enable auto reconnecting, false to disable.
650     * @return true if request is sent successfully, false otherwise.
651     */
652    public boolean enableStaAutoReconnect(boolean enable) {
653        return mSupplicantStaIfaceHal.enableAutoReconnect(enable);
654    }
655
656    /**
657     * Migrate all the configured networks from wpa_supplicant.
658     *
659     * @param configs       Map of configuration key to configuration objects corresponding to all
660     *                      the networks.
661     * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf
662     * @return Max priority of all the configs.
663     */
664    public boolean migrateNetworksFromSupplicant(Map<String, WifiConfiguration> configs,
665                                                 SparseArray<Map<String, String>> networkExtras) {
666        return mSupplicantStaIfaceHal.loadNetworks(configs, networkExtras);
667    }
668
669    /**
670     * Add the provided network configuration to wpa_supplicant and initiate connection to it.
671     * This method does the following:
672     * 1. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect).
673     * 2. Add a new network to wpa_supplicant.
674     * 3. Save the provided configuration to wpa_supplicant.
675     * 4. Select the new network in wpa_supplicant.
676     * 5. Triggers reconnect command to wpa_supplicant.
677     *
678     * @param configuration WifiConfiguration parameters for the provided network.
679     * @return {@code true} if it succeeds, {@code false} otherwise
680     */
681    public boolean connectToNetwork(WifiConfiguration configuration) {
682        return mSupplicantStaIfaceHal.connectToNetwork(configuration);
683    }
684
685    /**
686     * Initiates roaming to the already configured network in wpa_supplicant. If the network
687     * configuration provided does not match the already configured network, then this triggers
688     * a new connection attempt (instead of roam).
689     * 1. First check if we're attempting to connect to the same network as we currently have
690     * configured.
691     * 2. Set the new bssid for the network in wpa_supplicant.
692     * 3. Triggers reassociate command to wpa_supplicant.
693     *
694     * @param configuration WifiConfiguration parameters for the provided network.
695     * @return {@code true} if it succeeds, {@code false} otherwise
696     */
697    public boolean roamToNetwork(WifiConfiguration configuration) {
698        return mSupplicantStaIfaceHal.roamToNetwork(configuration);
699    }
700
701    /**
702     * Get the framework network ID corresponding to the provided supplicant network ID for the
703     * network configured in wpa_supplicant.
704     *
705     * @param supplicantNetworkId network ID in wpa_supplicant for the network.
706     * @return Corresponding framework network ID if found, -1 if network not found.
707     */
708    public int getFrameworkNetworkId(int supplicantNetworkId) {
709        return supplicantNetworkId;
710    }
711
712    /**
713     * Remove all the networks.
714     *
715     * @return {@code true} if it succeeds, {@code false} otherwise
716     */
717    public boolean removeAllNetworks() {
718        return mSupplicantStaIfaceHal.removeAllNetworks();
719    }
720
721    /**
722     * Set the BSSID for the currently configured network in wpa_supplicant.
723     *
724     * @return true if successful, false otherwise.
725     */
726    public boolean setConfiguredNetworkBSSID(String bssid) {
727        return mSupplicantStaIfaceHal.setCurrentNetworkBssid(bssid);
728    }
729
730    /**
731     * Initiate ANQP query.
732     *
733     * @param bssid BSSID of the AP to be queried
734     * @param anqpIds Set of anqp IDs.
735     * @param hs20Subtypes Set of HS20 subtypes.
736     * @return true on success, false otherwise.
737     */
738    public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) {
739        if (bssid == null || ((anqpIds == null || anqpIds.isEmpty())
740                && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) {
741            Log.e(mTAG, "Invalid arguments for ANQP request.");
742            return false;
743        }
744        ArrayList<Short> anqpIdList = new ArrayList<>();
745        for (Integer anqpId : anqpIds) {
746            anqpIdList.add(anqpId.shortValue());
747        }
748        ArrayList<Integer> hs20SubtypeList = new ArrayList<>();
749        hs20SubtypeList.addAll(hs20Subtypes);
750        return mSupplicantStaIfaceHal.initiateAnqpQuery(bssid, anqpIdList, hs20SubtypeList);
751    }
752
753    /**
754     * Request a passpoint icon file |filename| from the specified AP |bssid|.
755     * @param bssid BSSID of the AP
756     * @param fileName name of the icon file
757     * @return true if request is sent successfully, false otherwise
758     */
759    public boolean requestIcon(String  bssid, String fileName) {
760        if (bssid == null || fileName == null) {
761            Log.e(mTAG, "Invalid arguments for Icon request.");
762            return false;
763        }
764        return mSupplicantStaIfaceHal.initiateHs20IconQuery(bssid, fileName);
765    }
766
767    /**
768     * Get the currently configured network's WPS NFC token.
769     *
770     * @return Hex string corresponding to the WPS NFC token.
771     */
772    public String getNfcWpsConfigurationToken(int netId) {
773        return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken();
774    }
775    /********************************************************
776     * Vendor HAL operations
777     ********************************************************/
778    /**
779     * Callback to notify vendor HAL death.
780     */
781    public interface VendorHalDeathEventHandler {
782        /**
783         * Invoked when the vendor HAL dies.
784         */
785        void onDeath();
786    }
787
788    /**
789     * Initializes the vendor HAL. This is just used to initialize the {@link HalDeviceManager}.
790     */
791    public boolean initializeVendorHal(VendorHalDeathEventHandler handler) {
792        return mWifiVendorHal.initialize(handler);
793    }
794
795    /**
796     * Bring up the Vendor HAL and configure for STA mode or AP mode.
797     *
798     * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
799     */
800    public boolean startHal(boolean isStaMode) {
801        return mWifiVendorHal.startVendorHal(isStaMode);
802    }
803
804    /**
805     * Stops the HAL
806     */
807    public void stopHal() {
808        mWifiVendorHal.stopVendorHal();
809    }
810
811    /**
812     * Tests whether the HAL is running or not
813     */
814    public boolean isHalStarted() {
815        return mWifiVendorHal.isHalStarted();
816    }
817
818    // TODO: Change variable names to camel style.
819    public static class ScanCapabilities {
820        public int  max_scan_cache_size;
821        public int  max_scan_buckets;
822        public int  max_ap_cache_per_scan;
823        public int  max_rssi_sample_size;
824        public int  max_scan_reporting_threshold;
825        public int  max_hotlist_bssids;
826        public int  max_significant_wifi_change_aps;
827        public int  max_bssid_history_entries;
828        public int  max_number_epno_networks;
829        public int  max_number_epno_networks_by_ssid;
830        public int  max_number_of_white_listed_ssid;
831    }
832
833    /**
834     * Gets the scan capabilities
835     *
836     * @param capabilities object to be filled in
837     * @return true for success. false for failure
838     */
839    public boolean getBgScanCapabilities(ScanCapabilities capabilities) {
840        return mWifiVendorHal.getBgScanCapabilities(capabilities);
841    }
842
843    public static class ChannelSettings {
844        public int frequency;
845        public int dwell_time_ms;
846        public boolean passive;
847    }
848
849    public static class BucketSettings {
850        public int bucket;
851        public int band;
852        public int period_ms;
853        public int max_period_ms;
854        public int step_count;
855        public int report_events;
856        public int num_channels;
857        public ChannelSettings[] channels;
858    }
859
860    /**
861     * Network parameters for hidden networks to be scanned for.
862     */
863    public static class HiddenNetwork {
864        public String ssid;
865
866        @Override
867        public boolean equals(Object otherObj) {
868            if (this == otherObj) {
869                return true;
870            } else if (otherObj == null || getClass() != otherObj.getClass()) {
871                return false;
872            }
873            HiddenNetwork other = (HiddenNetwork) otherObj;
874            return Objects.equals(ssid, other.ssid);
875        }
876
877        @Override
878        public int hashCode() {
879            return (ssid == null ? 0 : ssid.hashCode());
880        }
881    }
882
883    public static class ScanSettings {
884        public int base_period_ms;
885        public int max_ap_per_scan;
886        public int report_threshold_percent;
887        public int report_threshold_num_scans;
888        public int num_buckets;
889        /* Not used for bg scans. Only works for single scans. */
890        public HiddenNetwork[] hiddenNetworks;
891        public BucketSettings[] buckets;
892    }
893
894    /**
895     * Network parameters to start PNO scan.
896     */
897    public static class PnoNetwork {
898        public String ssid;
899        public byte flags;
900        public byte auth_bit_field;
901
902        @Override
903        public boolean equals(Object otherObj) {
904            if (this == otherObj) {
905                return true;
906            } else if (otherObj == null || getClass() != otherObj.getClass()) {
907                return false;
908            }
909            PnoNetwork other = (PnoNetwork) otherObj;
910            return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags)
911                    && (auth_bit_field == other.auth_bit_field));
912        }
913
914        @Override
915        public int hashCode() {
916            int result = (ssid == null ? 0 : ssid.hashCode());
917            result ^= ((int) flags * 31) + ((int) auth_bit_field << 8);
918            return result;
919        }
920    }
921
922    /**
923     * Parameters to start PNO scan. This holds the list of networks which are going to used for
924     * PNO scan.
925     */
926    public static class PnoSettings {
927        public int min5GHzRssi;
928        public int min24GHzRssi;
929        public int initialScoreMax;
930        public int currentConnectionBonus;
931        public int sameNetworkBonus;
932        public int secureBonus;
933        public int band5GHzBonus;
934        public int periodInMs;
935        public boolean isConnected;
936        public PnoNetwork[] networkList;
937    }
938
939    public static interface ScanEventHandler {
940        /**
941         * Called for each AP as it is found with the entire contents of the beacon/probe response.
942         * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified.
943         */
944        void onFullScanResult(ScanResult fullScanResult, int bucketsScanned);
945        /**
946         * Callback on an event during a gscan scan.
947         * See WifiNative.WIFI_SCAN_* for possible values.
948         */
949        void onScanStatus(int event);
950        /**
951         * Called with the current cached scan results when gscan is paused.
952         */
953        void onScanPaused(WifiScanner.ScanData[] data);
954        /**
955         * Called with the current cached scan results when gscan is resumed.
956         */
957        void onScanRestarted();
958    }
959
960    /**
961     * Handler to notify the occurrence of various events during PNO scan.
962     */
963    public interface PnoEventHandler {
964        /**
965         * Callback to notify when one of the shortlisted networks is found during PNO scan.
966         * @param results List of Scan results received.
967         */
968        void onPnoNetworkFound(ScanResult[] results);
969
970        /**
971         * Callback to notify when the PNO scan schedule fails.
972         */
973        void onPnoScanFailed();
974    }
975
976    public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
977    public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
978    public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
979    public static final int WIFI_SCAN_FAILED = 3;
980
981    /**
982     * Starts a background scan.
983     * Any ongoing scan will be stopped first
984     *
985     * @param settings     to control the scan
986     * @param eventHandler to call with the results
987     * @return true for success
988     */
989    public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) {
990        return mWifiVendorHal.startBgScan(settings, eventHandler);
991    }
992
993    /**
994     * Stops any ongoing backgound scan
995     */
996    public void stopBgScan() {
997        mWifiVendorHal.stopBgScan();
998    }
999
1000    /**
1001     * Pauses an ongoing backgound scan
1002     */
1003    public void pauseBgScan() {
1004        mWifiVendorHal.pauseBgScan();
1005    }
1006
1007    /**
1008     * Restarts a paused scan
1009     */
1010    public void restartBgScan() {
1011        mWifiVendorHal.restartBgScan();
1012    }
1013
1014    /**
1015     * Gets the latest scan results received.
1016     */
1017    public WifiScanner.ScanData[] getBgScanResults() {
1018        return mWifiVendorHal.getBgScanResults();
1019    }
1020
1021    public static interface HotlistEventHandler {
1022        void onHotlistApFound (ScanResult[] result);
1023        void onHotlistApLost  (ScanResult[] result);
1024    }
1025
1026    public boolean setHotlist(WifiScanner.HotlistSettings settings,
1027            HotlistEventHandler eventHandler) {
1028        Log.e(mTAG, "setHotlist not supported");
1029        return false;
1030    }
1031
1032    public void resetHotlist() {
1033        Log.e(mTAG, "resetHotlist not supported");
1034    }
1035
1036    public static interface SignificantWifiChangeEventHandler {
1037        void onChangesFound(ScanResult[] result);
1038    }
1039
1040    public boolean trackSignificantWifiChange(
1041            WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler) {
1042        Log.e(mTAG, "trackSignificantWifiChange not supported");
1043        return false;
1044    }
1045
1046    public void untrackSignificantWifiChange() {
1047        Log.e(mTAG, "untrackSignificantWifiChange not supported");
1048    }
1049
1050    public WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
1051        return mWifiVendorHal.getWifiLinkLayerStats();
1052    }
1053
1054    /**
1055     * Get the supported features
1056     *
1057     * @return bitmask defined by WifiManager.WIFI_FEATURE_*
1058     */
1059    public int getSupportedFeatureSet() {
1060        return mWifiVendorHal.getSupportedFeatureSet();
1061    }
1062
1063    public static interface RttEventHandler {
1064        void onRttResults(RttManager.RttResult[] result);
1065    }
1066
1067    /**
1068     * Starts a new rtt request
1069     *
1070     * @param params RTT request params. Refer to {@link RttManager#RttParams}.
1071     * @param handler Callback to be invoked to notify any results.
1072     * @return true if the request was successful, false otherwise.
1073     */
1074    public boolean requestRtt(
1075            RttManager.RttParams[] params, RttEventHandler handler) {
1076        return mWifiVendorHal.requestRtt(params, handler);
1077    }
1078
1079    /**
1080     * Cancels an outstanding rtt request
1081     *
1082     * @param params RTT request params. Refer to {@link RttManager#RttParams}
1083     * @return true if there was an outstanding request and it was successfully cancelled
1084     */
1085    public boolean cancelRtt(RttManager.RttParams[] params) {
1086        return mWifiVendorHal.cancelRtt(params);
1087    }
1088
1089    /**
1090     * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder
1091     * role is successfully enabled, {@code null} otherwise.
1092     *
1093     * @param timeoutSeconds timeout to use for the responder.
1094     */
1095    @Nullable
1096    public ResponderConfig enableRttResponder(int timeoutSeconds) {
1097        return mWifiVendorHal.enableRttResponder(timeoutSeconds);
1098    }
1099
1100    /**
1101     * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled,
1102     * {@code false} otherwise.
1103     */
1104    public boolean disableRttResponder() {
1105        return mWifiVendorHal.disableRttResponder();
1106    }
1107
1108    /**
1109     * Set the MAC OUI during scanning.
1110     * An OUI {Organizationally Unique Identifier} is a 24-bit number that
1111     * uniquely identifies a vendor or manufacturer.
1112     *
1113     * @param oui OUI to set.
1114     * @return true for success
1115     */
1116    public boolean setScanningMacOui(byte[] oui) {
1117        return mWifiVendorHal.setScanningMacOui(oui);
1118    }
1119
1120    /**
1121     * Query the list of valid frequencies for the provided band.
1122     * The result depends on the on the country code that has been set.
1123     *
1124     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
1125     * @return frequencies vector of valid frequencies (MHz), or null for error.
1126     * @throws IllegalArgumentException if band is not recognized.
1127     */
1128    public int [] getChannelsForBand(int band) {
1129        return mWifiVendorHal.getChannelsForBand(band);
1130    }
1131
1132    /**
1133     * Indicates whether getChannelsForBand is supported.
1134     *
1135     * @return true if it is.
1136     */
1137    public boolean isGetChannelsForBandSupported() {
1138        return mWifiVendorHal.isGetChannelsForBandSupported();
1139    }
1140
1141    /**
1142     * RTT (Round Trip Time) measurement capabilities of the device.
1143     */
1144    public RttManager.RttCapabilities getRttCapabilities() {
1145        return mWifiVendorHal.getRttCapabilities();
1146    }
1147
1148    /**
1149     * Get the APF (Android Packet Filter) capabilities of the device
1150     */
1151    public ApfCapabilities getApfCapabilities() {
1152        return mWifiVendorHal.getApfCapabilities();
1153    }
1154
1155    /**
1156     * Installs an APF program on this iface, replacing any existing program.
1157     *
1158     * @param filter is the android packet filter program
1159     * @return true for success
1160     */
1161    public boolean installPacketFilter(byte[] filter) {
1162        return mWifiVendorHal.installPacketFilter(filter);
1163    }
1164
1165    /**
1166     * Set country code for this AP iface.
1167     *
1168     * @param countryCode - two-letter country code (as ISO 3166)
1169     * @return true for success
1170     */
1171    public boolean setCountryCodeHal(String countryCode) {
1172        return mWifiVendorHal.setCountryCodeHal(countryCode);
1173    }
1174
1175    //---------------------------------------------------------------------------------
1176    /* Wifi Logger commands/events */
1177    public static interface WifiLoggerEventHandler {
1178        void onRingBufferData(RingBufferStatus status, byte[] buffer);
1179        void onWifiAlert(int errorCode, byte[] buffer);
1180    }
1181
1182    /**
1183     * Registers the logger callback and enables alerts.
1184     * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked.
1185     *
1186     * @param handler Callback to be invoked.
1187     * @return true on success, false otherwise.
1188     */
1189    public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
1190        return mWifiVendorHal.setLoggingEventHandler(handler);
1191    }
1192
1193    /**
1194     * Control debug data collection
1195     *
1196     * @param verboseLevel 0 to 3, inclusive. 0 stops logging.
1197     * @param flags        Ignored.
1198     * @param maxInterval  Maximum interval between reports; ignore if 0.
1199     * @param minDataSize  Minimum data size in buffer for report; ignore if 0.
1200     * @param ringName     Name of the ring for which data collection is to start.
1201     * @return true for success, false otherwise.
1202     */
1203    public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
1204            int minDataSize, String ringName){
1205        return mWifiVendorHal.startLoggingRingBuffer(
1206                verboseLevel, flags, maxInterval, minDataSize, ringName);
1207    }
1208
1209    /**
1210     * Logger features exposed.
1211     * This is a no-op now, will always return -1.
1212     *
1213     * @return true on success, false otherwise.
1214     */
1215    public int getSupportedLoggerFeatureSet() {
1216        return mWifiVendorHal.getSupportedLoggerFeatureSet();
1217    }
1218
1219    /**
1220     * Stops all logging and resets the logger callback.
1221     * This stops both the alerts and ring buffer data collection.
1222     * @return true on success, false otherwise.
1223     */
1224    public boolean resetLogHandler() {
1225        return mWifiVendorHal.resetLogHandler();
1226    }
1227
1228    /**
1229     * Vendor-provided wifi driver version string
1230     *
1231     * @return String returned from the HAL.
1232     */
1233    public String getDriverVersion() {
1234        return mWifiVendorHal.getDriverVersion();
1235    }
1236
1237    /**
1238     * Vendor-provided wifi firmware version string
1239     *
1240     * @return String returned from the HAL.
1241     */
1242    public String getFirmwareVersion() {
1243        return mWifiVendorHal.getFirmwareVersion();
1244    }
1245
1246    public static class RingBufferStatus{
1247        String name;
1248        int flag;
1249        int ringBufferId;
1250        int ringBufferByteSize;
1251        int verboseLevel;
1252        int writtenBytes;
1253        int readBytes;
1254        int writtenRecords;
1255
1256        // Bit masks for interpreting |flag|
1257        public static final int HAS_BINARY_ENTRIES = (1 << 0);
1258        public static final int HAS_ASCII_ENTRIES = (1 << 1);
1259        public static final int HAS_PER_PACKET_ENTRIES = (1 << 2);
1260
1261        @Override
1262        public String toString() {
1263            return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
1264                    " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
1265                    " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
1266                    " writtenRecords: " + writtenRecords;
1267        }
1268    }
1269
1270    /**
1271     * API to get the status of all ring buffers supported by driver
1272     */
1273    public RingBufferStatus[] getRingBufferStatus() {
1274        return mWifiVendorHal.getRingBufferStatus();
1275    }
1276
1277    /**
1278     * Indicates to driver that all the data has to be uploaded urgently
1279     *
1280     * @param ringName Name of the ring buffer requested.
1281     * @return true on success, false otherwise.
1282     */
1283    public boolean getRingBufferData(String ringName) {
1284        return mWifiVendorHal.getRingBufferData(ringName);
1285    }
1286
1287    /**
1288     * Request vendor debug info from the firmware
1289     *
1290     * @return Raw data obtained from the HAL.
1291     */
1292    public byte[] getFwMemoryDump() {
1293        return mWifiVendorHal.getFwMemoryDump();
1294    }
1295
1296    /**
1297     * Request vendor debug info from the driver
1298     *
1299     * @return Raw data obtained from the HAL.
1300     */
1301    public byte[] getDriverStateDump() {
1302        return mWifiVendorHal.getDriverStateDump();
1303    }
1304
1305    //---------------------------------------------------------------------------------
1306    /* Packet fate API */
1307
1308    @Immutable
1309    abstract static class FateReport {
1310        final static int USEC_PER_MSEC = 1000;
1311        // The driver timestamp is a 32-bit counter, in microseconds. This field holds the
1312        // maximal value of a driver timestamp in milliseconds.
1313        final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000);
1314        final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
1315
1316        final byte mFate;
1317        final long mDriverTimestampUSec;
1318        final byte mFrameType;
1319        final byte[] mFrameBytes;
1320        final long mEstimatedWallclockMSec;
1321
1322        FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1323            mFate = fate;
1324            mDriverTimestampUSec = driverTimestampUSec;
1325            mEstimatedWallclockMSec =
1326                    convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec);
1327            mFrameType = frameType;
1328            mFrameBytes = frameBytes;
1329        }
1330
1331        public String toTableRowString() {
1332            StringWriter sw = new StringWriter();
1333            PrintWriter pw = new PrintWriter(sw);
1334            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1335            dateFormatter.setTimeZone(TimeZone.getDefault());
1336            pw.format("%-15s  %12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1337                    mDriverTimestampUSec,
1338                    dateFormatter.format(new Date(mEstimatedWallclockMSec)),
1339                    directionToString(), fateToString(), parser.mMostSpecificProtocolString,
1340                    parser.mTypeString, parser.mResultString);
1341            return sw.toString();
1342        }
1343
1344        public String toVerboseStringWithPiiAllowed() {
1345            StringWriter sw = new StringWriter();
1346            PrintWriter pw = new PrintWriter(sw);
1347            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1348            pw.format("Frame direction: %s\n", directionToString());
1349            pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
1350            pw.format("Frame fate: %s\n", fateToString());
1351            pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
1352            pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
1353            pw.format("Frame protocol type: %s\n", parser.mTypeString);
1354            pw.format("Frame length: %d\n", mFrameBytes.length);
1355            pw.append("Frame bytes");
1356            pw.append(HexDump.dumpHexString(mFrameBytes));  // potentially contains PII
1357            pw.append("\n");
1358            return sw.toString();
1359        }
1360
1361        /* Returns a header to match the output of toTableRowString(). */
1362        public static String getTableHeader() {
1363            StringWriter sw = new StringWriter();
1364            PrintWriter pw = new PrintWriter(sw);
1365            pw.format("\n%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1366                    "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result");
1367            pw.format("%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1368                    "---------", "--------", "---------", "----", "--------", "----", "------");
1369            return sw.toString();
1370        }
1371
1372        protected abstract String directionToString();
1373
1374        protected abstract String fateToString();
1375
1376        private static String frameTypeToString(byte frameType) {
1377            switch (frameType) {
1378                case WifiLoggerHal.FRAME_TYPE_UNKNOWN:
1379                    return "unknown";
1380                case WifiLoggerHal.FRAME_TYPE_ETHERNET_II:
1381                    return "data";
1382                case WifiLoggerHal.FRAME_TYPE_80211_MGMT:
1383                    return "802.11 management";
1384                default:
1385                    return Byte.toString(frameType);
1386            }
1387        }
1388
1389        /**
1390         * Converts a driver timestamp to a wallclock time, based on the current
1391         * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of
1392         * microseconds, with the same base as BOOTTIME.
1393         */
1394        private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) {
1395            final long wallclockMillisNow = System.currentTimeMillis();
1396            final long boottimeMillisNow = SystemClock.elapsedRealtime();
1397            final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC;
1398
1399            long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC;
1400            if (boottimeTimestampMillis < driverTimestampMillis) {
1401                // The 32-bit microsecond count has wrapped between the time that the driver
1402                // recorded the packet, and the call to this function. Adjust the BOOTTIME
1403                // timestamp, to compensate.
1404                //
1405                // Note that overflow is not a concern here, since the result is less than
1406                // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above,
1407                // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since
1408                // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit
1409                // within a long.
1410                boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC;
1411            }
1412
1413            final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis;
1414            return wallclockMillisNow - millisSincePacketTimestamp;
1415        }
1416    }
1417
1418    /**
1419     * Represents the fate information for one outbound packet.
1420     */
1421    @Immutable
1422    public static final class TxFateReport extends FateReport {
1423        TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1424            super(fate, driverTimestampUSec, frameType, frameBytes);
1425        }
1426
1427        @Override
1428        protected String directionToString() {
1429            return "TX";
1430        }
1431
1432        @Override
1433        protected String fateToString() {
1434            switch (mFate) {
1435                case WifiLoggerHal.TX_PKT_FATE_ACKED:
1436                    return "acked";
1437                case WifiLoggerHal.TX_PKT_FATE_SENT:
1438                    return "sent";
1439                case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED:
1440                    return "firmware queued";
1441                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID:
1442                    return "firmware dropped (invalid frame)";
1443                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS:
1444                    return "firmware dropped (no bufs)";
1445                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER:
1446                    return "firmware dropped (other)";
1447                case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED:
1448                    return "driver queued";
1449                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID:
1450                    return "driver dropped (invalid frame)";
1451                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS:
1452                    return "driver dropped (no bufs)";
1453                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER:
1454                    return "driver dropped (other)";
1455                default:
1456                    return Byte.toString(mFate);
1457            }
1458        }
1459    }
1460
1461    /**
1462     * Represents the fate information for one inbound packet.
1463     */
1464    @Immutable
1465    public static final class RxFateReport extends FateReport {
1466        RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1467            super(fate, driverTimestampUSec, frameType, frameBytes);
1468        }
1469
1470        @Override
1471        protected String directionToString() {
1472            return "RX";
1473        }
1474
1475        @Override
1476        protected String fateToString() {
1477            switch (mFate) {
1478                case WifiLoggerHal.RX_PKT_FATE_SUCCESS:
1479                    return "success";
1480                case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED:
1481                    return "firmware queued";
1482                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER:
1483                    return "firmware dropped (filter)";
1484                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID:
1485                    return "firmware dropped (invalid frame)";
1486                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS:
1487                    return "firmware dropped (no bufs)";
1488                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER:
1489                    return "firmware dropped (other)";
1490                case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED:
1491                    return "driver queued";
1492                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER:
1493                    return "driver dropped (filter)";
1494                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID:
1495                    return "driver dropped (invalid frame)";
1496                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS:
1497                    return "driver dropped (no bufs)";
1498                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER:
1499                    return "driver dropped (other)";
1500                default:
1501                    return Byte.toString(mFate);
1502            }
1503        }
1504    }
1505
1506    /**
1507     * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started.
1508     *
1509     * @return true for success, false otherwise.
1510     */
1511    public boolean startPktFateMonitoring() {
1512        return mWifiVendorHal.startPktFateMonitoring();
1513    }
1514
1515    /**
1516     * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started.
1517     *
1518     * @return true for success, false otherwise.
1519     */
1520    public boolean getTxPktFates(TxFateReport[] reportBufs) {
1521        return mWifiVendorHal.getTxPktFates(reportBufs);
1522    }
1523
1524    /**
1525     * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started.
1526     */
1527    public boolean getRxPktFates(RxFateReport[] reportBufs) {
1528        return mWifiVendorHal.getRxPktFates(reportBufs);
1529    }
1530
1531    /**
1532     * Set the PNO settings & the network list in HAL to start PNO.
1533     * @param settings PNO settings and network list.
1534     * @param eventHandler Handler to receive notifications back during PNO scan.
1535     * @return true if success, false otherwise
1536     */
1537    public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) {
1538        Log.e(mTAG, "setPnoList not supported");
1539        return false;
1540    }
1541
1542    /**
1543     * Reset the PNO settings in HAL to stop PNO.
1544     * @return true if success, false otherwise
1545     */
1546    public boolean resetPnoList() {
1547        Log.e(mTAG, "resetPnoList not supported");
1548        return false;
1549    }
1550
1551    /**
1552     * Start sending the specified keep alive packets periodically.
1553     *
1554     * @param slot Integer used to identify each request.
1555     * @param keepAlivePacket Raw packet contents to send.
1556     * @param period Period to use for sending these packets.
1557     * @return 0 for success, -1 for error
1558     */
1559    public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket,
1560                                           int period) {
1561        String[] macAddrStr = getMacAddress().split(":");
1562        byte[] srcMac = new byte[6];
1563        for (int i = 0; i < 6; i++) {
1564            Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
1565            srcMac[i] = hexVal.byteValue();
1566        }
1567        return mWifiVendorHal.startSendingOffloadedPacket(
1568                slot, srcMac, keepAlivePacket, period);
1569    }
1570
1571    /**
1572     * Stop sending the specified keep alive packets.
1573     *
1574     * @param slot id - same as startSendingOffloadedPacket call.
1575     * @return 0 for success, -1 for error
1576     */
1577    public int stopSendingOffloadedPacket(int slot) {
1578        return mWifiVendorHal.stopSendingOffloadedPacket(slot);
1579    }
1580
1581    public static interface WifiRssiEventHandler {
1582        void onRssiThresholdBreached(byte curRssi);
1583    }
1584
1585    /**
1586     * Start RSSI monitoring on the currently connected access point.
1587     *
1588     * @param maxRssi          Maximum RSSI threshold.
1589     * @param minRssi          Minimum RSSI threshold.
1590     * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
1591     * @return 0 for success, -1 for failure
1592     */
1593    public int startRssiMonitoring(byte maxRssi, byte minRssi,
1594                                   WifiRssiEventHandler rssiEventHandler) {
1595        return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler);
1596    }
1597
1598    public int stopRssiMonitoring() {
1599        return mWifiVendorHal.stopRssiMonitoring();
1600    }
1601
1602    /**
1603     * Fetch the host wakeup reasons stats from wlan driver.
1604     *
1605     * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
1606     */
1607    public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
1608        return mWifiVendorHal.getWlanWakeReasonCount();
1609    }
1610
1611    /**
1612     * Enable/Disable Neighbour discovery offload functionality in the firmware.
1613     *
1614     * @param enabled true to enable, false to disable.
1615     * @return true for success, false otherwise.
1616     */
1617    public boolean configureNeighborDiscoveryOffload(boolean enabled) {
1618        return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled);
1619    }
1620
1621    // Firmware roaming control.
1622
1623    /**
1624     * Class to retrieve firmware roaming capability parameters.
1625     */
1626    public static class RoamingCapabilities {
1627        public int  maxBlacklistSize;
1628        public int  maxWhitelistSize;
1629    }
1630
1631    /**
1632     * Query the firmware roaming capabilities.
1633     * @return true for success, false otherwise.
1634     */
1635    public boolean getRoamingCapabilities(RoamingCapabilities capabilities) {
1636        return mWifiVendorHal.getRoamingCapabilities(capabilities);
1637    }
1638
1639    /**
1640     * Macros for controlling firmware roaming.
1641     */
1642    public static final int DISABLE_FIRMWARE_ROAMING = 0;
1643    public static final int ENABLE_FIRMWARE_ROAMING = 1;
1644
1645    /**
1646     * Enable/disable firmware roaming.
1647     *
1648     * @return error code returned from HAL.
1649     */
1650    public int enableFirmwareRoaming(int state) {
1651        return mWifiVendorHal.enableFirmwareRoaming(state);
1652    }
1653
1654    /**
1655     * Class for specifying the roaming configurations.
1656     */
1657    public static class RoamingConfig {
1658        public ArrayList<String> blacklistBssids;
1659        public ArrayList<String> whitelistSsids;
1660    }
1661
1662    /**
1663     * Set firmware roaming configurations.
1664     */
1665    public boolean configureRoaming(RoamingConfig config) {
1666        Log.d(mTAG, "configureRoaming ");
1667        return mWifiVendorHal.configureRoaming(config);
1668    }
1669
1670    /**
1671     * Reset firmware roaming configuration.
1672     */
1673    public boolean resetRoamingConfiguration() {
1674        // Pass in an empty RoamingConfig object which translates to zero size
1675        // blacklist and whitelist to reset the firmware roaming configuration.
1676        return mWifiVendorHal.configureRoaming(new RoamingConfig());
1677    }
1678
1679    /********************************************************
1680     * JNI operations
1681     ********************************************************/
1682    /* Register native functions */
1683    static {
1684        /* Native functions are defined in libwifi-service.so */
1685        System.loadLibrary("wifi-service");
1686        registerNatives();
1687    }
1688
1689    private static native int registerNatives();
1690    /* kernel logging support */
1691    private static native byte[] readKernelLogNative();
1692
1693    /**
1694     * Fetches the latest kernel logs.
1695     */
1696    public synchronized String readKernelLog() {
1697        byte[] bytes = readKernelLogNative();
1698        if (bytes != null) {
1699            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
1700            try {
1701                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
1702                return decoded.toString();
1703            } catch (CharacterCodingException cce) {
1704                return new String(bytes, StandardCharsets.ISO_8859_1);
1705            }
1706        } else {
1707            return "*** failed to read kernel log ***";
1708        }
1709    }
1710}
1711