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