WifiVendorHal.java revision b4659e143a1a0b27e4f4ca82e8428863b8c41324
1/*
2 * Copyright (C) 2017 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 */
16package com.android.server.wifi;
17
18import android.annotation.Nullable;
19import android.hardware.wifi.V1_0.IWifiApIface;
20import android.hardware.wifi.V1_0.IWifiChip;
21import android.hardware.wifi.V1_0.IWifiIface;
22import android.hardware.wifi.V1_0.IWifiRttController;
23import android.hardware.wifi.V1_0.IWifiStaIface;
24import android.hardware.wifi.V1_0.StaRoamingConfig;
25import android.hardware.wifi.V1_0.StaRoamingState;
26import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats;
27import android.hardware.wifi.V1_0.WifiStatus;
28import android.hardware.wifi.V1_0.WifiStatusCode;
29import android.net.apf.ApfCapabilities;
30import android.net.wifi.RttManager;
31import android.net.wifi.RttManager.ResponderConfig;
32import android.net.wifi.WifiInfo;
33import android.net.wifi.WifiLinkLayerStats;
34import android.net.wifi.WifiScanner;
35import android.net.wifi.WifiWakeReasonAndCounts;
36import android.os.HandlerThread;
37import android.os.RemoteException;
38import android.util.Log;
39import android.util.MutableBoolean;
40
41import com.android.internal.annotations.VisibleForTesting;
42import com.android.server.connectivity.KeepalivePacketData;
43
44/**
45 * Vendor HAL via HIDL
46 */
47public class WifiVendorHal {
48
49    private static final String TAG = "WifiVendorHal";
50
51    // Vendor HAL HIDL interface objects.
52    private IWifiChip mIWifiChip;
53    private IWifiStaIface mIWifiStaIface;
54    private IWifiApIface mIWifiApIface;
55    private IWifiRttController mIWifiRttController;
56    private final HalDeviceManager mHalDeviceManager;
57    private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks;
58    private final HandlerThread mWifiStateMachineHandlerThread;
59
60    public WifiVendorHal(HalDeviceManager halDeviceManager,
61                         HandlerThread wifiStateMachineHandlerThread) {
62        mHalDeviceManager = halDeviceManager;
63        mWifiStateMachineHandlerThread = wifiStateMachineHandlerThread;
64        mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener();
65    }
66
67    // TODO(mplass): figure out where we need locking in hidl world. b/33383725
68    public static final Object sLock = new Object();
69
70    private void handleRemoteException(RemoteException e) {
71        kilroy();
72        Log.e(TAG, "RemoteException in HIDL call " + e);
73    }
74
75    private void noteHidlError(WifiStatus status, String culprit) {
76        kilroy();
77        Log.e(TAG, "Error in " + culprit + " code: " + status.code
78                + " (" + status.description + ")");
79    }
80
81    /**
82     * Initialize the Hal device manager and register for status callbacks.
83     * @return
84     */
85    public boolean initialize() {
86        mHalDeviceManager.initialize();
87        mHalDeviceManager.registerStatusListener(
88                mHalDeviceManagerStatusCallbacks, mWifiStateMachineHandlerThread.getLooper());
89        return true;
90    }
91
92    /**
93     * Bring up the HIDL Vendor HAL and configure for STA mode or AP mode.
94     *
95     * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
96     */
97    public boolean startVendorHal(boolean isStaMode) {
98        if (!mHalDeviceManager.start()) {
99            Log.e(TAG, "Failed to start the vendor HAL");
100            return false;
101        }
102        if (isStaMode) {
103            mIWifiStaIface = mHalDeviceManager.createStaIface(null, null);
104            if (mIWifiStaIface == null) {
105                Log.e(TAG, "Failed to create STA Iface");
106                return false;
107            }
108        } else {
109            mIWifiApIface = mHalDeviceManager.createApIface(null, null);
110            if (mIWifiApIface == null) {
111                Log.e(TAG, "Failed to create AP Iface");
112                return false;
113            }
114        }
115        IWifiIface iface = (IWifiIface) (mIWifiStaIface != null ? mIWifiStaIface : mIWifiApIface);
116        mIWifiChip = mHalDeviceManager.getChip(iface);
117        if (mIWifiStaIface == null) {
118            Log.e(TAG, "Failed to get the chip created for the Iface");
119            return false;
120        }
121        return true;
122    }
123
124    /**
125     * Stops the HAL
126     */
127    public void stopVendorHal() {
128        mHalDeviceManager.stop();
129    }
130
131    /**
132     * Tests whether the HAL is running or not
133     */
134    public boolean isHalStarted() {
135        return (mIWifiStaIface != null || mIWifiApIface != null);
136    }
137
138    /**
139     * Gets the scan capabilities
140     *
141     * @param capabilities object to be filled in
142     * @return true for success. false for failure
143     */
144    public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) {
145        kilroy();
146        throw new UnsupportedOperationException();
147    }
148
149    /**
150     * to be implemented
151     */
152    public boolean startScan(WifiNative.ScanSettings settings,
153                             WifiNative.ScanEventHandler eventHandler) {
154        kilroy();
155        throw new UnsupportedOperationException();
156    }
157
158    /**
159     * to be implemented
160     */
161    public void stopScan() {
162        kilroy();
163        throw new UnsupportedOperationException();
164    }
165
166    /**
167     * to be implemented
168     */
169    public void pauseScan() {
170        kilroy();
171        throw new UnsupportedOperationException();
172    }
173
174    /**
175     * to be implemented
176     */
177    public void restartScan() {
178        kilroy();
179        throw new UnsupportedOperationException();
180    }
181
182    /**
183     * to be implemented
184     */
185    public WifiScanner.ScanData[] getScanResults(boolean flush) {
186        kilroy();
187        throw new UnsupportedOperationException();
188    }
189
190    /**
191     * Get the link layer statistics
192     *
193     * @param iface is the name of the wifi interface (checked for null, otherwise ignored)
194     * @return the statistics, or null if unable to do so
195     */
196    public WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
197        kilroy();
198        throw new UnsupportedOperationException();
199    }
200
201    /**
202     * Enable link layer stats collection
203     *
204     * @param iface  is the name of the wifi interface (checked for null, otherwise ignored)
205     * @param enable must be 1
206     */
207    public void setWifiLinkLayerStats(String iface, int enable) {
208        kilroy();
209        throw new UnsupportedOperationException();
210    }
211
212    /**
213     * Get the supported features
214     *
215     * @return bitmask defined by WifiManager.WIFI_FEATURE_*
216     */
217    public int getSupportedFeatureSet() {
218        kilroy();
219        throw new UnsupportedOperationException();
220    }
221
222    /* RTT related commands/events */
223
224    /**
225     * Starts a new rtt request
226     *
227     * @param params
228     * @param handler
229     * @return success indication
230     */
231    public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) {
232        kilroy();
233        throw new UnsupportedOperationException();
234    }
235
236    /**
237     * Cancels an outstanding rtt request
238     *
239     * @param params
240     * @return true if there was an outstanding request and it was successfully cancelled
241     */
242    public boolean cancelRtt(RttManager.RttParams[] params) {
243        kilroy();
244        throw new UnsupportedOperationException();
245    }
246
247    /**
248     * Enables RTT responder role on the device.
249     *
250     * @return {@link ResponderConfig} if the responder role is successfully enabled,
251     * {@code null} otherwise.
252     */
253    @Nullable
254    public ResponderConfig enableRttResponder(int timeoutSeconds) {
255        kilroy();
256        throw new UnsupportedOperationException();
257    }
258
259    /**
260     * Disables RTT responder role.
261     *
262     * @return {@code true} if responder role is successfully disabled,
263     * {@code false} otherwise.
264     */
265    public boolean disableRttResponder() {
266        kilroy();
267        throw new UnsupportedOperationException();
268    }
269
270    /**
271     * not supported
272     */
273    public boolean setScanningMacOui(byte[] oui) {
274        kilroy();
275        throw new UnsupportedOperationException();
276    }
277
278    /**
279     * not supported
280     */
281    public int[] getChannelsForBand(int band) {
282        kilroy();
283        throw new UnsupportedOperationException();
284    }
285
286    /**
287     * not supported
288     */
289    public boolean isGetChannelsForBandSupported() {
290        kilroy();
291        throw new UnsupportedOperationException();
292    }
293
294    /**
295     * Set DFS - actually, this is always on.
296     *
297     * @param dfsOn
298     * @return success indication
299     */
300    public boolean setDfsFlag(boolean dfsOn) {
301        kilroy();
302        throw new UnsupportedOperationException();
303    }
304
305    /**
306     * RTT (Round Trip Time) measurement capabilities of the device.
307     */
308    public RttManager.RttCapabilities getRttCapabilities() {
309        kilroy();
310        throw new UnsupportedOperationException();
311    }
312
313    /**
314     * Get the APF (Android Packet Filter) capabilities of the device
315     */
316    public ApfCapabilities getApfCapabilities() {
317        kilroy();
318        throw new UnsupportedOperationException();
319    }
320
321    private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0);
322
323    /**
324     * Installs an APF program on this iface, replacing an existing
325     * program if present.
326     */
327    public boolean installPacketFilter(byte[] filter) {
328        kilroy();
329        throw new UnsupportedOperationException();
330    }
331
332
333    /**
334     * to be implemented
335     */
336    public boolean setCountryCodeHal(String countryCode) {
337        kilroy();
338        throw new UnsupportedOperationException();
339    }
340
341    /**
342     * not to be implemented
343     */
344    public boolean enableDisableTdls(boolean enable, String macAdd,
345                                     WifiNative.TdlsEventHandler tdlsCallBack) {
346        kilroy();
347        throw new UnsupportedOperationException();
348    }
349
350    /**
351     * not to be implemented
352     */
353    public WifiNative.TdlsStatus getTdlsStatus(String macAdd) {
354        kilroy();
355        throw new UnsupportedOperationException();
356    }
357
358    /**
359     * not to be implemented
360     */
361    public WifiNative.TdlsCapabilities getTdlsCapabilities() {
362        kilroy();
363        throw new UnsupportedOperationException();
364    }
365
366    /**
367     * to be implemented
368     */
369    public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) {
370        kilroy();
371        throw new UnsupportedOperationException();
372    }
373
374    /**
375     * Control debug data collection
376     *
377     * @param verboseLevel       0 to 3, inclusive. 0 stops logging.
378     * @param flags              Ignored.
379     * @param maxIntervalInSec   Maximum interval between reports; ignore if 0.
380     * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0.
381     * @param ringName           Name of the ring for which data collection is to start.
382     * @return true for success
383     */
384    public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec,
385                                          int minDataSizeInBytes, String ringName) {
386        kilroy();
387        throw new UnsupportedOperationException();
388    }
389
390    /**
391     * Pointlessly fail
392     *
393     * @return -1
394     */
395    public int getSupportedLoggerFeatureSet() {
396        return -1;
397    }
398
399    /**
400     * to be implemented
401     */
402    public boolean resetLogHandler() {
403        kilroy();
404        throw new UnsupportedOperationException();
405    }
406
407    private String mDriverDescription;
408
409    /**
410     * Vendor-provided wifi driver version string
411     */
412    public String getDriverVersion() {
413        kilroy();
414        throw new UnsupportedOperationException();
415    }
416
417    private String mFirmwareDescription;
418
419    /**
420     * Vendor-provided wifi firmware version string
421     */
422    public String getFirmwareVersion() {
423        kilroy();
424        throw new UnsupportedOperationException();
425    }
426
427    /**
428     * API to get the status of all ring buffers supported by driver
429     */
430    public WifiNative.RingBufferStatus[] getRingBufferStatus() {
431        kilroy();
432        throw new UnsupportedOperationException();
433    }
434
435    /**
436     * indicates to driver that all
437     * the data has to be uploaded urgently
438     */
439    public boolean getRingBufferData(String ringName) {
440        kilroy();
441        throw new UnsupportedOperationException();
442    }
443
444    /**
445     * to be implemented via mIWifiChip.requestFirmwareDebugDump
446     */
447    public byte[] getFwMemoryDump() {
448        kilroy();
449        throw new UnsupportedOperationException();
450    }
451
452    /**
453     * Request vendor debug info from the driver
454     */
455    public byte[] getDriverStateDump() {
456        kilroy();
457        throw new UnsupportedOperationException();
458    }
459
460    /**
461     * Start packet fate monitoring
462     * <p>
463     * Once started, monitoring remains active until HAL is unloaded.
464     *
465     * @return true for success
466     */
467    public boolean startPktFateMonitoring() {
468        kilroy();
469        throw new UnsupportedOperationException();
470    }
471
472    /**
473     * Retrieve fates of outbound packets
474     * <p>
475     * Reports the outbound frames for the most recent association (space allowing).
476     *
477     * @param reportBufs
478     * @return true for success
479     */
480    public boolean getTxPktFates(WifiNative.TxFateReport[] reportBufs) {
481        kilroy();
482        throw new UnsupportedOperationException();
483    }
484
485    /**
486     * Retrieve fates of inbound packets
487     * <p>
488     * Reports the inbound frames for the most recent association (space allowing).
489     *
490     * @param reportBufs
491     * @return true for success
492     */
493    public boolean getRxPktFates(WifiNative.RxFateReport[] reportBufs) {
494        kilroy();
495        throw new UnsupportedOperationException();
496    }
497
498    /**
499     * Start sending the specified keep alive packets periodically.
500     *
501     * @return 0 for success, -1 for error
502     */
503    public int startSendingOffloadedPacket(
504            int slot, KeepalivePacketData keepAlivePacket, int periodInMs) {
505        kilroy();
506        throw new UnsupportedOperationException();
507    }
508
509    /**
510     * Stop sending the specified keep alive packets.
511     *
512     * @param slot id - same as startSendingOffloadedPacket call.
513     * @return 0 for success, -1 for error
514     */
515    public int stopSendingOffloadedPacket(int slot) {
516        kilroy();
517        throw new UnsupportedOperationException();
518    }
519
520    /**
521     * Start RSSI monitoring on the currently connected access point.
522     *
523     * @param maxRssi          Maximum RSSI threshold.
524     * @param minRssi          Minimum RSSI threshold.
525     * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
526     * @return 0 for success, -1 for failure
527     */
528    public int startRssiMonitoring(byte maxRssi, byte minRssi,
529                                   WifiNative.WifiRssiEventHandler rssiEventHandler) {
530        kilroy();
531        throw new UnsupportedOperationException();
532    }
533
534    /**
535     * Stop RSSI monitoring
536     *
537     * @return 0 for success, -1 for failure
538     */
539    public int stopRssiMonitoring() {
540        kilroy();
541        throw new UnsupportedOperationException();
542    }
543
544    private WifiDebugHostWakeReasonStats mWifiDebugHostWakeReasonStats;
545
546    /**
547     * Fetch the host wakeup reasons stats from wlan driver.
548     *
549     * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
550     */
551    public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
552        kilroy();
553        throw new UnsupportedOperationException();
554    }
555
556    /**
557     * Enable/Disable Neighbour discovery offload functionality in the firmware.
558     */
559    public boolean configureNeighborDiscoveryOffload(boolean enabled) {
560        kilroy();
561        throw new UnsupportedOperationException();
562    }
563
564    // Firmware roaming control.
565
566    /**
567     * Query the firmware roaming capabilities.
568     *
569     * @param capabilities object to be filled in
570     * @return true for success; false for failure
571     */
572    public boolean getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities) {
573        kilroy();
574        synchronized (sLock) {
575            kilroy();
576            try {
577                kilroy();
578                if (!isHalStarted()) return false;
579                MutableBoolean ok = new MutableBoolean(false);
580                WifiNative.RoamingCapabilities out = capabilities;
581                mIWifiStaIface.getRoamingCapabilities((status, cap) -> {
582                    kilroy();
583                    if (status.code != WifiStatusCode.SUCCESS) return;
584                    out.maxBlacklistSize = cap.maxBlacklistSize;
585                    out.maxWhitelistSize = cap.maxWhitelistSize;
586                    ok.value = true;
587                });
588                return ok.value;
589            } catch (RemoteException e) {
590                kilroy();
591                handleRemoteException(e);
592                return false;
593            }
594        }
595    }
596
597    /**
598     * Enable/disable firmware roaming.
599     *
600     * @param state the intended roaming state
601     * @return SUCCESS, FAILURE, or BUSY
602     */
603    public int enableFirmwareRoaming(int state) {
604        kilroy();
605        synchronized (sLock) {
606            kilroy();
607            try {
608                kilroy();
609                if (!isHalStarted()) return WifiStatusCode.ERROR_NOT_STARTED;
610                byte val;
611                switch (state) {
612                    case WifiNative.DISABLE_FIRMWARE_ROAMING:
613                        val = StaRoamingState.DISABLED;
614                        break;
615                    case WifiNative.ENABLE_FIRMWARE_ROAMING:
616                        val = StaRoamingState.ENABLED;
617                        break;
618                    default:
619                        Log.e(TAG, "enableFirmwareRoaming invalid argument " + state);
620                        return WifiStatusCode.ERROR_INVALID_ARGS;
621                }
622
623                kilroy();
624                WifiStatus status = mIWifiStaIface.setRoamingState(val);
625                Log.d(TAG, "setRoamingState returned " + status.code);
626                return status.code;
627            } catch (RemoteException e) {
628                kilroy();
629                handleRemoteException(e);
630                return WifiStatusCode.ERROR_UNKNOWN;
631            }
632        }
633    }
634
635    /**
636     * Set firmware roaming configurations.
637     *
638     * @param config new roaming configuration object
639     * @return true for success; false for failure
640     */
641    public boolean configureRoaming(WifiNative.RoamingConfig config) {
642        kilroy();
643        synchronized (sLock) {
644            kilroy();
645            try {
646                kilroy();
647                if (!isHalStarted()) return false;
648                StaRoamingConfig roamingConfig = new StaRoamingConfig();
649
650                // parse the blacklist BSSIDs if any
651                if (config.blacklistBssids != null) {
652                    kilroy();
653                    for (String bssid : config.blacklistBssids) {
654                        String unquotedMacStr = WifiInfo.removeDoubleQuotes(bssid);
655                        byte[] mac = new byte[6];
656                        parseUnquotedMacStrToByteArray(unquotedMacStr, mac);
657                        roamingConfig.bssidBlacklist.add(mac);
658                    }
659                }
660
661                // parse the whitelist SSIDs if any
662                if (config.whitelistSsids != null) {
663                    kilroy();
664                    for (String ssidStr : config.whitelistSsids) {
665                        String unquotedSsidStr = WifiInfo.removeDoubleQuotes(ssidStr);
666
667                        int len = unquotedSsidStr.length();
668                        if (len > 32) {
669                            Log.e(TAG, "configureRoaming: skip invalid SSID " + unquotedSsidStr);
670                            continue;
671                        }
672                        byte[] ssid = new byte[len];
673                        for (int i = 0; i < len; i++) {
674                            ssid[i] = (byte) unquotedSsidStr.charAt(i);
675                        }
676                        roamingConfig.ssidWhitelist.add(ssid);
677                    }
678                }
679
680                kilroy();
681                WifiStatus status = mIWifiStaIface.configureRoaming(roamingConfig);
682                if (status.code != WifiStatusCode.SUCCESS) {
683                    kilroy();
684                    noteHidlError(status, "configureRoaming");
685                    return false;
686                }
687            } catch (RemoteException e) {
688                kilroy();
689                handleRemoteException(e);
690                return false;
691            }
692            kilroy();
693            return true;
694        }
695    }
696
697    /**
698     * Helper function that parses unquoted MAC address string to a byte array
699     *
700     * @param macWithColons mac address string without double quotes
701     * @param mac an array of 6 bytes to receive the parsed mac address
702     */
703    @VisibleForTesting
704    void parseUnquotedMacStrToByteArray(String macWithColons, byte[] mac) {
705        String[] macAddrStr = macWithColons.split(":");
706        for (int i = 0; i < 6; i++) {
707            Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
708            mac[i] = hexVal.byteValue();
709        }
710    }
711
712    StackTraceElement[] mTrace;
713
714    private void kilroy() {
715        Thread cur = Thread.currentThread();
716        mTrace = cur.getStackTrace();
717        StackTraceElement s = mTrace[3];
718        String name = s.getMethodName();
719        if (name.contains("lambda$")) {
720            // Try to find a friendlier method name
721            String myFile = s.getFileName();
722            if (myFile != null) {
723                for (int i = 4; i < mTrace.length; i++) {
724                    if (myFile.equals(mTrace[i].getFileName())) {
725                        name = mTrace[i].getMethodName();
726                        break;
727                    }
728                }
729            }
730        }
731        Log.e(TAG, "th " + cur.getId() + " line " + s.getLineNumber() + " " + name);
732    }
733
734    /**
735     * Hal Device Manager callbacks.
736     */
737    public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener {
738        @Override
739        public void onStatusChanged() {
740            Log.i(TAG, "Device Manager onStatusChanged. isReady(): " + mHalDeviceManager.isReady()
741                    + "isStarted(): " + mHalDeviceManager.isStarted());
742            // Reset all our cached handles.
743            if (!mHalDeviceManager.isReady() || !mHalDeviceManager.isStarted())  {
744                mIWifiChip = null;
745                mIWifiStaIface = null;
746                mIWifiApIface = null;
747                mIWifiRttController = null;
748                mDriverDescription = null;
749                mFirmwareDescription = null;
750            }
751        }
752    }
753}
754