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