• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 package com.android.server.wifi.hal;
18 
19 import static android.net.wifi.WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.content.Context;
24 import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback;
25 import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask;
26 import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters;
27 import android.hardware.wifi.V1_0.StaBackgroundScanParameters;
28 import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats;
29 import android.hardware.wifi.V1_0.StaLinkLayerRadioStats;
30 import android.hardware.wifi.V1_0.StaLinkLayerStats;
31 import android.hardware.wifi.V1_0.StaRoamingConfig;
32 import android.hardware.wifi.V1_0.StaRoamingState;
33 import android.hardware.wifi.V1_0.StaScanData;
34 import android.hardware.wifi.V1_0.StaScanDataFlagMask;
35 import android.hardware.wifi.V1_0.StaScanResult;
36 import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType;
37 import android.hardware.wifi.V1_0.WifiDebugRxPacketFate;
38 import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport;
39 import android.hardware.wifi.V1_0.WifiDebugTxPacketFate;
40 import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport;
41 import android.hardware.wifi.V1_0.WifiStatus;
42 import android.hardware.wifi.V1_0.WifiStatusCode;
43 import android.hardware.wifi.V1_5.WifiBand;
44 import android.net.MacAddress;
45 import android.net.apf.ApfCapabilities;
46 import android.net.wifi.ScanResult;
47 import android.net.wifi.WifiManager;
48 import android.net.wifi.WifiScanner;
49 import android.net.wifi.WifiSsid;
50 import android.os.RemoteException;
51 import android.util.Log;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.server.wifi.SsidTranslator;
55 import com.android.server.wifi.WifiLinkLayerStats;
56 import com.android.server.wifi.WifiLoggerHal;
57 import com.android.server.wifi.WifiNative;
58 import com.android.server.wifi.util.BitMask;
59 import com.android.server.wifi.util.GeneralUtil;
60 import com.android.server.wifi.util.NativeUtil;
61 import com.android.wifi.resources.R;
62 
63 import java.util.ArrayList;
64 import java.util.List;
65 import java.util.function.Supplier;
66 
67 
68 /**
69  * HIDL implementation of the IWifiStaIface interface.
70  */
71 public class WifiStaIfaceHidlImpl implements IWifiStaIface {
72     private static final String TAG = "WifiStaIfaceHidlImpl";
73     private android.hardware.wifi.V1_0.IWifiStaIface mWifiStaIface;
74     private String mIfaceName;
75     private IWifiStaIfaceEventCallback mHalCallback;
76     private WifiStaIface.Callback mFrameworkCallback;
77     private Context mContext;
78     private SsidTranslator mSsidTranslator;
79     private static final int DEFAULT_LINK = 0;
80     private static final int NUM_OF_LINKS = 1;
81     private final boolean mWifiLinkLayerAllRadiosStatsAggregationEnabled;
82 
WifiStaIfaceHidlImpl(@onNull android.hardware.wifi.V1_0.IWifiStaIface staIface, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)83     public WifiStaIfaceHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiStaIface staIface,
84             @NonNull Context context, @NonNull SsidTranslator ssidTranslator) {
85         mWifiStaIface = staIface;
86         mContext = context;
87         mSsidTranslator = ssidTranslator;
88         mHalCallback = new StaIfaceEventCallback();
89         mWifiLinkLayerAllRadiosStatsAggregationEnabled = mContext.getResources()
90                 .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled);
91     }
92 
93     /**
94      * See comments for {@link IWifiStaIface#registerFrameworkCallback(WifiStaIface.Callback)}
95      */
registerFrameworkCallback(WifiStaIface.Callback callback)96     public boolean registerFrameworkCallback(WifiStaIface.Callback callback) {
97         final String methodStr = "registerFrameworkCallback";
98         return validateAndCall(methodStr, false,
99                 () -> registerFrameworkCallbackInternal(methodStr, callback));
100     }
101 
102     /**
103      * See comments for {@link IWifiStaIface#getName()}
104      */
105     @Nullable
getName()106     public String getName() {
107         final String methodStr = "getName";
108         return validateAndCall(methodStr, null,
109                 () -> getNameInternal(methodStr));
110     }
111 
112     /**
113      * See comments for {@link IWifiStaIface#configureRoaming(List, List)}
114      */
configureRoaming(List<MacAddress> bssidBlocklist, List<byte[]> ssidAllowlist)115     public boolean configureRoaming(List<MacAddress> bssidBlocklist,
116             List<byte[]> ssidAllowlist) {
117         final String methodStr = "configureRoaming";
118         return validateAndCall(methodStr, false,
119                 () -> configureRoamingInternal(methodStr, bssidBlocklist, ssidAllowlist));
120     }
121 
122     /**
123      * See comments for {@link IWifiStaIface#enableLinkLayerStatsCollection(boolean)}
124      */
enableLinkLayerStatsCollection(boolean debug)125     public boolean enableLinkLayerStatsCollection(boolean debug) {
126         final String methodStr = "enableLinkLayerStatsCollection";
127         return validateAndCall(methodStr, false,
128                 () -> enableLinkLayerStatsCollectionInternal(methodStr, debug));
129     }
130 
131     /**
132      * See comments for {@link IWifiStaIface#enableNdOffload(boolean)}
133      */
enableNdOffload(boolean enable)134     public boolean enableNdOffload(boolean enable) {
135         final String methodStr = "enableNdOffload";
136         return validateAndCall(methodStr, false,
137                 () -> enableNdOffloadInternal(methodStr, enable));
138     }
139 
140     /**
141      * See comments for {@link IWifiStaIface#getApfPacketFilterCapabilities()}
142      */
getApfPacketFilterCapabilities()143     public ApfCapabilities getApfPacketFilterCapabilities() {
144         final String methodStr = "getApfPacketFilterCapabilities";
145         return validateAndCall(methodStr, new ApfCapabilities(0, 0, 0),
146                 () -> getApfPacketFilterCapabilitiesInternal(methodStr));
147     }
148 
149     /**
150      * See comments for {@link IWifiStaIface#getBackgroundScanCapabilities()}
151      */
152     @Nullable
getBackgroundScanCapabilities()153     public WifiNative.ScanCapabilities getBackgroundScanCapabilities() {
154         final String methodStr = "getBackgroundScanCapabilities";
155         return validateAndCall(methodStr, null,
156                 () -> getBackgroundScanCapabilitiesInternal(methodStr));
157     }
158 
159     /**
160      * See comments for {@link IWifiStaIface#getCapabilities()}
161      */
getCapabilities()162     public long getCapabilities() {
163         final String methodStr = "getCapabilities";
164         return validateAndCall(methodStr, 0L,
165                 () -> getCapabilitiesInternal(methodStr));
166     }
167 
168     /**
169      * See comments for {@link IWifiStaIface#getDebugRxPacketFates()}
170      */
getDebugRxPacketFates()171     public List<WifiNative.RxFateReport> getDebugRxPacketFates() {
172         final String methodStr = "getDebugRxPacketFates";
173         return validateAndCall(methodStr, new ArrayList<>(),
174                 () -> getDebugRxPacketFatesInternal(methodStr));
175     }
176 
177     /**
178      * See comments for {@link IWifiStaIface#getDebugTxPacketFates()}
179      */
getDebugTxPacketFates()180     public List<WifiNative.TxFateReport> getDebugTxPacketFates() {
181         final String methodStr = "getDebugTxPacketFates";
182         return validateAndCall(methodStr, new ArrayList<>(),
183                 () -> getDebugTxPacketFatesInternal(methodStr));
184     }
185 
186     /**
187      * See comments for {@link IWifiStaIface#getFactoryMacAddress()}
188      */
189     @Nullable
getFactoryMacAddress()190     public MacAddress getFactoryMacAddress() {
191         final String methodStr = "getFactoryMacAddress";
192         return validateAndCall(methodStr, null,
193                 () -> getFactoryMacAddressInternal(methodStr));
194     }
195 
196     /**
197      * See comments for {@link IWifiStaIface#getCachedScanData()}
198      */
199     @Nullable
getCachedScanData()200     public WifiScanner.ScanData getCachedScanData() {
201         Log.d(TAG, "getCachedScanData is not implemented by HIDL");
202         return null;
203     }
204 
205     /**
206      * See comments for {@link IWifiStaIface#getLinkLayerStats()}
207      */
208     @Nullable
getLinkLayerStats()209     public WifiLinkLayerStats getLinkLayerStats() {
210         final String methodStr = "getLinkLayerStats";
211         return validateAndCall(methodStr, null,
212                 () -> getLinkLayerStatsInternal(methodStr));
213     }
214 
215     /**
216      * See comments for {@link IWifiStaIface#getRoamingCapabilities()}
217      */
218     @Nullable
getRoamingCapabilities()219     public WifiNative.RoamingCapabilities getRoamingCapabilities() {
220         final String methodStr = "getRoamingCapabilities";
221         return validateAndCall(methodStr, null,
222                 () -> getRoamingCapabilitiesInternal(methodStr));
223     }
224 
225     /**
226      * See comments for {@link IWifiStaIface#installApfPacketFilter(byte[])}
227      */
installApfPacketFilter(byte[] program)228     public boolean installApfPacketFilter(byte[] program) {
229         final String methodStr = "installApfPacketFilter";
230         return validateAndCall(methodStr, false,
231                 () -> installApfPacketFilterInternal(methodStr, program));
232     }
233 
234     /**
235      * See comments for {@link IWifiStaIface#readApfPacketFilterData()}
236      */
237     @Nullable
readApfPacketFilterData()238     public byte[] readApfPacketFilterData() {
239         final String methodStr = "readApfPacketFilterData";
240         return validateAndCall(methodStr, null,
241                 () -> readApfPacketFilterDataInternal(methodStr));
242     }
243 
244     /**
245      * See comments for {@link IWifiStaIface#setMacAddress(MacAddress)}
246      */
setMacAddress(MacAddress mac)247     public boolean setMacAddress(MacAddress mac) {
248         final String methodStr = "setMacAddress";
249         return validateAndCall(methodStr, false,
250                 () -> setMacAddressInternal(methodStr, mac));
251     }
252 
253     /**
254      * See comments for {@link IWifiStaIface#setRoamingState(int)}
255      */
setRoamingState( @ifiNative.RoamingEnableState int state)256     public @WifiNative.RoamingEnableStatus int setRoamingState(
257             @WifiNative.RoamingEnableState int state) {
258         final String methodStr = "setRoamingState";
259         return validateAndCall(methodStr, WifiNative.SET_FIRMWARE_ROAMING_FAILURE,
260                 () -> setRoamingStateInternal(methodStr, state));
261     }
262 
263     /**
264      * See comments for {@link IWifiStaIface#setScanMode(boolean)}
265      */
setScanMode(boolean enable)266     public boolean setScanMode(boolean enable) {
267         final String methodStr = "setScanMode";
268         return validateAndCall(methodStr, false,
269                 () -> setScanModeInternal(methodStr, enable));
270     }
271 
272     /**
273      * See comments for
274      * {@link IWifiStaIface#startBackgroundScan(int, WifiStaIface.StaBackgroundScanParameters)}
275      */
startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params)276     public boolean startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params) {
277         final String methodStr = "startBackgroundScan";
278         return validateAndCall(methodStr, false,
279                 () -> startBackgroundScanInternal(methodStr, cmdId, params));
280     }
281 
282     /**
283      * See comments for {@link IWifiStaIface#startDebugPacketFateMonitoring()}
284      */
startDebugPacketFateMonitoring()285     public boolean startDebugPacketFateMonitoring() {
286         final String methodStr = "startDebugPacketFateMonitoring";
287         return validateAndCall(methodStr, false,
288                 () -> startDebugPacketFateMonitoringInternal(methodStr));
289     }
290 
291     /**
292      * See comments for
293      * {@link IWifiStaIface#startRssiMonitoring(int, int, int)}
294      */
startRssiMonitoring(int cmdId, int maxRssi, int minRssi)295     public boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi) {
296         final String methodStr = "startRssiMonitoring";
297         return validateAndCall(methodStr, false,
298                 () -> startRssiMonitoringInternal(methodStr, cmdId, maxRssi, minRssi));
299     }
300 
301     /**
302      * See comments for {@link IWifiStaIface#startSendingKeepAlivePackets(int, byte[], int,
303      *                         MacAddress, MacAddress, int)}
304      */
startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, int periodInMs)305     public boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType,
306             MacAddress srcAddress, MacAddress dstAddress, int periodInMs) {
307         final String methodStr = "startSendingKeepAlivePackets";
308         return validateAndCall(methodStr, false,
309                 () -> startSendingKeepAlivePacketsInternal(methodStr, cmdId, ipPacketData,
310                         etherType, srcAddress, dstAddress, periodInMs));
311     }
312 
313     /**
314      * See comments for {@link IWifiStaIface#stopBackgroundScan(int)}
315      */
stopBackgroundScan(int cmdId)316     public boolean stopBackgroundScan(int cmdId) {
317         final String methodStr = "stopBackgroundScan";
318         return validateAndCall(methodStr, false,
319                 () -> stopBackgroundScanInternal(methodStr, cmdId));
320     }
321 
322     /**
323      * See comments for {@link IWifiStaIface#stopRssiMonitoring(int)}
324      */
stopRssiMonitoring(int cmdId)325     public boolean stopRssiMonitoring(int cmdId) {
326         final String methodStr = "stopRssiMonitoring";
327         return validateAndCall(methodStr, false,
328                 () -> stopRssiMonitoringInternal(methodStr, cmdId));
329     }
330 
331     /**
332      * See comments for {@link IWifiStaIface#stopSendingKeepAlivePackets(int)}
333      */
stopSendingKeepAlivePackets(int cmdId)334     public boolean stopSendingKeepAlivePackets(int cmdId) {
335         final String methodStr = "stopSendingKeepAlivePackets";
336         return validateAndCall(methodStr, false,
337                 () -> stopSendingKeepAlivePacketsInternal(methodStr, cmdId));
338     }
339 
340     /**
341      * See comments for {@link IWifiStaIface#setDtimMultiplier(int)}
342      */
setDtimMultiplier(int multiplier)343     public boolean setDtimMultiplier(int multiplier) {
344         Log.d(TAG, "setDtimMultiplier is not implemented by HIDL");
345         return false;
346     }
347 
348     /**
349      * See comments for {@link IWifiStaIface#setRoamingMode(int)}
350      */
setRoamingMode(int roamingMode)351     public int setRoamingMode(int roamingMode) {
352         Log.d(TAG, "setRoamingMode is not implemented by HIDL");
353         return 0;
354     }
355 
356     // Internal Implementations
357 
registerFrameworkCallbackInternal(String methodStr, WifiStaIface.Callback callback)358     private boolean registerFrameworkCallbackInternal(String methodStr,
359             WifiStaIface.Callback callback) {
360         if (mFrameworkCallback != null) {
361             Log.e(TAG, "Framework callback is already registered");
362             return false;
363         } else if (callback == null) {
364             Log.e(TAG, "Cannot register a null callback");
365             return false;
366         }
367 
368         try {
369             WifiStatus status = mWifiStaIface.registerEventCallback(mHalCallback);
370             if (!isOk(status, methodStr)) return false;
371             mFrameworkCallback = callback;
372             return true;
373         } catch (RemoteException e) {
374             handleRemoteException(e, methodStr);
375             return false;
376         }
377     }
378 
getNameInternal(String methodStr)379     private String getNameInternal(String methodStr) {
380         if (mIfaceName != null) return mIfaceName;
381         GeneralUtil.Mutable<String> nameResp = new GeneralUtil.Mutable<>();
382         try {
383             mWifiStaIface.getName((WifiStatus status, String name) -> {
384                 if (isOk(status, methodStr)) {
385                     nameResp.value = name;
386                     mIfaceName = name;
387                 }
388             });
389         } catch (RemoteException e) {
390             handleRemoteException(e, methodStr);
391         }
392         return nameResp.value;
393     }
394 
configureRoamingInternal(String methodStr, List<MacAddress> bssidBlocklist, List<byte[]> ssidAllowlist)395     private boolean configureRoamingInternal(String methodStr, List<MacAddress> bssidBlocklist,
396             List<byte[]> ssidAllowlist) {
397         StaRoamingConfig config = new StaRoamingConfig();
398         config.ssidWhitelist = new ArrayList<>(ssidAllowlist);
399         config.bssidBlacklist = new ArrayList<>();
400         for (MacAddress bssid : bssidBlocklist) {
401             config.bssidBlacklist.add(bssid.toByteArray());
402         }
403         try {
404             WifiStatus status = mWifiStaIface.configureRoaming(config);
405             return isOk(status, methodStr);
406         } catch (RemoteException e) {
407             handleRemoteException(e, methodStr);
408             return false;
409         }
410     }
411 
enableLinkLayerStatsCollectionInternal(String methodStr, boolean debug)412     private boolean enableLinkLayerStatsCollectionInternal(String methodStr, boolean debug) {
413         try {
414             WifiStatus status = mWifiStaIface.enableLinkLayerStatsCollection(debug);
415             return isOk(status, methodStr);
416         } catch (RemoteException e) {
417             handleRemoteException(e, methodStr);
418             return false;
419         }
420     }
421 
enableNdOffloadInternal(String methodStr, boolean enable)422     private boolean enableNdOffloadInternal(String methodStr, boolean enable) {
423         try {
424             WifiStatus status = mWifiStaIface.enableNdOffload(enable);
425             return isOk(status, methodStr);
426         } catch (RemoteException e) {
427             handleRemoteException(e, methodStr);
428             return false;
429         }
430     }
431 
getApfPacketFilterCapabilitiesInternal(String methodStr)432     private ApfCapabilities getApfPacketFilterCapabilitiesInternal(String methodStr) {
433         GeneralUtil.Mutable<ApfCapabilities> apfResp =
434                 new GeneralUtil.Mutable<>(new ApfCapabilities(0, 0, 0));
435         try {
436             mWifiStaIface.getApfPacketFilterCapabilities((status, caps) -> {
437                 if (isOk(status, methodStr)) {
438                     apfResp.value = new ApfCapabilities(
439                             /* apfVersionSupported */   caps.version,
440                             /* maximumApfProgramSize */ caps.maxLength,
441                             /* apfPacketFormat */       android.system.OsConstants.ARPHRD_ETHER);
442                 }
443             });
444         } catch (RemoteException e) {
445             handleRemoteException(e, methodStr);
446         }
447         return apfResp.value;
448     }
449 
getBackgroundScanCapabilitiesInternal(String methodStr)450     private WifiNative.ScanCapabilities getBackgroundScanCapabilitiesInternal(String methodStr) {
451         GeneralUtil.Mutable<WifiNative.ScanCapabilities> scanResp = new GeneralUtil.Mutable<>();
452         try {
453             mWifiStaIface.getBackgroundScanCapabilities((status, caps) -> {
454                 if (isOk(status, methodStr)) {
455                     WifiNative.ScanCapabilities out = new WifiNative.ScanCapabilities();
456                     out.max_scan_cache_size = caps.maxCacheSize;
457                     out.max_ap_cache_per_scan = caps.maxApCachePerScan;
458                     out.max_scan_buckets = caps.maxBuckets;
459                     out.max_rssi_sample_size = 0;
460                     out.max_scan_reporting_threshold = caps.maxReportingThreshold;
461                     scanResp.value = out;
462                 }
463             });
464         } catch (RemoteException e) {
465             handleRemoteException(e, methodStr);
466         }
467         return scanResp.value;
468     }
469 
getCapabilitiesInternal(String methodStr)470     private long getCapabilitiesInternal(String methodStr) {
471         GeneralUtil.Mutable<Long> capsResp = new GeneralUtil.Mutable<>(0L);
472         try {
473             mWifiStaIface.getCapabilities((status, caps) -> {
474                 if (isOk(status, methodStr)) {
475                     capsResp.value = halToFrameworkStaIfaceCapability(caps);
476                 }
477             });
478         } catch (RemoteException e) {
479             handleRemoteException(e, methodStr);
480         }
481         return capsResp.value;
482     }
483 
getDebugRxPacketFatesInternal(String methodStr)484     private List<WifiNative.RxFateReport> getDebugRxPacketFatesInternal(String methodStr) {
485         try {
486             List<WifiNative.RxFateReport> reportBufs = new ArrayList<>();
487             mWifiStaIface.getDebugRxPacketFates((status, fates) -> {
488                 if (!isOk(status, methodStr)) return;
489                 for (WifiDebugRxPacketFateReport fate : fates) {
490                     if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break;
491                     byte code = halToFrameworkRxPktFate(fate.fate);
492                     long us = fate.frameInfo.driverTimestampUsec;
493                     byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType);
494                     byte[] frame = NativeUtil.byteArrayFromArrayList(
495                             fate.frameInfo.frameContent);
496                     reportBufs.add(new WifiNative.RxFateReport(code, us, type, frame));
497                 }
498             });
499             return reportBufs;
500         } catch (RemoteException e) {
501             handleRemoteException(e, methodStr);
502             return new ArrayList<>();
503         }
504     }
505 
getDebugTxPacketFatesInternal(String methodStr)506     private List<WifiNative.TxFateReport> getDebugTxPacketFatesInternal(String methodStr) {
507         try {
508             List<WifiNative.TxFateReport> reportBufs = new ArrayList<>();
509             mWifiStaIface.getDebugTxPacketFates((status, fates) -> {
510                 if (!isOk(status, methodStr)) return;
511                 for (WifiDebugTxPacketFateReport fate : fates) {
512                     if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break;
513                     byte code = halToFrameworkTxPktFate(fate.fate);
514                     long us = fate.frameInfo.driverTimestampUsec;
515                     byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType);
516                     byte[] frame = NativeUtil.byteArrayFromArrayList(
517                             fate.frameInfo.frameContent);
518                     reportBufs.add(new WifiNative.TxFateReport(code, us, type, frame));
519                 }
520             });
521             return reportBufs;
522         } catch (RemoteException e) {
523             handleRemoteException(e, methodStr);
524             return new ArrayList<>();
525         }
526     }
527 
getFactoryMacAddressInternal(String methodStr)528     private MacAddress getFactoryMacAddressInternal(String methodStr) {
529         GeneralUtil.Mutable<MacAddress> macResp = new GeneralUtil.Mutable<>();
530         try {
531             android.hardware.wifi.V1_3.IWifiStaIface sta13 = getWifiStaIfaceV1_3Mockable();
532             if (sta13 == null) return null;
533             sta13.getFactoryMacAddress((status, macBytes) -> {
534                 if (isOk(status, methodStr)) {
535                     macResp.value = MacAddress.fromBytes(macBytes);
536                 }
537             });
538         } catch (RemoteException e) {
539             handleRemoteException(e, methodStr);
540         }
541         return macResp.value;
542     }
543 
getLinkLayerStatsInternal(String methodStr)544     private WifiLinkLayerStats getLinkLayerStatsInternal(String methodStr) {
545         if (getWifiStaIfaceV1_6Mockable() != null) {
546             return getLinkLayerStatsV1_6Internal(methodStr);
547         } else if (getWifiStaIfaceV1_5Mockable() != null) {
548             return getLinkLayerStatsV1_5Internal(methodStr);
549         } else if (getWifiStaIfaceV1_3Mockable() != null) {
550             return getLinkLayerStatsV1_3Internal(methodStr);
551         } else {
552             return getLinkLayerStatsV1_0Internal(methodStr);
553         }
554     }
555 
getLinkLayerStatsV1_0Internal(String methodStr)556     private WifiLinkLayerStats getLinkLayerStatsV1_0Internal(String methodStr) {
557         final String methodStrV1_0 = methodStr + "V1_0";
558         GeneralUtil.Mutable<StaLinkLayerStats> statsResp = new GeneralUtil.Mutable<>();
559         try {
560             mWifiStaIface.getLinkLayerStats((status, stats) -> {
561                 if (isOk(status, methodStrV1_0)) {
562                     statsResp.value = stats;
563                 }
564             });
565         } catch (RemoteException e) {
566             handleRemoteException(e, methodStrV1_0);
567             return null;
568         }
569         return frameworkFromHalLinkLayerStats(statsResp.value);
570     }
571 
getLinkLayerStatsV1_3Internal(String methodStr)572     private WifiLinkLayerStats getLinkLayerStatsV1_3Internal(String methodStr) {
573         final String methodStrV1_3 = methodStr + "V1_3";
574         GeneralUtil.Mutable<android.hardware.wifi.V1_3.StaLinkLayerStats> statsResp =
575                 new GeneralUtil.Mutable<>();
576         try {
577             android.hardware.wifi.V1_3.IWifiStaIface iface13 = getWifiStaIfaceV1_3Mockable();
578             if (iface13 == null) return null;
579             iface13.getLinkLayerStats_1_3((status, stats) -> {
580                 if (isOk(status, methodStrV1_3)) {
581                     statsResp.value = stats;
582                 }
583             });
584         } catch (RemoteException e) {
585             handleRemoteException(e, methodStrV1_3);
586             return null;
587         }
588         return frameworkFromHalLinkLayerStats_1_3(statsResp.value);
589     }
590 
getLinkLayerStatsV1_5Internal(String methodStr)591     private WifiLinkLayerStats getLinkLayerStatsV1_5Internal(String methodStr) {
592         final String methodStrV1_5 = methodStr + "V1_5";
593         GeneralUtil.Mutable<android.hardware.wifi.V1_5.StaLinkLayerStats> statsResp =
594                 new GeneralUtil.Mutable<>();
595         try {
596             android.hardware.wifi.V1_5.IWifiStaIface iface15 = getWifiStaIfaceV1_5Mockable();
597             if (iface15 == null) return null;
598             iface15.getLinkLayerStats_1_5((status, stats) -> {
599                 if (isOk(status, methodStrV1_5)) {
600                     statsResp.value = stats;
601                 }
602             });
603         } catch (RemoteException e) {
604             handleRemoteException(e, methodStrV1_5);
605             return null;
606         }
607         return frameworkFromHalLinkLayerStats_1_5(statsResp.value);
608     }
609 
getLinkLayerStatsV1_6Internal(String methodStr)610     private WifiLinkLayerStats getLinkLayerStatsV1_6Internal(String methodStr) {
611         final String methodStrV1_6 = methodStr + "V1_6";
612         GeneralUtil.Mutable<android.hardware.wifi.V1_6.StaLinkLayerStats> statsResp =
613                 new GeneralUtil.Mutable<>();
614         try {
615             android.hardware.wifi.V1_6.IWifiStaIface iface16 = getWifiStaIfaceV1_6Mockable();
616             if (iface16 == null) return null;
617             iface16.getLinkLayerStats_1_6((status, stats) -> {
618                 if (isOk(status, methodStrV1_6)) {
619                     statsResp.value = stats;
620                 }
621             });
622         } catch (RemoteException e) {
623             handleRemoteException(e, methodStrV1_6);
624             return null;
625         } catch (Exception e) {
626             handleException(e, methodStrV1_6);
627             return null;
628         }
629         return frameworkFromHalLinkLayerStats_1_6(statsResp.value);
630     }
631 
getRoamingCapabilitiesInternal(String methodStr)632     private WifiNative.RoamingCapabilities getRoamingCapabilitiesInternal(String methodStr) {
633         GeneralUtil.Mutable<WifiNative.RoamingCapabilities> capsResp = new GeneralUtil.Mutable<>();
634         try {
635             mWifiStaIface.getRoamingCapabilities((status, caps) -> {
636                 if (isOk(status, methodStr)) {
637                     WifiNative.RoamingCapabilities out = new WifiNative.RoamingCapabilities();
638                     out.maxBlocklistSize = caps.maxBlacklistSize;
639                     out.maxAllowlistSize = caps.maxWhitelistSize;
640                     capsResp.value = out;
641                 }
642             });
643         } catch (RemoteException e) {
644             handleRemoteException(e, methodStr);
645         }
646         return capsResp.value;
647     }
648 
installApfPacketFilterInternal(String methodStr, byte[] program)649     private boolean installApfPacketFilterInternal(String methodStr, byte[] program) {
650         try {
651             int cmdId = 0; // We only aspire to support one program at a time.
652             ArrayList<Byte> filter = NativeUtil.byteArrayToArrayList(program);
653             WifiStatus status = mWifiStaIface.installApfPacketFilter(cmdId, filter);
654             return isOk(status, methodStr);
655         } catch (RemoteException e) {
656             handleRemoteException(e, methodStr);
657             return false;
658         }
659     }
660 
readApfPacketFilterDataInternal(String methodStr)661     private byte[] readApfPacketFilterDataInternal(String methodStr) {
662         GeneralUtil.Mutable<byte[]> dataResp = new GeneralUtil.Mutable<>();
663         try {
664             android.hardware.wifi.V1_2.IWifiStaIface iface12 = getWifiStaIfaceV1_2Mockable();
665             if (iface12 == null) return null;
666             iface12.readApfPacketFilterData((status, data) -> {
667                 if (isOk(status, methodStr)) {
668                     dataResp.value = NativeUtil.byteArrayFromArrayList(data);
669                 }
670             });
671         } catch (RemoteException e) {
672             handleRemoteException(e, methodStr);
673         }
674         return dataResp.value;
675     }
676 
setMacAddressInternal(String methodStr, MacAddress mac)677     private boolean setMacAddressInternal(String methodStr, MacAddress mac) {
678         try {
679             android.hardware.wifi.V1_2.IWifiStaIface iface12 = getWifiStaIfaceV1_2Mockable();
680             if (iface12 == null) return false;
681             byte[] macBytes = mac.toByteArray();
682             WifiStatus status = iface12.setMacAddress(macBytes);
683             return isOk(status, methodStr);
684         } catch (RemoteException e) {
685             handleRemoteException(e, methodStr);
686             return false;
687         }
688     }
689 
setRoamingStateInternal(String methodStr, @WifiNative.RoamingEnableState int state)690     private @WifiNative.RoamingEnableStatus int setRoamingStateInternal(String methodStr,
691             @WifiNative.RoamingEnableState int state) {
692         byte halState = frameworkToHalStaRoamingState(state);
693         if (halState == -1) {
694             return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE;
695         }
696 
697         try {
698             WifiStatus status = mWifiStaIface.setRoamingState(halState);
699             if (isOk(status, methodStr)) {
700                 return WifiNative.SET_FIRMWARE_ROAMING_SUCCESS;
701             } else if (status.code == WifiStatusCode.ERROR_BUSY) {
702                 return WifiNative.SET_FIRMWARE_ROAMING_BUSY;
703             } else {
704                 return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE;
705             }
706         } catch (RemoteException e) {
707             handleRemoteException(e, methodStr);
708             return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE;
709         }
710     }
711 
setScanModeInternal(String methodStr, boolean enable)712     private boolean setScanModeInternal(String methodStr, boolean enable) {
713         try {
714             android.hardware.wifi.V1_5.IWifiStaIface iface15 = getWifiStaIfaceV1_5Mockable();
715             if (iface15 == null) return false;
716             WifiStatus status = iface15.setScanMode(enable);
717             return isOk(status, methodStr);
718         } catch (RemoteException e) {
719             handleRemoteException(e, methodStr);
720             return false;
721         }
722     }
723 
startBackgroundScanInternal(String methodStr, int cmdId, WifiStaIface.StaBackgroundScanParameters params)724     private boolean startBackgroundScanInternal(String methodStr, int cmdId,
725             WifiStaIface.StaBackgroundScanParameters params) {
726         try {
727             StaBackgroundScanParameters halParams = frameworkToHalBackgroundScanParams(params);
728             WifiStatus status = mWifiStaIface.startBackgroundScan(cmdId, halParams);
729             return isOk(status, methodStr);
730         } catch (RemoteException e) {
731             handleRemoteException(e, methodStr);
732             return false;
733         }
734     }
735 
startDebugPacketFateMonitoringInternal(String methodStr)736     private boolean startDebugPacketFateMonitoringInternal(String methodStr) {
737         try {
738             WifiStatus status = mWifiStaIface.startDebugPacketFateMonitoring();
739             return isOk(status, methodStr);
740         } catch (RemoteException e) {
741             handleRemoteException(e, methodStr);
742             return false;
743         }
744     }
745 
startRssiMonitoringInternal(String methodStr, int cmdId, int maxRssi, int minRssi)746     private boolean startRssiMonitoringInternal(String methodStr, int cmdId, int maxRssi,
747             int minRssi) {
748         try {
749             WifiStatus status = mWifiStaIface.startRssiMonitoring(cmdId, maxRssi, minRssi);
750             return isOk(status, methodStr);
751         } catch (RemoteException e) {
752             handleRemoteException(e, methodStr);
753             return false;
754         }
755     }
756 
startSendingKeepAlivePacketsInternal(String methodStr, int cmdId, byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, int periodInMs)757     private boolean startSendingKeepAlivePacketsInternal(String methodStr, int cmdId,
758             byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress,
759             int periodInMs) {
760         try {
761             ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(ipPacketData);
762             byte[] srcMac = srcAddress.toByteArray();
763             byte[] dstMac = dstAddress.toByteArray();
764             WifiStatus status = mWifiStaIface.startSendingKeepAlivePackets(
765                     cmdId, data, (short) etherType, srcMac, dstMac, periodInMs);
766             return isOk(status, methodStr);
767         } catch (RemoteException e) {
768             handleRemoteException(e, methodStr);
769             return false;
770         }
771     }
772 
stopBackgroundScanInternal(String methodStr, int cmdId)773     private boolean stopBackgroundScanInternal(String methodStr, int cmdId) {
774         try {
775             WifiStatus status = mWifiStaIface.stopBackgroundScan(cmdId);
776             return isOk(status, methodStr);
777         } catch (RemoteException e) {
778             handleRemoteException(e, methodStr);
779             return false;
780         }
781     }
782 
stopRssiMonitoringInternal(String methodStr, int cmdId)783     private boolean stopRssiMonitoringInternal(String methodStr, int cmdId) {
784         try {
785             WifiStatus status = mWifiStaIface.stopRssiMonitoring(cmdId);
786             return isOk(status, methodStr);
787         } catch (RemoteException e) {
788             handleRemoteException(e, methodStr);
789             return false;
790         }
791     }
792 
stopSendingKeepAlivePacketsInternal(String methodStr, int cmdId)793     private boolean stopSendingKeepAlivePacketsInternal(String methodStr, int cmdId) {
794         try {
795             WifiStatus status = mWifiStaIface.stopSendingKeepAlivePackets(cmdId);
796             return isOk(status, methodStr);
797         } catch (RemoteException e) {
798             handleRemoteException(e, methodStr);
799             return false;
800         }
801     }
802 
803 
804     // Helper Functions
805 
frameworkToHalStaRoamingState(@ifiNative.RoamingEnableState int state)806     private static byte frameworkToHalStaRoamingState(@WifiNative.RoamingEnableState int state) {
807         switch (state) {
808             case WifiNative.DISABLE_FIRMWARE_ROAMING:
809                 return StaRoamingState.DISABLED;
810             case WifiNative.ENABLE_FIRMWARE_ROAMING:
811                 return StaRoamingState.ENABLED;
812             default:
813                 Log.e(TAG, "Invalid firmware roaming state enum: " + state);
814                 return -1;
815         }
816     }
817 
halToFrameworkPktFateFrameType(int type)818     private static byte halToFrameworkPktFateFrameType(int type) {
819         switch (type) {
820             case WifiDebugPacketFateFrameType.UNKNOWN:
821                 return WifiLoggerHal.FRAME_TYPE_UNKNOWN;
822             case WifiDebugPacketFateFrameType.ETHERNET_II:
823                 return WifiLoggerHal.FRAME_TYPE_ETHERNET_II;
824             case WifiDebugPacketFateFrameType.MGMT_80211:
825                 return WifiLoggerHal.FRAME_TYPE_80211_MGMT;
826             default:
827                 throw new IllegalArgumentException("bad " + type);
828         }
829     }
830 
halToFrameworkRxPktFate(int type)831     private static byte halToFrameworkRxPktFate(int type) {
832         switch (type) {
833             case WifiDebugRxPacketFate.SUCCESS:
834                 return WifiLoggerHal.RX_PKT_FATE_SUCCESS;
835             case WifiDebugRxPacketFate.FW_QUEUED:
836                 return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED;
837             case WifiDebugRxPacketFate.FW_DROP_FILTER:
838                 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER;
839             case WifiDebugRxPacketFate.FW_DROP_INVALID:
840                 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID;
841             case WifiDebugRxPacketFate.FW_DROP_NOBUFS:
842                 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS;
843             case WifiDebugRxPacketFate.FW_DROP_OTHER:
844                 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER;
845             case WifiDebugRxPacketFate.DRV_QUEUED:
846                 return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED;
847             case WifiDebugRxPacketFate.DRV_DROP_FILTER:
848                 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER;
849             case WifiDebugRxPacketFate.DRV_DROP_INVALID:
850                 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID;
851             case WifiDebugRxPacketFate.DRV_DROP_NOBUFS:
852                 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS;
853             case WifiDebugRxPacketFate.DRV_DROP_OTHER:
854                 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER;
855             default:
856                 throw new IllegalArgumentException("bad " + type);
857         }
858     }
859 
halToFrameworkTxPktFate(int type)860     private static byte halToFrameworkTxPktFate(int type) {
861         switch (type) {
862             case WifiDebugTxPacketFate.ACKED:
863                 return WifiLoggerHal.TX_PKT_FATE_ACKED;
864             case WifiDebugTxPacketFate.SENT:
865                 return WifiLoggerHal.TX_PKT_FATE_SENT;
866             case WifiDebugTxPacketFate.FW_QUEUED:
867                 return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED;
868             case WifiDebugTxPacketFate.FW_DROP_INVALID:
869                 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID;
870             case WifiDebugTxPacketFate.FW_DROP_NOBUFS:
871                 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS;
872             case WifiDebugTxPacketFate.FW_DROP_OTHER:
873                 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER;
874             case WifiDebugTxPacketFate.DRV_QUEUED:
875                 return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED;
876             case WifiDebugTxPacketFate.DRV_DROP_INVALID:
877                 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID;
878             case WifiDebugTxPacketFate.DRV_DROP_NOBUFS:
879                 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS;
880             case WifiDebugTxPacketFate.DRV_DROP_OTHER:
881                 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER;
882             default:
883                 throw new IllegalArgumentException("bad " + type);
884         }
885     }
886 
hasCapability(long capabilities, long desiredCapability)887     private static boolean hasCapability(long capabilities, long desiredCapability) {
888         return (capabilities & desiredCapability) != 0;
889     }
890 
891     @VisibleForTesting
halToFrameworkStaIfaceCapability(int caps)892     long halToFrameworkStaIfaceCapability(int caps) {
893         long features = 0;
894         if (hasCapability(caps,
895                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT)) {
896             features |= WifiManager.WIFI_FEATURE_PASSPOINT;
897         }
898         if (hasCapability(caps,
899                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) {
900             features |= WifiManager.WIFI_FEATURE_SCANNER;
901         }
902         if (hasCapability(caps,
903                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.PNO)) {
904             features |= WifiManager.WIFI_FEATURE_PNO;
905         }
906         if (hasCapability(caps,
907                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) {
908             features |= WifiManager.WIFI_FEATURE_TDLS;
909         }
910         if (hasCapability(caps,
911                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) {
912             features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL;
913         }
914         if (hasCapability(caps,
915                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS)) {
916             features |= WifiManager.WIFI_FEATURE_LINK_LAYER_STATS;
917         }
918         if (hasCapability(caps,
919                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR)) {
920             features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR;
921         }
922         if (hasCapability(caps,
923                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE)) {
924             features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE;
925         }
926         if (hasCapability(caps,
927                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD)) {
928             features |= WifiManager.WIFI_FEATURE_CONFIG_NDO;
929         }
930         if (hasCapability(caps,
931                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING)) {
932             features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING;
933         }
934         if (hasCapability(caps,
935                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask
936                         .PROBE_IE_WHITELIST)) {
937             features |= WifiManager.WIFI_FEATURE_IE_WHITELIST;
938         }
939         if (hasCapability(caps,
940                 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND)) {
941             features |= WifiManager.WIFI_FEATURE_SCAN_RAND;
942         }
943         return features;
944     }
945 
946     @VisibleForTesting
frameworkFromHalLinkLayerStats(StaLinkLayerStats stats)947     WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) {
948         if (stats == null) return null;
949         WifiLinkLayerStats out = new WifiLinkLayerStats();
950         setIfaceStats(out, stats.iface);
951         setRadioStats(out, stats.radios);
952         out.timeStampInMs = stats.timeStampInMs;
953         out.version = WifiLinkLayerStats.V1_0;
954         return out;
955     }
956 
957     /**
958      * Makes the framework version of link layer stats from the hal version.
959      */
960     @VisibleForTesting
frameworkFromHalLinkLayerStats_1_3( android.hardware.wifi.V1_3.StaLinkLayerStats stats)961     WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_3(
962             android.hardware.wifi.V1_3.StaLinkLayerStats stats) {
963         if (stats == null) return null;
964         WifiLinkLayerStats out = new WifiLinkLayerStats();
965         setIfaceStats(out, stats.iface);
966         setRadioStats_1_3(out, stats.radios);
967         out.timeStampInMs = stats.timeStampInMs;
968         out.version = WifiLinkLayerStats.V1_3;
969         return out;
970     }
971 
972     /**
973      * Makes the framework version of link layer stats from the hal version.
974      */
975     @VisibleForTesting
frameworkFromHalLinkLayerStats_1_5( android.hardware.wifi.V1_5.StaLinkLayerStats stats)976     WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_5(
977             android.hardware.wifi.V1_5.StaLinkLayerStats stats) {
978         if (stats == null) return null;
979         WifiLinkLayerStats out = new WifiLinkLayerStats();
980         setIfaceStats_1_5(out, stats.iface);
981         setRadioStats_1_5(out, stats.radios);
982         out.timeStampInMs = stats.timeStampInMs;
983         out.version = WifiLinkLayerStats.V1_5;
984         return out;
985     }
986 
987     /**
988      * Makes the framework version of link layer stats from the hal version.
989      */
990     @VisibleForTesting
frameworkFromHalLinkLayerStats_1_6( android.hardware.wifi.V1_6.StaLinkLayerStats stats)991     WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_6(
992             android.hardware.wifi.V1_6.StaLinkLayerStats stats) {
993         if (stats == null) return null;
994         WifiLinkLayerStats out = new WifiLinkLayerStats();
995         setIfaceStats_1_6(out, stats.iface);
996         setRadioStats_1_6(out, stats.radios);
997         out.timeStampInMs = stats.timeStampInMs;
998         out.version = WifiLinkLayerStats.V1_5;
999         return out;
1000     }
1001 
setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface)1002     private static void setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface) {
1003         if (iface == null) return;
1004         stats.links = new WifiLinkLayerStats.LinkSpecificStats[NUM_OF_LINKS];
1005         stats.links[DEFAULT_LINK] = new WifiLinkLayerStats.LinkSpecificStats();
1006         stats.links[DEFAULT_LINK].link_id = 0;
1007         stats.links[DEFAULT_LINK].state = LINK_STATE_UNKNOWN;
1008         stats.links[DEFAULT_LINK].beacon_rx = iface.beaconRx;
1009         /* HIDL is using legacy single link layer stats. */
1010         stats.links[DEFAULT_LINK].radio_id = 0;
1011         stats.links[DEFAULT_LINK].frequencyMhz = 0;
1012         stats.links[DEFAULT_LINK].rssi_mgmt = iface.avgRssiMgmt;
1013         // Statistics are broken out by Wireless Multimedia Extensions categories
1014         // WME Best Effort Access Category
1015         stats.links[DEFAULT_LINK].rxmpdu_be = iface.wmeBePktStats.rxMpdu;
1016         stats.links[DEFAULT_LINK].txmpdu_be = iface.wmeBePktStats.txMpdu;
1017         stats.links[DEFAULT_LINK].lostmpdu_be = iface.wmeBePktStats.lostMpdu;
1018         stats.links[DEFAULT_LINK].retries_be = iface.wmeBePktStats.retries;
1019         // WME Background Access Category
1020         stats.links[DEFAULT_LINK].rxmpdu_bk = iface.wmeBkPktStats.rxMpdu;
1021         stats.links[DEFAULT_LINK].txmpdu_bk = iface.wmeBkPktStats.txMpdu;
1022         stats.links[DEFAULT_LINK].lostmpdu_bk = iface.wmeBkPktStats.lostMpdu;
1023         stats.links[DEFAULT_LINK].retries_bk = iface.wmeBkPktStats.retries;
1024         // WME Video Access Category
1025         stats.links[DEFAULT_LINK].rxmpdu_vi = iface.wmeViPktStats.rxMpdu;
1026         stats.links[DEFAULT_LINK].txmpdu_vi = iface.wmeViPktStats.txMpdu;
1027         stats.links[DEFAULT_LINK].lostmpdu_vi = iface.wmeViPktStats.lostMpdu;
1028         stats.links[DEFAULT_LINK].retries_vi = iface.wmeViPktStats.retries;
1029         // WME Voice Access Category
1030         stats.links[DEFAULT_LINK].rxmpdu_vo = iface.wmeVoPktStats.rxMpdu;
1031         stats.links[DEFAULT_LINK].txmpdu_vo = iface.wmeVoPktStats.txMpdu;
1032         stats.links[DEFAULT_LINK].lostmpdu_vo = iface.wmeVoPktStats.lostMpdu;
1033         stats.links[DEFAULT_LINK].retries_vo = iface.wmeVoPktStats.retries;
1034     }
1035 
setIfaceStats_1_5(WifiLinkLayerStats stats, android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface)1036     private static void setIfaceStats_1_5(WifiLinkLayerStats stats,
1037             android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface) {
1038         if (iface == null) return;
1039         setIfaceStats(stats, iface.V1_0);
1040         stats.links[DEFAULT_LINK].timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent;
1041         // WME Best Effort Access Category
1042         stats.links[DEFAULT_LINK].contentionTimeMinBeInUsec =
1043                 iface.wmeBeContentionTimeStats.contentionTimeMinInUsec;
1044         stats.links[DEFAULT_LINK].contentionTimeMaxBeInUsec =
1045                 iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec;
1046         stats.links[DEFAULT_LINK].contentionTimeAvgBeInUsec =
1047                 iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec;
1048         stats.links[DEFAULT_LINK].contentionNumSamplesBe =
1049                 iface.wmeBeContentionTimeStats.contentionNumSamples;
1050         // WME Background Access Category
1051         stats.links[DEFAULT_LINK].contentionTimeMinBkInUsec =
1052                 iface.wmeBkContentionTimeStats.contentionTimeMinInUsec;
1053         stats.links[DEFAULT_LINK].contentionTimeMaxBkInUsec =
1054                 iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec;
1055         stats.links[DEFAULT_LINK].contentionTimeAvgBkInUsec =
1056                 iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec;
1057         stats.links[DEFAULT_LINK].contentionNumSamplesBk =
1058                 iface.wmeBkContentionTimeStats.contentionNumSamples;
1059         // WME Video Access Category
1060         stats.links[DEFAULT_LINK].contentionTimeMinViInUsec =
1061                 iface.wmeViContentionTimeStats.contentionTimeMinInUsec;
1062         stats.links[DEFAULT_LINK].contentionTimeMaxViInUsec =
1063                 iface.wmeViContentionTimeStats.contentionTimeMaxInUsec;
1064         stats.links[DEFAULT_LINK].contentionTimeAvgViInUsec =
1065                 iface.wmeViContentionTimeStats.contentionTimeAvgInUsec;
1066         stats.links[DEFAULT_LINK].contentionNumSamplesVi =
1067                 iface.wmeViContentionTimeStats.contentionNumSamples;
1068         // WME Voice Access Category
1069         stats.links[DEFAULT_LINK].contentionTimeMinVoInUsec =
1070                 iface.wmeVoContentionTimeStats.contentionTimeMinInUsec;
1071         stats.links[DEFAULT_LINK].contentionTimeMaxVoInUsec =
1072                 iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec;
1073         stats.links[DEFAULT_LINK].contentionTimeAvgVoInUsec =
1074                 iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec;
1075         stats.links[DEFAULT_LINK].contentionNumSamplesVo =
1076                 iface.wmeVoContentionTimeStats.contentionNumSamples;
1077         // Peer information statistics
1078         stats.links[DEFAULT_LINK].peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.size()];
1079         for (int i = 0; i < stats.links[DEFAULT_LINK].peerInfo.length; i++) {
1080             WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo();
1081             android.hardware.wifi.V1_5.StaPeerInfo staPeerInfo = iface.peers.get(i);
1082             peer.staCount = staPeerInfo.staCount;
1083             peer.chanUtil = staPeerInfo.chanUtil;
1084             WifiLinkLayerStats.RateStat[] rateStats =
1085                     new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.size()];
1086             for (int j = 0; j < staPeerInfo.rateStats.size(); j++) {
1087                 rateStats[j] = new WifiLinkLayerStats.RateStat();
1088                 android.hardware.wifi.V1_5.StaRateStat staRateStat = staPeerInfo.rateStats.get(j);
1089                 rateStats[j].preamble = staRateStat.rateInfo.preamble;
1090                 rateStats[j].nss = staRateStat.rateInfo.nss;
1091                 rateStats[j].bw = staRateStat.rateInfo.bw;
1092                 rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx;
1093                 rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps;
1094                 rateStats[j].txMpdu = staRateStat.txMpdu;
1095                 rateStats[j].rxMpdu = staRateStat.rxMpdu;
1096                 rateStats[j].mpduLost = staRateStat.mpduLost;
1097                 rateStats[j].retries = staRateStat.retries;
1098             }
1099             peer.rateStats = rateStats;
1100             stats.links[DEFAULT_LINK].peerInfo[i] = peer;
1101         }
1102     }
1103 
setIfaceStats_1_6(WifiLinkLayerStats stats, android.hardware.wifi.V1_6.StaLinkLayerIfaceStats iface)1104     private static void setIfaceStats_1_6(WifiLinkLayerStats stats,
1105             android.hardware.wifi.V1_6.StaLinkLayerIfaceStats iface) {
1106         if (iface == null) return;
1107         setIfaceStats(stats, iface.V1_0);
1108         stats.links[DEFAULT_LINK].timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent;
1109         // WME Best Effort Access Category
1110         stats.links[DEFAULT_LINK].contentionTimeMinBeInUsec =
1111                 iface.wmeBeContentionTimeStats.contentionTimeMinInUsec;
1112         stats.links[DEFAULT_LINK].contentionTimeMaxBeInUsec =
1113                 iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec;
1114         stats.links[DEFAULT_LINK].contentionTimeAvgBeInUsec =
1115                 iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec;
1116         stats.links[DEFAULT_LINK].contentionNumSamplesBe =
1117                 iface.wmeBeContentionTimeStats.contentionNumSamples;
1118         // WME Background Access Category
1119         stats.links[DEFAULT_LINK].contentionTimeMinBkInUsec =
1120                 iface.wmeBkContentionTimeStats.contentionTimeMinInUsec;
1121         stats.links[DEFAULT_LINK].contentionTimeMaxBkInUsec =
1122                 iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec;
1123         stats.links[DEFAULT_LINK].contentionTimeAvgBkInUsec =
1124                 iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec;
1125         stats.links[DEFAULT_LINK].contentionNumSamplesBk =
1126                 iface.wmeBkContentionTimeStats.contentionNumSamples;
1127         // WME Video Access Category
1128         stats.links[DEFAULT_LINK].contentionTimeMinViInUsec =
1129                 iface.wmeViContentionTimeStats.contentionTimeMinInUsec;
1130         stats.links[DEFAULT_LINK].contentionTimeMaxViInUsec =
1131                 iface.wmeViContentionTimeStats.contentionTimeMaxInUsec;
1132         stats.links[DEFAULT_LINK].contentionTimeAvgViInUsec =
1133                 iface.wmeViContentionTimeStats.contentionTimeAvgInUsec;
1134         stats.links[DEFAULT_LINK].contentionNumSamplesVi =
1135                 iface.wmeViContentionTimeStats.contentionNumSamples;
1136         // WME Voice Access Category
1137         stats.links[DEFAULT_LINK].contentionTimeMinVoInUsec =
1138                 iface.wmeVoContentionTimeStats.contentionTimeMinInUsec;
1139         stats.links[DEFAULT_LINK].contentionTimeMaxVoInUsec =
1140                 iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec;
1141         stats.links[DEFAULT_LINK].contentionTimeAvgVoInUsec =
1142                 iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec;
1143         stats.links[DEFAULT_LINK].contentionNumSamplesVo =
1144                 iface.wmeVoContentionTimeStats.contentionNumSamples;
1145         // Peer information statistics
1146         stats.links[DEFAULT_LINK].peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.size()];
1147         for (int i = 0; i < stats.links[DEFAULT_LINK].peerInfo.length; i++) {
1148             WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo();
1149             android.hardware.wifi.V1_6.StaPeerInfo staPeerInfo = iface.peers.get(i);
1150             peer.staCount = staPeerInfo.staCount;
1151             peer.chanUtil = staPeerInfo.chanUtil;
1152             WifiLinkLayerStats.RateStat[] rateStats =
1153                     new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.size()];
1154             for (int j = 0; j < staPeerInfo.rateStats.size(); j++) {
1155                 rateStats[j] = new WifiLinkLayerStats.RateStat();
1156                 android.hardware.wifi.V1_6.StaRateStat staRateStat = staPeerInfo.rateStats.get(j);
1157                 rateStats[j].preamble = staRateStat.rateInfo.preamble;
1158                 rateStats[j].nss = staRateStat.rateInfo.nss;
1159                 rateStats[j].bw = staRateStat.rateInfo.bw;
1160                 rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx;
1161                 rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps;
1162                 rateStats[j].txMpdu = staRateStat.txMpdu;
1163                 rateStats[j].rxMpdu = staRateStat.rxMpdu;
1164                 rateStats[j].mpduLost = staRateStat.mpduLost;
1165                 rateStats[j].retries = staRateStat.retries;
1166             }
1167             peer.rateStats = rateStats;
1168             stats.links[DEFAULT_LINK].peerInfo[i] = peer;
1169         }
1170     }
1171 
setRadioStats(WifiLinkLayerStats stats, List<StaLinkLayerRadioStats> radios)1172     private static void setRadioStats(WifiLinkLayerStats stats,
1173             List<StaLinkLayerRadioStats> radios) {
1174         if (radios == null) return;
1175         // Do not coalesce this info for multi radio devices with older HALs.
1176         if (radios.size() > 0) {
1177             StaLinkLayerRadioStats radioStats = radios.get(0);
1178             stats.on_time = radioStats.onTimeInMs;
1179             stats.tx_time = radioStats.txTimeInMs;
1180             stats.tx_time_per_level = new int[radioStats.txTimeInMsPerLevel.size()];
1181             for (int i = 0; i < stats.tx_time_per_level.length; i++) {
1182                 stats.tx_time_per_level[i] = radioStats.txTimeInMsPerLevel.get(i);
1183             }
1184             stats.rx_time = radioStats.rxTimeInMs;
1185             stats.on_time_scan = radioStats.onTimeInMsForScan;
1186             stats.numRadios = 1;
1187         }
1188     }
1189 
setRadioStats_1_3(WifiLinkLayerStats stats, List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios)1190     private void setRadioStats_1_3(WifiLinkLayerStats stats,
1191             List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios) {
1192         if (radios == null) return;
1193         int radioIndex = 0;
1194         for (android.hardware.wifi.V1_3.StaLinkLayerRadioStats radioStats : radios) {
1195             aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats);
1196             radioIndex++;
1197         }
1198     }
1199 
setRadioStats_1_5(WifiLinkLayerStats stats, List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios)1200     private void setRadioStats_1_5(WifiLinkLayerStats stats,
1201             List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios) {
1202         if (radios == null) return;
1203         int radioIndex = 0;
1204         stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.size()];
1205         for (android.hardware.wifi.V1_5.StaLinkLayerRadioStats radioStats : radios) {
1206             WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat();
1207             setFrameworkPerRadioStatsFromHidl_1_3(radioStats.radioId, radio, radioStats.V1_3);
1208             stats.radioStats[radioIndex] = radio;
1209             aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats.V1_3);
1210             radioIndex++;
1211         }
1212     }
1213 
setRadioStats_1_6(WifiLinkLayerStats stats, List<android.hardware.wifi.V1_6.StaLinkLayerRadioStats> radios)1214     private void setRadioStats_1_6(WifiLinkLayerStats stats,
1215             List<android.hardware.wifi.V1_6.StaLinkLayerRadioStats> radios) {
1216         if (radios == null) return;
1217         int radioIndex = 0;
1218         stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.size()];
1219         for (android.hardware.wifi.V1_6.StaLinkLayerRadioStats radioStats : radios) {
1220             WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat();
1221             setFrameworkPerRadioStatsFromHidl_1_6(radio, radioStats);
1222             stats.radioStats[radioIndex] = radio;
1223             aggregateFrameworkRadioStatsFromHidl_1_6(radioIndex, stats, radioStats);
1224             radioIndex++;
1225         }
1226     }
1227 
1228     /**
1229      * Set individual radio stats from the hal radio stats for V1_3
1230      */
setFrameworkPerRadioStatsFromHidl_1_3(int radioId, WifiLinkLayerStats.RadioStat radio, android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats)1231     private void setFrameworkPerRadioStatsFromHidl_1_3(int radioId,
1232             WifiLinkLayerStats.RadioStat radio,
1233             android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) {
1234         radio.radio_id = radioId;
1235         radio.on_time = hidlRadioStats.V1_0.onTimeInMs;
1236         radio.tx_time = hidlRadioStats.V1_0.txTimeInMs;
1237         radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs;
1238         radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan;
1239         radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan;
1240         radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan;
1241         radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan;
1242         radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan;
1243         radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan;
1244         /* Copy list of channel stats */
1245         for (android.hardware.wifi.V1_3.WifiChannelStats channelStats
1246                 : hidlRadioStats.channelStats) {
1247             WifiLinkLayerStats.ChannelStats channelStatsEntry =
1248                     new WifiLinkLayerStats.ChannelStats();
1249             channelStatsEntry.frequency = channelStats.channel.centerFreq;
1250             channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs;
1251             channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs;
1252             radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry);
1253         }
1254     }
1255 
1256     /**
1257      * Set individual radio stats from the hal radio stats for V1_6
1258      */
setFrameworkPerRadioStatsFromHidl_1_6(WifiLinkLayerStats.RadioStat radio, android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats)1259     private void setFrameworkPerRadioStatsFromHidl_1_6(WifiLinkLayerStats.RadioStat radio,
1260             android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) {
1261         radio.radio_id = hidlRadioStats.radioId;
1262         radio.on_time = hidlRadioStats.V1_0.onTimeInMs;
1263         radio.tx_time = hidlRadioStats.V1_0.txTimeInMs;
1264         radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs;
1265         radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan;
1266         radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan;
1267         radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan;
1268         radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan;
1269         radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan;
1270         radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan;
1271         /* Copy list of channel stats */
1272         for (android.hardware.wifi.V1_6.WifiChannelStats channelStats
1273                 : hidlRadioStats.channelStats) {
1274             WifiLinkLayerStats.ChannelStats channelStatsEntry =
1275                     new WifiLinkLayerStats.ChannelStats();
1276             channelStatsEntry.frequency = channelStats.channel.centerFreq;
1277             channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs;
1278             channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs;
1279             radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry);
1280         }
1281     }
1282 
1283     /**
1284      * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate
1285      * the radio stats from all the radios else process the stats from Radio 0 only.
1286      * This method is for V1_3
1287      */
aggregateFrameworkRadioStatsFromHidl_1_3(int radioIndex, WifiLinkLayerStats stats, android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats)1288     private void aggregateFrameworkRadioStatsFromHidl_1_3(int radioIndex,
1289             WifiLinkLayerStats stats,
1290             android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) {
1291         if (!mWifiLinkLayerAllRadiosStatsAggregationEnabled && radioIndex > 0) {
1292             return;
1293         }
1294         // Aggregate the radio stats from all the radios
1295         stats.on_time += hidlRadioStats.V1_0.onTimeInMs;
1296         stats.tx_time += hidlRadioStats.V1_0.txTimeInMs;
1297         // Aggregate tx_time_per_level based on the assumption that the length of
1298         // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other
1299         // radios at array indices greater than the length of first radio will be dropped.
1300         if (stats.tx_time_per_level == null) {
1301             stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()];
1302         }
1303         for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size()
1304                 && i < stats.tx_time_per_level.length; i++) {
1305             stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i);
1306         }
1307         stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs;
1308         stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan;
1309         stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan;
1310         stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan;
1311         stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan;
1312         stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan;
1313         stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan;
1314         /* Copy list of channel stats */
1315         for (android.hardware.wifi.V1_3.WifiChannelStats channelStats
1316                 : hidlRadioStats.channelStats) {
1317             WifiLinkLayerStats.ChannelStats channelStatsEntry =
1318                     stats.channelStatsMap.get(channelStats.channel.centerFreq);
1319             if (channelStatsEntry == null) {
1320                 channelStatsEntry = new WifiLinkLayerStats.ChannelStats();
1321                 channelStatsEntry.frequency = channelStats.channel.centerFreq;
1322                 stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry);
1323             }
1324             channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs;
1325             channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs;
1326         }
1327         stats.numRadios++;
1328     }
1329 
1330     /**
1331      * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate
1332      * the radio stats from all the radios else process the stats from Radio 0 only.
1333      * This method is for V1_6
1334      */
aggregateFrameworkRadioStatsFromHidl_1_6(int radioIndex, WifiLinkLayerStats stats, android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats)1335     private void aggregateFrameworkRadioStatsFromHidl_1_6(int radioIndex,
1336             WifiLinkLayerStats stats,
1337             android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) {
1338         if (!mWifiLinkLayerAllRadiosStatsAggregationEnabled && radioIndex > 0) {
1339             return;
1340         }
1341         // Aggregate the radio stats from all the radios
1342         stats.on_time += hidlRadioStats.V1_0.onTimeInMs;
1343         stats.tx_time += hidlRadioStats.V1_0.txTimeInMs;
1344         // Aggregate tx_time_per_level based on the assumption that the length of
1345         // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other
1346         // radios at array indices greater than the length of first radio will be dropped.
1347         if (stats.tx_time_per_level == null) {
1348             stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()];
1349         }
1350         for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size()
1351                 && i < stats.tx_time_per_level.length; i++) {
1352             stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i);
1353         }
1354         stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs;
1355         stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan;
1356         stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan;
1357         stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan;
1358         stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan;
1359         stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan;
1360         stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan;
1361         /* Copy list of channel stats */
1362         for (android.hardware.wifi.V1_6.WifiChannelStats channelStats
1363                 : hidlRadioStats.channelStats) {
1364             WifiLinkLayerStats.ChannelStats channelStatsEntry =
1365                     stats.channelStatsMap.get(channelStats.channel.centerFreq);
1366             if (channelStatsEntry == null) {
1367                 channelStatsEntry = new WifiLinkLayerStats.ChannelStats();
1368                 channelStatsEntry.frequency = channelStats.channel.centerFreq;
1369                 stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry);
1370             }
1371             channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs;
1372             channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs;
1373         }
1374         stats.numRadios++;
1375     }
1376 
frameworkToHalBackgroundScanParams( WifiStaIface.StaBackgroundScanParameters frameworkParams)1377     private static StaBackgroundScanParameters frameworkToHalBackgroundScanParams(
1378             WifiStaIface.StaBackgroundScanParameters frameworkParams) {
1379         StaBackgroundScanParameters halParams = new StaBackgroundScanParameters();
1380         halParams.basePeriodInMs = frameworkParams.basePeriodInMs;
1381         halParams.maxApPerScan = frameworkParams.maxApPerScan;
1382         halParams.reportThresholdPercent = frameworkParams.reportThresholdPercent;
1383         halParams.reportThresholdNumScans = frameworkParams.reportThresholdNumScans;
1384         if (frameworkParams.buckets != null) {
1385             for (WifiNative.BucketSettings bucket : frameworkParams.buckets) {
1386                 halParams.buckets.add(frameworkToHalBucketParams(bucket));
1387             }
1388         }
1389         return halParams;
1390     }
1391 
frameworkToHalBucketParams( WifiNative.BucketSettings frameworkBucket)1392     private static StaBackgroundScanBucketParameters frameworkToHalBucketParams(
1393             WifiNative.BucketSettings frameworkBucket) {
1394         StaBackgroundScanBucketParameters halBucket = new StaBackgroundScanBucketParameters();
1395         halBucket.bucketIdx = frameworkBucket.bucket;
1396         halBucket.band = frameworkToHalWifiBand(frameworkBucket.band);
1397         if (frameworkBucket.channels != null) {
1398             for (WifiNative.ChannelSettings cs : frameworkBucket.channels) {
1399                 halBucket.frequencies.add(cs.frequency);
1400             }
1401         }
1402         halBucket.periodInMs = frameworkBucket.period_ms;
1403         halBucket.eventReportScheme = frameworkToHalReportSchemeMask(frameworkBucket.report_events);
1404         halBucket.exponentialMaxPeriodInMs = frameworkBucket.max_period_ms;
1405         // Although HAL API allows configurable base value for the truncated
1406         // exponential back off scan. Native API and above support only
1407         // truncated binary exponential back off scan.
1408         // Hard code value of base to 2 here.
1409         halBucket.exponentialBase = 2;
1410         halBucket.exponentialStepCount = frameworkBucket.step_count;
1411         return halBucket;
1412     }
1413 
1414     /**
1415      * Convert WifiBand from framework to HAL.
1416      *
1417      * Note: This method is only used by background scan which does not
1418      *       support 6GHz, hence band combinations including 6GHz are considered invalid
1419      *
1420      * @param frameworkBand one of WifiScanner.WIFI_BAND_*
1421      * @return A WifiBand value
1422      * @throws IllegalArgumentException if frameworkBand is not recognized
1423      */
frameworkToHalWifiBand(int frameworkBand)1424     private static int frameworkToHalWifiBand(int frameworkBand) {
1425         switch (frameworkBand) {
1426             case WifiScanner.WIFI_BAND_UNSPECIFIED:
1427                 return WifiBand.BAND_UNSPECIFIED;
1428             case WifiScanner.WIFI_BAND_24_GHZ:
1429                 return WifiBand.BAND_24GHZ;
1430             case WifiScanner.WIFI_BAND_5_GHZ:
1431                 return WifiBand.BAND_5GHZ;
1432             case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
1433                 return WifiBand.BAND_5GHZ_DFS;
1434             case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS:
1435                 return WifiBand.BAND_5GHZ_WITH_DFS;
1436             case WifiScanner.WIFI_BAND_BOTH:
1437                 return WifiBand.BAND_24GHZ_5GHZ;
1438             case WifiScanner.WIFI_BAND_BOTH_WITH_DFS:
1439                 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS;
1440             case WifiScanner.WIFI_BAND_6_GHZ:
1441                 return WifiBand.BAND_6GHZ;
1442             case WifiScanner.WIFI_BAND_24_5_6_GHZ:
1443                 return WifiBand.BAND_24GHZ_5GHZ_6GHZ;
1444             case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ:
1445                 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ;
1446             case WifiScanner.WIFI_BAND_60_GHZ:
1447                 return WifiBand.BAND_60GHZ;
1448             case WifiScanner.WIFI_BAND_24_5_6_60_GHZ:
1449                 return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ;
1450             case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ:
1451                 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ;
1452             case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS:
1453             default:
1454                 throw new IllegalArgumentException("bad band " + frameworkBand);
1455         }
1456     }
1457 
1458     /**
1459      * Convert the report scheme mask from framework to hal.
1460      *
1461      * @param reportUnderscoreEvents is logical OR of WifiScanner.REPORT_EVENT_* values
1462      * @return Corresponding StaBackgroundScanBucketEventReportSchemeMask value
1463      * @throws IllegalArgumentException if a mask bit is not recognized
1464      */
frameworkToHalReportSchemeMask(int reportUnderscoreEvents)1465     private static int frameworkToHalReportSchemeMask(int reportUnderscoreEvents) {
1466         int ans = 0;
1467         BitMask in = new BitMask(reportUnderscoreEvents);
1468         if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) {
1469             ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN;
1470         }
1471         if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) {
1472             ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS;
1473         }
1474         if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) {
1475             ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH;
1476         }
1477         if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents);
1478         return ans;
1479     }
1480 
1481     // Only sets the fields of ScanResult used by Gscan clients.
hidlToFrameworkScanResult(StaScanResult scanResult)1482     private ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) {
1483         if (scanResult == null) return null;
1484         WifiSsid originalSsid = WifiSsid.fromBytes(
1485                 NativeUtil.byteArrayFromArrayList(scanResult.ssid));
1486         MacAddress bssid;
1487         try {
1488             bssid = MacAddress.fromString(NativeUtil.macAddressFromByteArray(scanResult.bssid));
1489         } catch (IllegalArgumentException e) {
1490             Log.e(TAG, "Failed to get BSSID of scan result: " + e);
1491             return null;
1492         }
1493         ScanResult frameworkScanResult = new ScanResult();
1494         frameworkScanResult.setWifiSsid(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset(
1495                 originalSsid, bssid));
1496         frameworkScanResult.BSSID = bssid.toString();
1497         frameworkScanResult.level = scanResult.rssi;
1498         frameworkScanResult.frequency = scanResult.frequency;
1499         frameworkScanResult.timestamp = scanResult.timeStampInUs;
1500         return frameworkScanResult;
1501     }
1502 
hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults)1503     private ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) {
1504         if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0];
1505         ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()];
1506         int i = 0;
1507         for (StaScanResult scanResult : scanResults) {
1508             ScanResult frameworkScanResult = hidlToFrameworkScanResult(scanResult);
1509             if (frameworkScanResult == null) {
1510                 Log.e(TAG, "hidlToFrameworkScanResults: unable to convert hidl to framework "
1511                         + "scan result!");
1512                 continue;
1513             }
1514             frameworkScanResults[i++] = frameworkScanResult;
1515         }
1516         return frameworkScanResults;
1517     }
1518 
hidlToFrameworkScanDataFlags(int flag)1519     private static int hidlToFrameworkScanDataFlags(int flag) {
1520         if (flag == StaScanDataFlagMask.INTERRUPTED) {
1521             return 1;
1522         } else {
1523             return 0;
1524         }
1525     }
1526 
hidlToFrameworkScanDatas( int cmdId, ArrayList<StaScanData> scanDatas)1527     private WifiScanner.ScanData[] hidlToFrameworkScanDatas(
1528             int cmdId, ArrayList<StaScanData> scanDatas) {
1529         if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0];
1530         WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()];
1531         int i = 0;
1532         for (StaScanData scanData : scanDatas) {
1533             int flags = hidlToFrameworkScanDataFlags(scanData.flags);
1534             ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results);
1535             frameworkScanDatas[i++] =
1536                     new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned,
1537                             WifiScanner.WIFI_BAND_UNSPECIFIED, frameworkScanResults);
1538         }
1539         return frameworkScanDatas;
1540     }
1541 
getWifiStaIfaceV1_2Mockable()1542     protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceV1_2Mockable() {
1543         return android.hardware.wifi.V1_2.IWifiStaIface.castFrom(mWifiStaIface);
1544     }
1545 
getWifiStaIfaceV1_3Mockable()1546     protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceV1_3Mockable() {
1547         return android.hardware.wifi.V1_3.IWifiStaIface.castFrom(mWifiStaIface);
1548     }
1549 
getWifiStaIfaceV1_5Mockable()1550     protected android.hardware.wifi.V1_5.IWifiStaIface getWifiStaIfaceV1_5Mockable() {
1551         return android.hardware.wifi.V1_5.IWifiStaIface.castFrom(mWifiStaIface);
1552     }
1553 
getWifiStaIfaceV1_6Mockable()1554     protected android.hardware.wifi.V1_6.IWifiStaIface getWifiStaIfaceV1_6Mockable() {
1555         return android.hardware.wifi.V1_6.IWifiStaIface.castFrom(mWifiStaIface);
1556     }
1557 
isOk(WifiStatus status, String methodStr)1558     private boolean isOk(WifiStatus status, String methodStr) {
1559         if (status.code == WifiStatusCode.SUCCESS) return true;
1560         Log.e(TAG, methodStr + " failed with status: " + status);
1561         return false;
1562     }
1563 
handleRemoteException(RemoteException e, String methodStr)1564     private void handleRemoteException(RemoteException e, String methodStr) {
1565         Log.e(TAG, methodStr + " failed with remote exception: " + e);
1566         mWifiStaIface = null;
1567     }
1568 
handleException(Exception e, String methodStr)1569     private void handleException(Exception e, String methodStr) {
1570         Log.e(TAG, methodStr + " failed with exception: " + e);
1571     }
1572 
validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier)1573     private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) {
1574         if (mWifiStaIface == null) {
1575             Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiStaIface is null");
1576             return defaultVal;
1577         }
1578         return supplier.get();
1579     }
1580 
1581 
1582     // HAL Callback
1583     private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub {
1584         @Override
onBackgroundScanFailure(int cmdId)1585         public void onBackgroundScanFailure(int cmdId) {
1586             if (mFrameworkCallback == null) return;
1587             mFrameworkCallback.onBackgroundScanFailure(cmdId);
1588         }
1589 
1590         @Override
onBackgroundFullScanResult(int cmdId, int bucketsScanned, StaScanResult result)1591         public void onBackgroundFullScanResult(int cmdId, int bucketsScanned,
1592                 StaScanResult result) {
1593             if (mFrameworkCallback == null) return;
1594             ScanResult frameworkScanResult = hidlToFrameworkScanResult(result);
1595             if (frameworkScanResult == null) {
1596                 Log.e(TAG, "Unable to convert scan result from HAL to framework");
1597                 return;
1598             }
1599             mFrameworkCallback.onBackgroundFullScanResult(cmdId, bucketsScanned,
1600                     frameworkScanResult);
1601         }
1602 
1603         @Override
onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas)1604         public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) {
1605             if (mFrameworkCallback == null) return;
1606             WifiScanner.ScanData[] frameworkScanDatas = hidlToFrameworkScanDatas(cmdId, scanDatas);
1607             mFrameworkCallback.onBackgroundScanResults(cmdId, frameworkScanDatas);
1608         }
1609 
1610         @Override
onRssiThresholdBreached(int cmdId, byte[ ] currBssid, int currRssi)1611         public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) {
1612             if (mFrameworkCallback == null) return;
1613             mFrameworkCallback.onRssiThresholdBreached(cmdId, currBssid, currRssi);
1614         }
1615     }
1616 }
1617