WifiNative.java revision fab2bc6d0df6f2523d0b8a5ecfebaf1ee936bcee
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 getCurrentNetworkWpsNfcConfigurationToken() {
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    }
826
827    /**
828     * Gets the scan capabilities
829     *
830     * @param capabilities object to be filled in
831     * @return true for success. false for failure
832     */
833    public boolean getBgScanCapabilities(ScanCapabilities capabilities) {
834        return mWifiVendorHal.getBgScanCapabilities(capabilities);
835    }
836
837    public static class ChannelSettings {
838        public int frequency;
839        public int dwell_time_ms;
840        public boolean passive;
841    }
842
843    public static class BucketSettings {
844        public int bucket;
845        public int band;
846        public int period_ms;
847        public int max_period_ms;
848        public int step_count;
849        public int report_events;
850        public int num_channels;
851        public ChannelSettings[] channels;
852    }
853
854    /**
855     * Network parameters for hidden networks to be scanned for.
856     */
857    public static class HiddenNetwork {
858        public String ssid;
859
860        @Override
861        public boolean equals(Object otherObj) {
862            if (this == otherObj) {
863                return true;
864            } else if (otherObj == null || getClass() != otherObj.getClass()) {
865                return false;
866            }
867            HiddenNetwork other = (HiddenNetwork) otherObj;
868            return Objects.equals(ssid, other.ssid);
869        }
870
871        @Override
872        public int hashCode() {
873            return (ssid == null ? 0 : ssid.hashCode());
874        }
875    }
876
877    public static class ScanSettings {
878        public int base_period_ms;
879        public int max_ap_per_scan;
880        public int report_threshold_percent;
881        public int report_threshold_num_scans;
882        public int num_buckets;
883        /* Not used for bg scans. Only works for single scans. */
884        public HiddenNetwork[] hiddenNetworks;
885        public BucketSettings[] buckets;
886    }
887
888    /**
889     * Network parameters to start PNO scan.
890     */
891    public static class PnoNetwork {
892        public String ssid;
893        public byte flags;
894        public byte auth_bit_field;
895
896        @Override
897        public boolean equals(Object otherObj) {
898            if (this == otherObj) {
899                return true;
900            } else if (otherObj == null || getClass() != otherObj.getClass()) {
901                return false;
902            }
903            PnoNetwork other = (PnoNetwork) otherObj;
904            return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags)
905                    && (auth_bit_field == other.auth_bit_field));
906        }
907
908        @Override
909        public int hashCode() {
910            int result = (ssid == null ? 0 : ssid.hashCode());
911            result ^= ((int) flags * 31) + ((int) auth_bit_field << 8);
912            return result;
913        }
914    }
915
916    /**
917     * Parameters to start PNO scan. This holds the list of networks which are going to used for
918     * PNO scan.
919     */
920    public static class PnoSettings {
921        public int min5GHzRssi;
922        public int min24GHzRssi;
923        public int initialScoreMax;
924        public int currentConnectionBonus;
925        public int sameNetworkBonus;
926        public int secureBonus;
927        public int band5GHzBonus;
928        public int periodInMs;
929        public boolean isConnected;
930        public PnoNetwork[] networkList;
931    }
932
933    public static interface ScanEventHandler {
934        /**
935         * Called for each AP as it is found with the entire contents of the beacon/probe response.
936         * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified.
937         */
938        void onFullScanResult(ScanResult fullScanResult, int bucketsScanned);
939        /**
940         * Callback on an event during a gscan scan.
941         * See WifiNative.WIFI_SCAN_* for possible values.
942         */
943        void onScanStatus(int event);
944        /**
945         * Called with the current cached scan results when gscan is paused.
946         */
947        void onScanPaused(WifiScanner.ScanData[] data);
948        /**
949         * Called with the current cached scan results when gscan is resumed.
950         */
951        void onScanRestarted();
952    }
953
954    /**
955     * Handler to notify the occurrence of various events during PNO scan.
956     */
957    public interface PnoEventHandler {
958        /**
959         * Callback to notify when one of the shortlisted networks is found during PNO scan.
960         * @param results List of Scan results received.
961         */
962        void onPnoNetworkFound(ScanResult[] results);
963
964        /**
965         * Callback to notify when the PNO scan schedule fails.
966         */
967        void onPnoScanFailed();
968    }
969
970    public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
971    public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
972    public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
973    public static final int WIFI_SCAN_FAILED = 3;
974
975    /**
976     * Starts a background scan.
977     * Any ongoing scan will be stopped first
978     *
979     * @param settings     to control the scan
980     * @param eventHandler to call with the results
981     * @return true for success
982     */
983    public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) {
984        return mWifiVendorHal.startBgScan(settings, eventHandler);
985    }
986
987    /**
988     * Stops any ongoing backgound scan
989     */
990    public void stopBgScan() {
991        mWifiVendorHal.stopBgScan();
992    }
993
994    /**
995     * Pauses an ongoing backgound scan
996     */
997    public void pauseBgScan() {
998        mWifiVendorHal.pauseBgScan();
999    }
1000
1001    /**
1002     * Restarts a paused scan
1003     */
1004    public void restartBgScan() {
1005        mWifiVendorHal.restartBgScan();
1006    }
1007
1008    /**
1009     * Gets the latest scan results received.
1010     */
1011    public WifiScanner.ScanData[] getBgScanResults() {
1012        return mWifiVendorHal.getBgScanResults();
1013    }
1014
1015    public WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
1016        return mWifiVendorHal.getWifiLinkLayerStats();
1017    }
1018
1019    /**
1020     * Get the supported features
1021     *
1022     * @return bitmask defined by WifiManager.WIFI_FEATURE_*
1023     */
1024    public int getSupportedFeatureSet() {
1025        return mWifiVendorHal.getSupportedFeatureSet();
1026    }
1027
1028    public static interface RttEventHandler {
1029        void onRttResults(RttManager.RttResult[] result);
1030    }
1031
1032    /**
1033     * Starts a new rtt request
1034     *
1035     * @param params RTT request params. Refer to {@link RttManager#RttParams}.
1036     * @param handler Callback to be invoked to notify any results.
1037     * @return true if the request was successful, false otherwise.
1038     */
1039    public boolean requestRtt(
1040            RttManager.RttParams[] params, RttEventHandler handler) {
1041        return mWifiVendorHal.requestRtt(params, handler);
1042    }
1043
1044    /**
1045     * Cancels an outstanding rtt request
1046     *
1047     * @param params RTT request params. Refer to {@link RttManager#RttParams}
1048     * @return true if there was an outstanding request and it was successfully cancelled
1049     */
1050    public boolean cancelRtt(RttManager.RttParams[] params) {
1051        return mWifiVendorHal.cancelRtt(params);
1052    }
1053
1054    /**
1055     * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder
1056     * role is successfully enabled, {@code null} otherwise.
1057     *
1058     * @param timeoutSeconds timeout to use for the responder.
1059     */
1060    @Nullable
1061    public ResponderConfig enableRttResponder(int timeoutSeconds) {
1062        return mWifiVendorHal.enableRttResponder(timeoutSeconds);
1063    }
1064
1065    /**
1066     * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled,
1067     * {@code false} otherwise.
1068     */
1069    public boolean disableRttResponder() {
1070        return mWifiVendorHal.disableRttResponder();
1071    }
1072
1073    /**
1074     * Set the MAC OUI during scanning.
1075     * An OUI {Organizationally Unique Identifier} is a 24-bit number that
1076     * uniquely identifies a vendor or manufacturer.
1077     *
1078     * @param oui OUI to set.
1079     * @return true for success
1080     */
1081    public boolean setScanningMacOui(byte[] oui) {
1082        return mWifiVendorHal.setScanningMacOui(oui);
1083    }
1084
1085    /**
1086     * Query the list of valid frequencies for the provided band.
1087     * The result depends on the on the country code that has been set.
1088     *
1089     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
1090     * @return frequencies vector of valid frequencies (MHz), or null for error.
1091     * @throws IllegalArgumentException if band is not recognized.
1092     */
1093    public int [] getChannelsForBand(int band) {
1094        return mWifiVendorHal.getChannelsForBand(band);
1095    }
1096
1097    /**
1098     * Indicates whether getChannelsForBand is supported.
1099     *
1100     * @return true if it is.
1101     */
1102    public boolean isGetChannelsForBandSupported() {
1103        return mWifiVendorHal.isGetChannelsForBandSupported();
1104    }
1105
1106    /**
1107     * RTT (Round Trip Time) measurement capabilities of the device.
1108     */
1109    public RttManager.RttCapabilities getRttCapabilities() {
1110        return mWifiVendorHal.getRttCapabilities();
1111    }
1112
1113    /**
1114     * Get the APF (Android Packet Filter) capabilities of the device
1115     */
1116    public ApfCapabilities getApfCapabilities() {
1117        return mWifiVendorHal.getApfCapabilities();
1118    }
1119
1120    /**
1121     * Installs an APF program on this iface, replacing any existing program.
1122     *
1123     * @param filter is the android packet filter program
1124     * @return true for success
1125     */
1126    public boolean installPacketFilter(byte[] filter) {
1127        return mWifiVendorHal.installPacketFilter(filter);
1128    }
1129
1130    /**
1131     * Set country code for this AP iface.
1132     *
1133     * @param countryCode - two-letter country code (as ISO 3166)
1134     * @return true for success
1135     */
1136    public boolean setCountryCodeHal(String countryCode) {
1137        return mWifiVendorHal.setCountryCodeHal(countryCode);
1138    }
1139
1140    //---------------------------------------------------------------------------------
1141    /* Wifi Logger commands/events */
1142    public static interface WifiLoggerEventHandler {
1143        void onRingBufferData(RingBufferStatus status, byte[] buffer);
1144        void onWifiAlert(int errorCode, byte[] buffer);
1145    }
1146
1147    /**
1148     * Registers the logger callback and enables alerts.
1149     * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked.
1150     *
1151     * @param handler Callback to be invoked.
1152     * @return true on success, false otherwise.
1153     */
1154    public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
1155        return mWifiVendorHal.setLoggingEventHandler(handler);
1156    }
1157
1158    /**
1159     * Control debug data collection
1160     *
1161     * @param verboseLevel 0 to 3, inclusive. 0 stops logging.
1162     * @param flags        Ignored.
1163     * @param maxInterval  Maximum interval between reports; ignore if 0.
1164     * @param minDataSize  Minimum data size in buffer for report; ignore if 0.
1165     * @param ringName     Name of the ring for which data collection is to start.
1166     * @return true for success, false otherwise.
1167     */
1168    public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
1169            int minDataSize, String ringName){
1170        return mWifiVendorHal.startLoggingRingBuffer(
1171                verboseLevel, flags, maxInterval, minDataSize, ringName);
1172    }
1173
1174    /**
1175     * Logger features exposed.
1176     * This is a no-op now, will always return -1.
1177     *
1178     * @return true on success, false otherwise.
1179     */
1180    public int getSupportedLoggerFeatureSet() {
1181        return mWifiVendorHal.getSupportedLoggerFeatureSet();
1182    }
1183
1184    /**
1185     * Stops all logging and resets the logger callback.
1186     * This stops both the alerts and ring buffer data collection.
1187     * @return true on success, false otherwise.
1188     */
1189    public boolean resetLogHandler() {
1190        return mWifiVendorHal.resetLogHandler();
1191    }
1192
1193    /**
1194     * Vendor-provided wifi driver version string
1195     *
1196     * @return String returned from the HAL.
1197     */
1198    public String getDriverVersion() {
1199        return mWifiVendorHal.getDriverVersion();
1200    }
1201
1202    /**
1203     * Vendor-provided wifi firmware version string
1204     *
1205     * @return String returned from the HAL.
1206     */
1207    public String getFirmwareVersion() {
1208        return mWifiVendorHal.getFirmwareVersion();
1209    }
1210
1211    public static class RingBufferStatus{
1212        String name;
1213        int flag;
1214        int ringBufferId;
1215        int ringBufferByteSize;
1216        int verboseLevel;
1217        int writtenBytes;
1218        int readBytes;
1219        int writtenRecords;
1220
1221        // Bit masks for interpreting |flag|
1222        public static final int HAS_BINARY_ENTRIES = (1 << 0);
1223        public static final int HAS_ASCII_ENTRIES = (1 << 1);
1224        public static final int HAS_PER_PACKET_ENTRIES = (1 << 2);
1225
1226        @Override
1227        public String toString() {
1228            return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
1229                    " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
1230                    " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
1231                    " writtenRecords: " + writtenRecords;
1232        }
1233    }
1234
1235    /**
1236     * API to get the status of all ring buffers supported by driver
1237     */
1238    public RingBufferStatus[] getRingBufferStatus() {
1239        return mWifiVendorHal.getRingBufferStatus();
1240    }
1241
1242    /**
1243     * Indicates to driver that all the data has to be uploaded urgently
1244     *
1245     * @param ringName Name of the ring buffer requested.
1246     * @return true on success, false otherwise.
1247     */
1248    public boolean getRingBufferData(String ringName) {
1249        return mWifiVendorHal.getRingBufferData(ringName);
1250    }
1251
1252    /**
1253     * Request vendor debug info from the firmware
1254     *
1255     * @return Raw data obtained from the HAL.
1256     */
1257    public byte[] getFwMemoryDump() {
1258        return mWifiVendorHal.getFwMemoryDump();
1259    }
1260
1261    /**
1262     * Request vendor debug info from the driver
1263     *
1264     * @return Raw data obtained from the HAL.
1265     */
1266    public byte[] getDriverStateDump() {
1267        return mWifiVendorHal.getDriverStateDump();
1268    }
1269
1270    //---------------------------------------------------------------------------------
1271    /* Packet fate API */
1272
1273    @Immutable
1274    abstract static class FateReport {
1275        final static int USEC_PER_MSEC = 1000;
1276        // The driver timestamp is a 32-bit counter, in microseconds. This field holds the
1277        // maximal value of a driver timestamp in milliseconds.
1278        final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000);
1279        final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
1280
1281        final byte mFate;
1282        final long mDriverTimestampUSec;
1283        final byte mFrameType;
1284        final byte[] mFrameBytes;
1285        final long mEstimatedWallclockMSec;
1286
1287        FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1288            mFate = fate;
1289            mDriverTimestampUSec = driverTimestampUSec;
1290            mEstimatedWallclockMSec =
1291                    convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec);
1292            mFrameType = frameType;
1293            mFrameBytes = frameBytes;
1294        }
1295
1296        public String toTableRowString() {
1297            StringWriter sw = new StringWriter();
1298            PrintWriter pw = new PrintWriter(sw);
1299            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1300            dateFormatter.setTimeZone(TimeZone.getDefault());
1301            pw.format("%-15s  %12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1302                    mDriverTimestampUSec,
1303                    dateFormatter.format(new Date(mEstimatedWallclockMSec)),
1304                    directionToString(), fateToString(), parser.mMostSpecificProtocolString,
1305                    parser.mTypeString, parser.mResultString);
1306            return sw.toString();
1307        }
1308
1309        public String toVerboseStringWithPiiAllowed() {
1310            StringWriter sw = new StringWriter();
1311            PrintWriter pw = new PrintWriter(sw);
1312            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1313            pw.format("Frame direction: %s\n", directionToString());
1314            pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
1315            pw.format("Frame fate: %s\n", fateToString());
1316            pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
1317            pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
1318            pw.format("Frame protocol type: %s\n", parser.mTypeString);
1319            pw.format("Frame length: %d\n", mFrameBytes.length);
1320            pw.append("Frame bytes");
1321            pw.append(HexDump.dumpHexString(mFrameBytes));  // potentially contains PII
1322            pw.append("\n");
1323            return sw.toString();
1324        }
1325
1326        /* Returns a header to match the output of toTableRowString(). */
1327        public static String getTableHeader() {
1328            StringWriter sw = new StringWriter();
1329            PrintWriter pw = new PrintWriter(sw);
1330            pw.format("\n%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1331                    "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result");
1332            pw.format("%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1333                    "---------", "--------", "---------", "----", "--------", "----", "------");
1334            return sw.toString();
1335        }
1336
1337        protected abstract String directionToString();
1338
1339        protected abstract String fateToString();
1340
1341        private static String frameTypeToString(byte frameType) {
1342            switch (frameType) {
1343                case WifiLoggerHal.FRAME_TYPE_UNKNOWN:
1344                    return "unknown";
1345                case WifiLoggerHal.FRAME_TYPE_ETHERNET_II:
1346                    return "data";
1347                case WifiLoggerHal.FRAME_TYPE_80211_MGMT:
1348                    return "802.11 management";
1349                default:
1350                    return Byte.toString(frameType);
1351            }
1352        }
1353
1354        /**
1355         * Converts a driver timestamp to a wallclock time, based on the current
1356         * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of
1357         * microseconds, with the same base as BOOTTIME.
1358         */
1359        private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) {
1360            final long wallclockMillisNow = System.currentTimeMillis();
1361            final long boottimeMillisNow = SystemClock.elapsedRealtime();
1362            final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC;
1363
1364            long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC;
1365            if (boottimeTimestampMillis < driverTimestampMillis) {
1366                // The 32-bit microsecond count has wrapped between the time that the driver
1367                // recorded the packet, and the call to this function. Adjust the BOOTTIME
1368                // timestamp, to compensate.
1369                //
1370                // Note that overflow is not a concern here, since the result is less than
1371                // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above,
1372                // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since
1373                // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit
1374                // within a long.
1375                boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC;
1376            }
1377
1378            final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis;
1379            return wallclockMillisNow - millisSincePacketTimestamp;
1380        }
1381    }
1382
1383    /**
1384     * Represents the fate information for one outbound packet.
1385     */
1386    @Immutable
1387    public static final class TxFateReport extends FateReport {
1388        TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1389            super(fate, driverTimestampUSec, frameType, frameBytes);
1390        }
1391
1392        @Override
1393        protected String directionToString() {
1394            return "TX";
1395        }
1396
1397        @Override
1398        protected String fateToString() {
1399            switch (mFate) {
1400                case WifiLoggerHal.TX_PKT_FATE_ACKED:
1401                    return "acked";
1402                case WifiLoggerHal.TX_PKT_FATE_SENT:
1403                    return "sent";
1404                case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED:
1405                    return "firmware queued";
1406                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID:
1407                    return "firmware dropped (invalid frame)";
1408                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS:
1409                    return "firmware dropped (no bufs)";
1410                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER:
1411                    return "firmware dropped (other)";
1412                case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED:
1413                    return "driver queued";
1414                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID:
1415                    return "driver dropped (invalid frame)";
1416                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS:
1417                    return "driver dropped (no bufs)";
1418                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER:
1419                    return "driver dropped (other)";
1420                default:
1421                    return Byte.toString(mFate);
1422            }
1423        }
1424    }
1425
1426    /**
1427     * Represents the fate information for one inbound packet.
1428     */
1429    @Immutable
1430    public static final class RxFateReport extends FateReport {
1431        RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1432            super(fate, driverTimestampUSec, frameType, frameBytes);
1433        }
1434
1435        @Override
1436        protected String directionToString() {
1437            return "RX";
1438        }
1439
1440        @Override
1441        protected String fateToString() {
1442            switch (mFate) {
1443                case WifiLoggerHal.RX_PKT_FATE_SUCCESS:
1444                    return "success";
1445                case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED:
1446                    return "firmware queued";
1447                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER:
1448                    return "firmware dropped (filter)";
1449                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID:
1450                    return "firmware dropped (invalid frame)";
1451                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS:
1452                    return "firmware dropped (no bufs)";
1453                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER:
1454                    return "firmware dropped (other)";
1455                case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED:
1456                    return "driver queued";
1457                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER:
1458                    return "driver dropped (filter)";
1459                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID:
1460                    return "driver dropped (invalid frame)";
1461                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS:
1462                    return "driver dropped (no bufs)";
1463                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER:
1464                    return "driver dropped (other)";
1465                default:
1466                    return Byte.toString(mFate);
1467            }
1468        }
1469    }
1470
1471    /**
1472     * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started.
1473     *
1474     * @return true for success, false otherwise.
1475     */
1476    public boolean startPktFateMonitoring() {
1477        return mWifiVendorHal.startPktFateMonitoring();
1478    }
1479
1480    /**
1481     * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started.
1482     *
1483     * @return true for success, false otherwise.
1484     */
1485    public boolean getTxPktFates(TxFateReport[] reportBufs) {
1486        return mWifiVendorHal.getTxPktFates(reportBufs);
1487    }
1488
1489    /**
1490     * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started.
1491     */
1492    public boolean getRxPktFates(RxFateReport[] reportBufs) {
1493        return mWifiVendorHal.getRxPktFates(reportBufs);
1494    }
1495
1496    /**
1497     * Set the PNO settings & the network list in HAL to start PNO.
1498     * @param settings PNO settings and network list.
1499     * @param eventHandler Handler to receive notifications back during PNO scan.
1500     * @return true if success, false otherwise
1501     */
1502    public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) {
1503        Log.e(mTAG, "setPnoList not supported");
1504        return false;
1505    }
1506
1507    /**
1508     * Reset the PNO settings in HAL to stop PNO.
1509     * @return true if success, false otherwise
1510     */
1511    public boolean resetPnoList() {
1512        Log.e(mTAG, "resetPnoList not supported");
1513        return false;
1514    }
1515
1516    /**
1517     * Start sending the specified keep alive packets periodically.
1518     *
1519     * @param slot Integer used to identify each request.
1520     * @param keepAlivePacket Raw packet contents to send.
1521     * @param period Period to use for sending these packets.
1522     * @return 0 for success, -1 for error
1523     */
1524    public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket,
1525                                           int period) {
1526        String[] macAddrStr = getMacAddress().split(":");
1527        byte[] srcMac = new byte[6];
1528        for (int i = 0; i < 6; i++) {
1529            Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
1530            srcMac[i] = hexVal.byteValue();
1531        }
1532        return mWifiVendorHal.startSendingOffloadedPacket(
1533                slot, srcMac, keepAlivePacket, period);
1534    }
1535
1536    /**
1537     * Stop sending the specified keep alive packets.
1538     *
1539     * @param slot id - same as startSendingOffloadedPacket call.
1540     * @return 0 for success, -1 for error
1541     */
1542    public int stopSendingOffloadedPacket(int slot) {
1543        return mWifiVendorHal.stopSendingOffloadedPacket(slot);
1544    }
1545
1546    public static interface WifiRssiEventHandler {
1547        void onRssiThresholdBreached(byte curRssi);
1548    }
1549
1550    /**
1551     * Start RSSI monitoring on the currently connected access point.
1552     *
1553     * @param maxRssi          Maximum RSSI threshold.
1554     * @param minRssi          Minimum RSSI threshold.
1555     * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
1556     * @return 0 for success, -1 for failure
1557     */
1558    public int startRssiMonitoring(byte maxRssi, byte minRssi,
1559                                   WifiRssiEventHandler rssiEventHandler) {
1560        return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler);
1561    }
1562
1563    public int stopRssiMonitoring() {
1564        return mWifiVendorHal.stopRssiMonitoring();
1565    }
1566
1567    /**
1568     * Fetch the host wakeup reasons stats from wlan driver.
1569     *
1570     * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
1571     */
1572    public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
1573        return mWifiVendorHal.getWlanWakeReasonCount();
1574    }
1575
1576    /**
1577     * Enable/Disable Neighbour discovery offload functionality in the firmware.
1578     *
1579     * @param enabled true to enable, false to disable.
1580     * @return true for success, false otherwise.
1581     */
1582    public boolean configureNeighborDiscoveryOffload(boolean enabled) {
1583        return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled);
1584    }
1585
1586    // Firmware roaming control.
1587
1588    /**
1589     * Class to retrieve firmware roaming capability parameters.
1590     */
1591    public static class RoamingCapabilities {
1592        public int  maxBlacklistSize;
1593        public int  maxWhitelistSize;
1594    }
1595
1596    /**
1597     * Query the firmware roaming capabilities.
1598     * @return true for success, false otherwise.
1599     */
1600    public boolean getRoamingCapabilities(RoamingCapabilities capabilities) {
1601        return mWifiVendorHal.getRoamingCapabilities(capabilities);
1602    }
1603
1604    /**
1605     * Macros for controlling firmware roaming.
1606     */
1607    public static final int DISABLE_FIRMWARE_ROAMING = 0;
1608    public static final int ENABLE_FIRMWARE_ROAMING = 1;
1609
1610    /**
1611     * Enable/disable firmware roaming.
1612     *
1613     * @return error code returned from HAL.
1614     */
1615    public int enableFirmwareRoaming(int state) {
1616        return mWifiVendorHal.enableFirmwareRoaming(state);
1617    }
1618
1619    /**
1620     * Class for specifying the roaming configurations.
1621     */
1622    public static class RoamingConfig {
1623        public ArrayList<String> blacklistBssids;
1624        public ArrayList<String> whitelistSsids;
1625    }
1626
1627    /**
1628     * Set firmware roaming configurations.
1629     */
1630    public boolean configureRoaming(RoamingConfig config) {
1631        Log.d(mTAG, "configureRoaming ");
1632        return mWifiVendorHal.configureRoaming(config);
1633    }
1634
1635    /**
1636     * Reset firmware roaming configuration.
1637     */
1638    public boolean resetRoamingConfiguration() {
1639        // Pass in an empty RoamingConfig object which translates to zero size
1640        // blacklist and whitelist to reset the firmware roaming configuration.
1641        return mWifiVendorHal.configureRoaming(new RoamingConfig());
1642    }
1643
1644    /********************************************************
1645     * JNI operations
1646     ********************************************************/
1647    /* Register native functions */
1648    static {
1649        /* Native functions are defined in libwifi-service.so */
1650        System.loadLibrary("wifi-service");
1651        registerNatives();
1652    }
1653
1654    private static native int registerNatives();
1655    /* kernel logging support */
1656    private static native byte[] readKernelLogNative();
1657
1658    /**
1659     * Fetches the latest kernel logs.
1660     */
1661    public synchronized String readKernelLog() {
1662        byte[] bytes = readKernelLogNative();
1663        if (bytes != null) {
1664            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
1665            try {
1666                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
1667                return decoded.toString();
1668            } catch (CharacterCodingException cce) {
1669                return new String(bytes, StandardCharsets.ISO_8859_1);
1670            }
1671        } else {
1672            return "*** failed to read kernel log ***";
1673        }
1674    }
1675}
1676