• 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.hardware.wifi.WifiChannelWidthInMhz.WIDTH_160;
20 import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_320;
21 import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_40;
22 import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_80;
23 import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_80P80;
24 import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE;
25 
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.content.Context;
29 import android.hardware.wifi.AfcChannelAllowance;
30 import android.hardware.wifi.AvailableAfcChannelInfo;
31 import android.hardware.wifi.AvailableAfcFrequencyInfo;
32 import android.hardware.wifi.IWifiApIface;
33 import android.hardware.wifi.IWifiChip.ChannelCategoryMask;
34 import android.hardware.wifi.IWifiChip.CoexRestriction;
35 import android.hardware.wifi.IWifiChip.FeatureSetMask;
36 import android.hardware.wifi.IWifiChip.LatencyMode;
37 import android.hardware.wifi.IWifiChip.MultiStaUseCase;
38 import android.hardware.wifi.IWifiChip.TxPowerScenario;
39 import android.hardware.wifi.IWifiChip.UsableChannelFilter;
40 import android.hardware.wifi.IWifiChip.VoipMode;
41 import android.hardware.wifi.IWifiChipEventCallback;
42 import android.hardware.wifi.IWifiNanIface;
43 import android.hardware.wifi.IWifiP2pIface;
44 import android.hardware.wifi.IWifiRttController;
45 import android.hardware.wifi.IWifiStaIface;
46 import android.hardware.wifi.IfaceConcurrencyType;
47 import android.hardware.wifi.IfaceType;
48 import android.hardware.wifi.WifiAntennaMode;
49 import android.hardware.wifi.WifiBand;
50 import android.hardware.wifi.WifiChipCapabilities;
51 import android.hardware.wifi.WifiDebugHostWakeReasonStats;
52 import android.hardware.wifi.WifiDebugRingBufferFlags;
53 import android.hardware.wifi.WifiDebugRingBufferStatus;
54 import android.hardware.wifi.WifiIfaceMode;
55 import android.hardware.wifi.WifiRadioCombination;
56 import android.hardware.wifi.WifiRadioConfiguration;
57 import android.hardware.wifi.WifiStatusCode;
58 import android.hardware.wifi.WifiUsableChannel;
59 import android.net.wifi.CoexUnsafeChannel;
60 import android.net.wifi.OuiKeyedData;
61 import android.net.wifi.ScanResult;
62 import android.net.wifi.WifiAnnotations;
63 import android.net.wifi.WifiAvailableChannel;
64 import android.net.wifi.WifiManager;
65 import android.net.wifi.WifiScanner;
66 import android.os.RemoteException;
67 import android.os.ServiceSpecificException;
68 import android.util.Log;
69 
70 import com.android.internal.annotations.VisibleForTesting;
71 import com.android.modules.utils.build.SdkLevel;
72 import com.android.server.wifi.SarInfo;
73 import com.android.server.wifi.SsidTranslator;
74 import com.android.server.wifi.WifiNative;
75 import com.android.server.wifi.WlanWakeReasonAndCounts;
76 import com.android.server.wifi.util.BitMask;
77 import com.android.server.wifi.util.HalAidlUtil;
78 
79 import java.util.ArrayList;
80 import java.util.Arrays;
81 import java.util.List;
82 
83 /**
84  * AIDL implementation of the WifiChip interface.
85  */
86 public class WifiChipAidlImpl implements IWifiChip {
87     private static final String TAG = "WifiChipAidlImpl";
88     private android.hardware.wifi.IWifiChip mWifiChip;
89     private android.hardware.wifi.IWifiChipEventCallback mHalCallback;
90     private WifiChip.Callback mFrameworkCallback;
91     private final Object mLock = new Object();
92     private Context mContext;
93     private SsidTranslator mSsidTranslator;
94     private long mHalFeatureSet;
95 
WifiChipAidlImpl(@onNull android.hardware.wifi.IWifiChip chip, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)96     public WifiChipAidlImpl(@NonNull android.hardware.wifi.IWifiChip chip,
97             @NonNull Context context, @NonNull SsidTranslator ssidTranslator) {
98         mWifiChip = chip;
99         mContext = context;
100         mSsidTranslator = ssidTranslator;
101     }
102 
103     /**
104      * See comments for {@link IWifiChip#configureChip(int)}
105      */
106     @Override
configureChip(int modeId)107     public boolean configureChip(int modeId) {
108         final String methodStr = "configureChip";
109         synchronized (mLock) {
110             try {
111                 if (!checkIfaceAndLogFailure(methodStr)) return false;
112                 mWifiChip.configureChip(modeId);
113                 return true;
114             } catch (RemoteException e) {
115                 handleRemoteException(e, methodStr);
116             } catch (ServiceSpecificException e) {
117                 handleServiceSpecificException(e, methodStr);
118             }
119             return false;
120         }
121     }
122 
123     /**
124      * See comments for {@link IWifiChip#createApIface(List)}
125      */
126     @Override
127     @Nullable
createApIface(@onNull List<OuiKeyedData> vendorData)128     public WifiApIface createApIface(@NonNull List<OuiKeyedData> vendorData) {
129         final String methodStr = "createApIface";
130         synchronized (mLock) {
131             try {
132                 if (!checkIfaceAndLogFailure(methodStr)) return null;
133                 IWifiApIface iface;
134                 if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && !vendorData.isEmpty()) {
135                     android.hardware.wifi.common.OuiKeyedData[] halVendorData =
136                             HalAidlUtil.frameworkToHalOuiKeyedDataList(vendorData);
137                     iface = mWifiChip.createApOrBridgedApIface(
138                             IfaceConcurrencyType.AP, halVendorData);
139                 } else {
140                     iface = mWifiChip.createApIface();
141                 }
142                 return new WifiApIface(iface);
143             } catch (RemoteException e) {
144                 handleRemoteException(e, methodStr);
145             } catch (ServiceSpecificException e) {
146                 handleServiceSpecificException(e, methodStr);
147             }
148             return null;
149         }
150     }
151 
152     /**
153      * See comments for {@link IWifiChip#createBridgedApIface(List)}
154      */
155     @Override
156     @Nullable
createBridgedApIface(@onNull List<OuiKeyedData> vendorData)157     public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData) {
158         final String methodStr = "createBridgedApIface";
159         synchronized (mLock) {
160             try {
161                 if (!checkIfaceAndLogFailure(methodStr)) return null;
162                 IWifiApIface iface;
163                 if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && !vendorData.isEmpty()) {
164                     android.hardware.wifi.common.OuiKeyedData[] halVendorData =
165                             HalAidlUtil.frameworkToHalOuiKeyedDataList(vendorData);
166                     iface = mWifiChip.createApOrBridgedApIface(
167                             IfaceConcurrencyType.AP_BRIDGED, halVendorData);
168                 } else {
169                     iface = mWifiChip.createBridgedApIface();
170                 }
171                 return new WifiApIface(iface);
172             } catch (RemoteException e) {
173                 handleRemoteException(e, methodStr);
174             } catch (ServiceSpecificException e) {
175                 handleServiceSpecificException(e, methodStr);
176             }
177             return null;
178         }
179     }
180 
181     /**
182      * See comments for {@link IWifiChip#createNanIface()}
183      */
184     @Override
185     @Nullable
createNanIface()186     public WifiNanIface createNanIface() {
187         final String methodStr = "createNanIface";
188         synchronized (mLock) {
189             try {
190                 if (!checkIfaceAndLogFailure(methodStr)) return null;
191                 IWifiNanIface iface = mWifiChip.createNanIface();
192                 return new WifiNanIface(iface);
193             } catch (RemoteException e) {
194                 handleRemoteException(e, methodStr);
195             } catch (ServiceSpecificException e) {
196                 handleServiceSpecificException(e, methodStr);
197             }
198             return null;
199         }
200     }
201 
202     /**
203      * See comments for {@link IWifiChip#createP2pIface()}
204      */
205     @Override
206     @Nullable
createP2pIface()207     public WifiP2pIface createP2pIface() {
208         final String methodStr = "createP2pIface";
209         synchronized (mLock) {
210             try {
211                 if (!checkIfaceAndLogFailure(methodStr)) return null;
212                 IWifiP2pIface iface = mWifiChip.createP2pIface();
213                 return new WifiP2pIface(iface);
214             } catch (RemoteException e) {
215                 handleRemoteException(e, methodStr);
216             } catch (ServiceSpecificException e) {
217                 handleServiceSpecificException(e, methodStr);
218             }
219             return null;
220         }
221     }
222 
223     /**
224      * See comments for {@link IWifiChip#createRttController()}
225      */
226     @Override
227     @Nullable
createRttController()228     public WifiRttController createRttController() {
229         final String methodStr = "createRttController";
230         synchronized (mLock) {
231             try {
232                 if (!checkIfaceAndLogFailure(methodStr)) return null;
233                 IWifiRttController rttController = mWifiChip.createRttController(null);
234                 return new WifiRttController(rttController);
235             } catch (RemoteException e) {
236                 handleRemoteException(e, methodStr);
237             } catch (ServiceSpecificException e) {
238                 handleServiceSpecificException(e, methodStr);
239             }
240             return null;
241         }
242     }
243 
244     /**
245      * See comments for {@link IWifiChip#createStaIface()}
246      */
247     @Override
248     @Nullable
createStaIface()249     public WifiStaIface createStaIface() {
250         final String methodStr = "createStaIface";
251         synchronized (mLock) {
252             try {
253                 if (!checkIfaceAndLogFailure(methodStr)) return null;
254                 IWifiStaIface iface = mWifiChip.createStaIface();
255                 return new WifiStaIface(iface, mContext, mSsidTranslator);
256             } catch (RemoteException e) {
257                 handleRemoteException(e, methodStr);
258             } catch (ServiceSpecificException e) {
259                 handleServiceSpecificException(e, methodStr);
260             }
261             return null;
262         }
263     }
264 
265     /**
266      * See comments for {@link IWifiChip#enableDebugErrorAlerts(boolean)}
267      */
268     @Override
enableDebugErrorAlerts(boolean enable)269     public boolean enableDebugErrorAlerts(boolean enable) {
270         final String methodStr = "enableDebugErrorAlerts";
271         synchronized (mLock) {
272             try {
273                 if (!checkIfaceAndLogFailure(methodStr)) return false;
274                 mWifiChip.enableDebugErrorAlerts(enable);
275                 return true;
276             } catch (RemoteException e) {
277                 handleRemoteException(e, methodStr);
278             } catch (ServiceSpecificException e) {
279                 handleServiceSpecificException(e, methodStr);
280             }
281             return false;
282         }
283     }
284 
285     /**
286      * See comments for {@link IWifiChip#flushRingBufferToFile()}
287      */
288     @Override
flushRingBufferToFile()289     public boolean flushRingBufferToFile() {
290         final String methodStr = "flushRingBufferToFile";
291         synchronized (mLock) {
292             try {
293                 if (!checkIfaceAndLogFailure(methodStr)) return false;
294                 mWifiChip.flushRingBufferToFile();
295                 return true;
296             } catch (RemoteException e) {
297                 handleRemoteException(e, methodStr);
298             } catch (ServiceSpecificException e) {
299                 handleServiceSpecificException(e, methodStr);
300             }
301             return false;
302         }
303     }
304 
305     /**
306      * See comments for {@link IWifiChip#forceDumpToDebugRingBuffer(String)}
307      */
308     @Override
forceDumpToDebugRingBuffer(String ringName)309     public boolean forceDumpToDebugRingBuffer(String ringName) {
310         final String methodStr = "forceDumpToDebugRingBuffer";
311         synchronized (mLock) {
312             try {
313                 if (!checkIfaceAndLogFailure(methodStr)) return false;
314                 mWifiChip.forceDumpToDebugRingBuffer(ringName);
315                 return true;
316             } catch (RemoteException e) {
317                 handleRemoteException(e, methodStr);
318             } catch (ServiceSpecificException e) {
319                 handleServiceSpecificException(e, methodStr);
320             }
321             return false;
322         }
323     }
324 
325     /**
326      * See comments for {@link IWifiChip#getApIface(String)}
327      */
328     @Override
329     @Nullable
getApIface(String ifaceName)330     public WifiApIface getApIface(String ifaceName) {
331         final String methodStr = "getApIface";
332         synchronized (mLock) {
333             try {
334                 if (!checkIfaceAndLogFailure(methodStr)) return null;
335                 IWifiApIface iface = mWifiChip.getApIface(ifaceName);
336                 return new WifiApIface(iface);
337             } catch (RemoteException e) {
338                 handleRemoteException(e, methodStr);
339             } catch (ServiceSpecificException e) {
340                 handleServiceSpecificException(e, methodStr);
341             }
342             return null;
343         }
344     }
345 
346     /**
347      * See comments for {@link IWifiChip#getApIfaceNames()}
348      */
349     @Override
350     @Nullable
getApIfaceNames()351     public List<String> getApIfaceNames() {
352         final String methodStr = "getApIfaceNames";
353         synchronized (mLock) {
354             try {
355                 if (!checkIfaceAndLogFailure(methodStr)) return null;
356                 String[] ifaceNames = mWifiChip.getApIfaceNames();
357                 return Arrays.asList(ifaceNames);
358             } catch (RemoteException e) {
359                 handleRemoteException(e, methodStr);
360             } catch (ServiceSpecificException e) {
361                 handleServiceSpecificException(e, methodStr);
362             }
363             return null;
364         }
365     }
366 
367     /**
368      * See comments for {@link IWifiChip#getAvailableModes()}
369      */
370     @Override
371     @Nullable
getAvailableModes()372     public List<WifiChip.ChipMode> getAvailableModes() {
373         final String methodStr = "getAvailableModes";
374         synchronized (mLock) {
375             try {
376                 if (!checkIfaceAndLogFailure(methodStr)) return null;
377                 android.hardware.wifi.IWifiChip.ChipMode[] halModes = mWifiChip.getAvailableModes();
378                 return halToFrameworkChipModeList(halModes);
379             } catch (RemoteException e) {
380                 handleRemoteException(e, methodStr);
381             } catch (ServiceSpecificException e) {
382                 handleServiceSpecificException(e, methodStr);
383             }
384             return null;
385         }
386     }
387 
388     /**
389      * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()}
390      */
391     @Override
getCapabilitiesBeforeIfacesExist()392     public WifiChip.Response<Long> getCapabilitiesBeforeIfacesExist() {
393         final String methodStr = "getCapabilitiesBeforeIfacesExist";
394         return getCapabilitiesInternal(methodStr);
395     }
396 
397     /**
398      * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()}
399      */
400     @Override
getCapabilitiesAfterIfacesExist()401     public WifiChip.Response<Long> getCapabilitiesAfterIfacesExist() {
402         final String methodStr = "getCapabilitiesAfterIfacesExist";
403         return getCapabilitiesInternal(methodStr);
404     }
405 
getCapabilitiesInternal(String methodStr)406     private WifiChip.Response<Long> getCapabilitiesInternal(String methodStr) {
407         // getCapabilities uses the same logic in AIDL, regardless of whether the call
408         // happens before or after any interfaces have been created.
409         WifiChip.Response<Long> featuresResp = new WifiChip.Response<>(0L);
410         synchronized (mLock) {
411             try {
412                 if (!checkIfaceAndLogFailure(methodStr)) return featuresResp;
413                 mHalFeatureSet = mWifiChip.getFeatureSet();
414                 featuresResp.setValue(halToFrameworkChipFeatureSet(mHalFeatureSet));
415                 featuresResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS);
416             } catch (RemoteException e) {
417                 handleRemoteException(e, methodStr);
418                 featuresResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION);
419             } catch (ServiceSpecificException e) {
420                 handleServiceSpecificException(e, methodStr);
421                 // TODO: convert to framework status code once WifiHalAidlImpl exists
422                 featuresResp.setStatusCode(e.errorCode);
423             }
424             return featuresResp;
425         }
426     }
427 
428     /**
429      * See comments for {@link IWifiChip#getDebugHostWakeReasonStats()}
430      */
431     @Override
432     @Nullable
getDebugHostWakeReasonStats()433     public WlanWakeReasonAndCounts getDebugHostWakeReasonStats() {
434         final String methodStr = "getDebugHostWakeReasonStats";
435         synchronized (mLock) {
436             try {
437                 if (!checkIfaceAndLogFailure(methodStr)) return null;
438                 WifiDebugHostWakeReasonStats stats = mWifiChip.getDebugHostWakeReasonStats();
439                 return halToFrameworkWakeReasons(stats);
440             } catch (RemoteException e) {
441                 handleRemoteException(e, methodStr);
442             } catch (ServiceSpecificException e) {
443                 handleServiceSpecificException(e, methodStr);
444             }
445             return null;
446         }
447     }
448 
449     /**
450      * See comments for {@link IWifiChip#getDebugRingBuffersStatus()}
451      */
452     @Override
453     @Nullable
getDebugRingBuffersStatus()454     public List<WifiNative.RingBufferStatus> getDebugRingBuffersStatus() {
455         final String methodStr = "getDebugRingBuffersStatus";
456         synchronized (mLock) {
457             try {
458                 if (!checkIfaceAndLogFailure(methodStr)) return null;
459                 WifiDebugRingBufferStatus[] stats = mWifiChip.getDebugRingBuffersStatus();
460                 return halToFrameworkRingBufferStatusList(stats);
461             } catch (RemoteException e) {
462                 handleRemoteException(e, methodStr);
463             } catch (ServiceSpecificException e) {
464                 handleServiceSpecificException(e, methodStr);
465             } catch (IllegalArgumentException e) {
466                 handleIllegalArgumentException(e, methodStr);
467             }
468             return null;
469         }
470     }
471 
472     /**
473      * See comments for {@link IWifiChip#getId()}
474      */
475     @Override
getId()476     public int getId() {
477         final String methodStr = "getId";
478         synchronized (mLock) {
479             try {
480                 if (!checkIfaceAndLogFailure(methodStr)) return -1;
481                 return mWifiChip.getId();
482             } catch (RemoteException e) {
483                 handleRemoteException(e, methodStr);
484             } catch (ServiceSpecificException e) {
485                 handleServiceSpecificException(e, methodStr);
486             }
487             return -1;
488         }
489     }
490 
491     /**
492      * See comments for {@link IWifiChip#getMode()}
493      */
494     @Override
getMode()495     public WifiChip.Response<Integer> getMode() {
496         final String methodStr = "getMode";
497         WifiChip.Response<Integer> modeResp = new WifiChip.Response<>(0);
498         synchronized (mLock) {
499             try {
500                 if (!checkIfaceAndLogFailure(methodStr)) return modeResp;
501                 int mode = mWifiChip.getMode();
502                 modeResp.setValue(mode);
503                 modeResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS);
504             } catch (RemoteException e) {
505                 handleRemoteException(e, methodStr);
506                 modeResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION);
507             } catch (ServiceSpecificException e) {
508                 handleServiceSpecificException(e, methodStr);
509                 // TODO: convert to framework status code once WifiHalAidlImpl exists
510                 modeResp.setStatusCode(e.errorCode);
511             }
512             return modeResp;
513         }
514     }
515 
516     /**
517      * See comments for {@link IWifiChip#getNanIface(String)}
518      */
519     @Override
520     @Nullable
getNanIface(String ifaceName)521     public WifiNanIface getNanIface(String ifaceName) {
522         final String methodStr = "getNanIface";
523         synchronized (mLock) {
524             try {
525                 if (!checkIfaceAndLogFailure(methodStr)) return null;
526                 IWifiNanIface iface = mWifiChip.getNanIface(ifaceName);
527                 return new WifiNanIface(iface);
528             } catch (RemoteException e) {
529                 handleRemoteException(e, methodStr);
530             } catch (ServiceSpecificException e) {
531                 handleServiceSpecificException(e, methodStr);
532             }
533             return null;
534         }
535     }
536 
537     /**
538      * See comments for {@link IWifiChip#getNanIfaceNames()}
539      */
540     @Override
541     @Nullable
getNanIfaceNames()542     public List<String> getNanIfaceNames() {
543         final String methodStr = "getNanIfaceNames";
544         synchronized (mLock) {
545             try {
546                 if (!checkIfaceAndLogFailure(methodStr)) return null;
547                 String[] ifaceNames = mWifiChip.getNanIfaceNames();
548                 return Arrays.asList(ifaceNames);
549             } catch (RemoteException e) {
550                 handleRemoteException(e, methodStr);
551             } catch (ServiceSpecificException e) {
552                 handleServiceSpecificException(e, methodStr);
553             }
554             return null;
555         }
556     }
557 
558     /**
559      * See comments for {@link IWifiChip#getP2pIface(String)}
560      */
561     @Override
562     @Nullable
getP2pIface(String ifaceName)563     public WifiP2pIface getP2pIface(String ifaceName) {
564         final String methodStr = "getP2pIface";
565         synchronized (mLock) {
566             try {
567                 if (!checkIfaceAndLogFailure(methodStr)) return null;
568                 IWifiP2pIface iface = mWifiChip.getP2pIface(ifaceName);
569                 return new WifiP2pIface(iface);
570             } catch (RemoteException e) {
571                 handleRemoteException(e, methodStr);
572             } catch (ServiceSpecificException e) {
573                 handleServiceSpecificException(e, methodStr);
574             }
575             return null;
576         }
577     }
578 
579     /**
580      * See comments for {@link IWifiChip#getP2pIfaceNames()}
581      */
582     @Override
583     @Nullable
getP2pIfaceNames()584     public List<String> getP2pIfaceNames() {
585         final String methodStr = "getP2pIfaceNames";
586         synchronized (mLock) {
587             try {
588                 if (!checkIfaceAndLogFailure(methodStr)) return null;
589                 String[] ifaceNames = mWifiChip.getP2pIfaceNames();
590                 return Arrays.asList(ifaceNames);
591             } catch (RemoteException e) {
592                 handleRemoteException(e, methodStr);
593             } catch (ServiceSpecificException e) {
594                 handleServiceSpecificException(e, methodStr);
595             }
596             return null;
597         }
598     }
599 
600     /**
601      * See comments for {@link IWifiChip#getStaIface(String)}
602      */
603     @Override
604     @Nullable
getStaIface(String ifaceName)605     public WifiStaIface getStaIface(String ifaceName) {
606         final String methodStr = "getStaIface";
607         synchronized (mLock) {
608             try {
609                 if (!checkIfaceAndLogFailure(methodStr)) return null;
610                 IWifiStaIface iface = mWifiChip.getStaIface(ifaceName);
611                 return new WifiStaIface(iface, mContext, mSsidTranslator);
612             } catch (RemoteException e) {
613                 handleRemoteException(e, methodStr);
614             } catch (ServiceSpecificException e) {
615                 handleServiceSpecificException(e, methodStr);
616             }
617             return null;
618         }
619     }
620 
621     /**
622      * See comments for {@link IWifiChip#getStaIfaceNames()}
623      */
624     @Override
625     @Nullable
getStaIfaceNames()626     public List<String> getStaIfaceNames() {
627         final String methodStr = "getStaIfaceNames";
628         synchronized (mLock) {
629             try {
630                 if (!checkIfaceAndLogFailure(methodStr)) return null;
631                 String[] ifaceNames = mWifiChip.getStaIfaceNames();
632                 return Arrays.asList(ifaceNames);
633             } catch (RemoteException e) {
634                 handleRemoteException(e, methodStr);
635             } catch (ServiceSpecificException e) {
636                 handleServiceSpecificException(e, methodStr);
637             }
638             return null;
639         }
640     }
641 
642     /**
643      * See comments for {@link IWifiChip#getSupportedRadioCombinations()}
644      */
645     @Override
646     @Nullable
getSupportedRadioCombinations()647     public List<WifiChip.WifiRadioCombination> getSupportedRadioCombinations() {
648         final String methodStr = "getSupportedRadioCombinations";
649         synchronized (mLock) {
650             try {
651                 if (!checkIfaceAndLogFailure(methodStr)) return null;
652                 WifiRadioCombination[] halCombos = mWifiChip.getSupportedRadioCombinations();
653                 return halToFrameworkRadioCombinations(halCombos);
654             } catch (RemoteException e) {
655                 handleRemoteException(e, methodStr);
656             } catch (ServiceSpecificException e) {
657                 handleServiceSpecificException(e, methodStr);
658             }
659             return null;
660         }
661     }
662 
663     /**
664      * See comments for {@link IWifiChip#getWifiChipCapabilities()}
665      */
getWifiChipCapabilities()666     public WifiChip.WifiChipCapabilities getWifiChipCapabilities() {
667         final String methodStr = "getWifiChipCapabilities";
668         synchronized (mLock) {
669             try {
670                 if (!checkIfaceAndLogFailure(methodStr)) return null;
671                 WifiChipCapabilities halCapab = mWifiChip.getWifiChipCapabilities();
672                 return halToFrameworkWifiChipCapabilities(halCapab);
673             } catch (RemoteException e) {
674                 handleRemoteException(e, methodStr);
675             } catch (ServiceSpecificException e) {
676                 handleServiceSpecificException(e, methodStr);
677             }
678             return null;
679         }
680     }
681 
682     /**
683      * See comments for {@link IWifiChip#getUsableChannels(int, int, int)}
684      */
685     @Override
686     @Nullable
getUsableChannels(@ifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter)687     public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band,
688             @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) {
689         final String methodStr = "getUsableChannels";
690         synchronized (mLock) {
691             try {
692                 if (!checkIfaceAndLogFailure(methodStr)) return null;
693                 WifiUsableChannel[] halChannels = mWifiChip.getUsableChannels(
694                         frameworkToHalWifiBand(band),
695                         frameworkToHalIfaceMode(mode),
696                         frameworkToHalUsableFilter(filter));
697                 List<WifiAvailableChannel> frameworkChannels = new ArrayList<>();
698                 for (WifiUsableChannel ch : halChannels) {
699                     frameworkChannels.add(new WifiAvailableChannel(
700                             ch.channel, halToFrameworkIfaceMode(ch.ifaceModeMask),
701                             halToFrameworkChannelWidth(ch.channelBandwidth)));
702                 }
703                 return frameworkChannels;
704             } catch (RemoteException e) {
705                 handleRemoteException(e, methodStr);
706             } catch (ServiceSpecificException e) {
707                 handleServiceSpecificException(e, methodStr);
708             } catch (IllegalArgumentException e) {
709                 handleIllegalArgumentException(e, methodStr);
710             }
711             return null;
712         }
713     }
714 
halToFrameworkChannelWidth(int channelBandwidth)715     private @WifiAnnotations.ChannelWidth int halToFrameworkChannelWidth(int channelBandwidth) {
716         switch(channelBandwidth) {
717             case WIDTH_40:
718                 return ScanResult.CHANNEL_WIDTH_40MHZ;
719             case WIDTH_80:
720                 return ScanResult.CHANNEL_WIDTH_80MHZ;
721             case WIDTH_160:
722                 return ScanResult.CHANNEL_WIDTH_160MHZ;
723             case WIDTH_80P80:
724                 return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
725             case WIDTH_320:
726                 return ScanResult.CHANNEL_WIDTH_320MHZ;
727             default:
728                 return ScanResult.CHANNEL_WIDTH_20MHZ;
729         }
730     }
731 
732     /**
733      * See comments for {@link IWifiChip#registerCallback(WifiChip.Callback)}
734      */
735     @Override
registerCallback(WifiChip.Callback callback)736     public boolean registerCallback(WifiChip.Callback callback) {
737         final String methodStr = "registerCallback";
738         synchronized (mLock) {
739             if (!checkIfaceAndLogFailure(methodStr)) return false;
740             if (mFrameworkCallback != null) {
741                 Log.e(TAG, "Framework callback is already registered");
742                 return false;
743             } else if (callback == null) {
744                 Log.e(TAG, "Cannot register a null callback");
745                 return false;
746             }
747 
748             try {
749                 mHalCallback = new ChipEventCallback();
750                 mWifiChip.registerEventCallback(mHalCallback);
751                 mFrameworkCallback = callback;
752                 return true;
753             } catch (RemoteException e) {
754                 handleRemoteException(e, methodStr);
755             } catch (ServiceSpecificException e) {
756                 handleServiceSpecificException(e, methodStr);
757             }
758             return false;
759         }
760     }
761 
762     /**
763      * See comments for {@link IWifiChip#removeApIface(String)}
764      */
765     @Override
removeApIface(String ifaceName)766     public boolean removeApIface(String ifaceName) {
767         final String methodStr = "removeApIface";
768         synchronized (mLock) {
769             try {
770                 if (!checkIfaceAndLogFailure(methodStr)) return false;
771                 mWifiChip.removeApIface(ifaceName);
772                 return true;
773             } catch (RemoteException e) {
774                 handleRemoteException(e, methodStr);
775             } catch (ServiceSpecificException e) {
776                 handleServiceSpecificException(e, methodStr);
777             }
778             return false;
779         }
780     }
781 
782     /**
783      * See comments for {@link IWifiChip#removeIfaceInstanceFromBridgedApIface(String, String)}
784      */
785     @Override
removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName)786     public boolean removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName) {
787         final String methodStr = "removeIfaceInstanceFromBridgedApIface";
788         synchronized (mLock) {
789             try {
790                 if (!checkIfaceAndLogFailure(methodStr)) return false;
791                 mWifiChip.removeIfaceInstanceFromBridgedApIface(brIfaceName, ifaceName);
792                 return true;
793             } catch (RemoteException e) {
794                 handleRemoteException(e, methodStr);
795             } catch (ServiceSpecificException e) {
796                 handleServiceSpecificException(e, methodStr);
797             }
798             return false;
799         }
800     }
801 
802     /**
803      * See comments for {@link IWifiChip#removeNanIface(String)}
804      */
805     @Override
removeNanIface(String ifaceName)806     public boolean removeNanIface(String ifaceName) {
807         final String methodStr = "removeNanIface";
808         synchronized (mLock) {
809             try {
810                 if (!checkIfaceAndLogFailure(methodStr)) return false;
811                 mWifiChip.removeNanIface(ifaceName);
812                 return true;
813             } catch (RemoteException e) {
814                 handleRemoteException(e, methodStr);
815             } catch (ServiceSpecificException e) {
816                 handleServiceSpecificException(e, methodStr);
817             }
818             return false;
819         }
820     }
821 
822     /**
823      * See comments for {@link IWifiChip#removeP2pIface(String)}
824      */
825     @Override
removeP2pIface(String ifaceName)826     public boolean removeP2pIface(String ifaceName) {
827         final String methodStr = "removeP2pIface";
828         synchronized (mLock) {
829             try {
830                 if (!checkIfaceAndLogFailure(methodStr)) return false;
831                 mWifiChip.removeP2pIface(ifaceName);
832                 return true;
833             } catch (RemoteException e) {
834                 handleRemoteException(e, methodStr);
835             } catch (ServiceSpecificException e) {
836                 handleServiceSpecificException(e, methodStr);
837             }
838             return false;
839         }
840     }
841 
842     /**
843      * See comments for {@link IWifiChip#removeStaIface(String)}
844      */
845     @Override
removeStaIface(String ifaceName)846     public boolean removeStaIface(String ifaceName) {
847         final String methodStr = "removeStaIface";
848         synchronized (mLock) {
849             try {
850                 if (!checkIfaceAndLogFailure(methodStr)) return false;
851                 mWifiChip.removeStaIface(ifaceName);
852                 return true;
853             } catch (RemoteException e) {
854                 handleRemoteException(e, methodStr);
855             } catch (ServiceSpecificException e) {
856                 handleServiceSpecificException(e, methodStr);
857             }
858             return false;
859         }
860     }
861 
862     /**
863      * See comments for {@link IWifiChip#requestChipDebugInfo()}
864      */
865     @Override
866     @Nullable
requestChipDebugInfo()867     public WifiChip.ChipDebugInfo requestChipDebugInfo() {
868         final String methodStr = "requestChipDebugInfo";
869         synchronized (mLock) {
870             try {
871                 if (!checkIfaceAndLogFailure(methodStr)) return null;
872                 android.hardware.wifi.IWifiChip.ChipDebugInfo info =
873                         mWifiChip.requestChipDebugInfo();
874                 return new WifiChip.ChipDebugInfo(info.driverDescription, info.firmwareDescription);
875             } catch (RemoteException e) {
876                 handleRemoteException(e, methodStr);
877             } catch (ServiceSpecificException e) {
878                 handleServiceSpecificException(e, methodStr);
879             }
880             return null;
881         }
882     }
883 
884     /**
885      * See comments for {@link IWifiChip#requestDriverDebugDump()}
886      */
887     @Override
888     @Nullable
requestDriverDebugDump()889     public byte[] requestDriverDebugDump() {
890         final String methodStr = "requestDriverDebugDump";
891         synchronized (mLock) {
892             try {
893                 if (!checkIfaceAndLogFailure(methodStr)) return null;
894                 return mWifiChip.requestDriverDebugDump();
895             } catch (RemoteException e) {
896                 handleRemoteException(e, methodStr);
897             } catch (ServiceSpecificException e) {
898                 handleServiceSpecificException(e, methodStr);
899             }
900             return null;
901         }
902     }
903 
904     /**
905      * See comments for {@link IWifiChip#requestFirmwareDebugDump()}
906      */
907     @Override
908     @Nullable
requestFirmwareDebugDump()909     public byte[] requestFirmwareDebugDump() {
910         final String methodStr = "requestFirmwareDebugDump";
911         synchronized (mLock) {
912             try {
913                 if (!checkIfaceAndLogFailure(methodStr)) return null;
914                 return mWifiChip.requestFirmwareDebugDump();
915             } catch (RemoteException e) {
916                 handleRemoteException(e, methodStr);
917             } catch (ServiceSpecificException e) {
918                 handleServiceSpecificException(e, methodStr);
919             }
920             return null;
921         }
922     }
923 
924     /**
925      * See comments for {@link IWifiChip#selectTxPowerScenario(SarInfo)}
926      */
927     @Override
selectTxPowerScenario(SarInfo sarInfo)928     public boolean selectTxPowerScenario(SarInfo sarInfo) {
929         final String methodStr = "selectTxPowerScenario";
930         synchronized (mLock) {
931             try {
932                 if (!checkIfaceAndLogFailure(methodStr)) return false;
933                 if (sarPowerBackoffRequired(sarInfo)) {
934                     // Power backoff is needed, so calculate and set the required scenario.
935                     int halScenario = frameworkToHalTxPowerScenario(sarInfo);
936                     if (sarInfo.setSarScenarioNeeded(halScenario)) {
937                         Log.d(TAG, "Attempting to set SAR scenario to " + halScenario);
938                         mWifiChip.selectTxPowerScenario(halScenario);
939                     }
940                     // Reaching here means that setting SAR scenario would be redundant,
941                     // do nothing and return with success.
942                     return true;
943                 }
944 
945                 // We don't need to perform power backoff, so attempt to reset the SAR scenario.
946                 if (sarInfo.resetSarScenarioNeeded()) {
947                     Log.d(TAG, "Attempting to reset the SAR scenario");
948                     mWifiChip.resetTxPowerScenario();
949                 }
950 
951                 // If no if-statement was executed, then setting/resetting the SAR scenario would
952                 // have been redundant. Do nothing and return with success.
953                 return true;
954             } catch (RemoteException e) {
955                 handleRemoteException(e, methodStr);
956             } catch (ServiceSpecificException e) {
957                 handleServiceSpecificException(e, methodStr);
958             } catch (IllegalArgumentException e) {
959                 handleIllegalArgumentException(e, methodStr);
960             }
961             return false;
962         }
963     }
964 
965     /**
966      * See comments for {@link IWifiChip#setCoexUnsafeChannels(List, int)}
967      */
968     @Override
setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions)969     public boolean setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions) {
970         final String methodStr = "setCoexUnsafeChannels";
971         synchronized (mLock) {
972             try {
973                 if (!checkIfaceAndLogFailure(methodStr)) return false;
974                 android.hardware.wifi.IWifiChip.CoexUnsafeChannel[] halChannels =
975                         frameworkToHalCoexUnsafeChannels(unsafeChannels);
976                 int halRestrictions = frameworkToHalCoexRestrictions(restrictions);
977                 mWifiChip.setCoexUnsafeChannels(halChannels, halRestrictions);
978                 return true;
979             } catch (RemoteException e) {
980                 handleRemoteException(e, methodStr);
981             } catch (ServiceSpecificException e) {
982                 handleServiceSpecificException(e, methodStr);
983             }
984             return false;
985         }
986     }
987 
988     /**
989      * See comments for {@link IWifiChip#setCountryCode(byte[])}
990      */
991     @Override
setCountryCode(byte[] code)992     public boolean setCountryCode(byte[] code) {
993         final String methodStr = "setCountryCode";
994         synchronized (mLock) {
995             try {
996                 if (!checkIfaceAndLogFailure(methodStr)) return false;
997                 mWifiChip.setCountryCode(code);
998                 return true;
999             } catch (RemoteException e) {
1000                 handleRemoteException(e, methodStr);
1001             } catch (ServiceSpecificException e) {
1002                 handleServiceSpecificException(e, methodStr);
1003             }
1004             return false;
1005         }
1006     }
1007 
1008     /**
1009      * See comments for {@link IWifiChip#setLowLatencyMode(boolean)}
1010      */
1011     @Override
setLowLatencyMode(boolean enable)1012     public boolean setLowLatencyMode(boolean enable) {
1013         final String methodStr = "setLowLatencyMode";
1014         synchronized (mLock) {
1015             try {
1016                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1017                 int mode = enable ? LatencyMode.LOW : LatencyMode.NORMAL;
1018                 mWifiChip.setLatencyMode(mode);
1019                 return true;
1020             } catch (RemoteException e) {
1021                 handleRemoteException(e, methodStr);
1022             } catch (ServiceSpecificException e) {
1023                 handleServiceSpecificException(e, methodStr);
1024             }
1025             return false;
1026         }
1027     }
1028 
1029     /**
1030      * See comments for {@link IWifiChip#setMultiStaPrimaryConnection(String)}
1031      */
1032     @Override
setMultiStaPrimaryConnection(String ifaceName)1033     public boolean setMultiStaPrimaryConnection(String ifaceName) {
1034         final String methodStr = "setMultiStaPrimaryConnection";
1035         synchronized (mLock) {
1036             try {
1037                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1038                 mWifiChip.setMultiStaPrimaryConnection(ifaceName);
1039                 return true;
1040             } catch (RemoteException e) {
1041                 handleRemoteException(e, methodStr);
1042             } catch (ServiceSpecificException e) {
1043                 handleServiceSpecificException(e, methodStr);
1044             }
1045             return false;
1046         }
1047     }
1048 
1049     /**
1050      * See comments for {@link IWifiChip#setMultiStaUseCase(int)}
1051      */
1052     @Override
setMultiStaUseCase(@ifiNative.MultiStaUseCase int useCase)1053     public boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) {
1054         final String methodStr = "setMultiStaUseCase";
1055         synchronized (mLock) {
1056             try {
1057                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1058                 mWifiChip.setMultiStaUseCase(frameworkToHalMultiStaUseCase(useCase));
1059                 return true;
1060             } catch (RemoteException e) {
1061                 handleRemoteException(e, methodStr);
1062             } catch (ServiceSpecificException e) {
1063                 handleServiceSpecificException(e, methodStr);
1064             } catch (IllegalArgumentException e) {
1065                 handleIllegalArgumentException(e, methodStr);
1066             }
1067             return false;
1068         }
1069     }
1070 
1071     /**
1072      * See comments for {@link IWifiChip#startLoggingToDebugRingBuffer(String, int, int, int)}
1073      */
1074     @Override
startLoggingToDebugRingBuffer(String ringName, int verboseLevel, int maxIntervalInSec, int minDataSizeInBytes)1075     public boolean startLoggingToDebugRingBuffer(String ringName, int verboseLevel,
1076             int maxIntervalInSec, int minDataSizeInBytes) {
1077         final String methodStr = "startLoggingToDebugRingBuffer";
1078         synchronized (mLock) {
1079             try {
1080                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1081                 mWifiChip.startLoggingToDebugRingBuffer(
1082                         ringName, verboseLevel, maxIntervalInSec, minDataSizeInBytes);
1083                 return true;
1084             } catch (RemoteException e) {
1085                 handleRemoteException(e, methodStr);
1086             } catch (ServiceSpecificException e) {
1087                 handleServiceSpecificException(e, methodStr);
1088             }
1089             return false;
1090         }
1091     }
1092 
1093     /**
1094      * See comments for {@link IWifiChip#stopLoggingToDebugRingBuffer()}
1095      */
1096     @Override
stopLoggingToDebugRingBuffer()1097     public boolean stopLoggingToDebugRingBuffer() {
1098         final String methodStr = "stopLoggingToDebugRingBuffer";
1099         synchronized (mLock) {
1100             try {
1101                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1102                 mWifiChip.stopLoggingToDebugRingBuffer();
1103                 return true;
1104             } catch (RemoteException e) {
1105                 handleRemoteException(e, methodStr);
1106             } catch (ServiceSpecificException e) {
1107                 handleServiceSpecificException(e, methodStr);
1108             }
1109             return false;
1110         }
1111     }
1112 
1113     /**
1114      * See comments for {@link IWifiChip#triggerSubsystemRestart()}
1115      */
1116     @Override
triggerSubsystemRestart()1117     public boolean triggerSubsystemRestart() {
1118         final String methodStr = "triggerSubsystemRestart";
1119         synchronized (mLock) {
1120             try {
1121                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1122                 mWifiChip.triggerSubsystemRestart();
1123                 return true;
1124             } catch (RemoteException e) {
1125                 handleRemoteException(e, methodStr);
1126             } catch (ServiceSpecificException e) {
1127                 handleServiceSpecificException(e, methodStr);
1128             }
1129             return false;
1130         }
1131     }
1132 
1133     /**
1134      * See comments for {@link IWifiChip#enableStaChannelForPeerNetwork(boolean, boolean)}
1135      */
1136     @Override
enableStaChannelForPeerNetwork(boolean enableIndoorChannel, boolean enableDfsChannel)1137     public boolean enableStaChannelForPeerNetwork(boolean enableIndoorChannel,
1138             boolean enableDfsChannel) {
1139         final String methodStr = "enableStaChannelForPeerNetwork";
1140         synchronized (mLock) {
1141             try {
1142                 if (!checkIfaceAndLogFailure(methodStr)) return false;
1143                 int halChannelCategoryEnableFlag = 0;
1144                 if (enableIndoorChannel) {
1145                     halChannelCategoryEnableFlag |= ChannelCategoryMask.INDOOR_CHANNEL;
1146                 }
1147                 if (enableDfsChannel) {
1148                     halChannelCategoryEnableFlag |= ChannelCategoryMask.DFS_CHANNEL;
1149                 }
1150                 mWifiChip.enableStaChannelForPeerNetwork(halChannelCategoryEnableFlag);
1151                 return true;
1152             } catch (RemoteException e) {
1153                 handleRemoteException(e, methodStr);
1154             } catch (ServiceSpecificException e) {
1155                 handleServiceSpecificException(e, methodStr);
1156             }
1157             return false;
1158         }
1159     }
1160 
1161     /**
1162      * See comments for {@link IWifiChip#setVoipMode(int)}
1163      */
1164     @Override
setVoipMode(@ifiChip.WifiVoipMode int mode)1165     public boolean setVoipMode(@WifiChip.WifiVoipMode int mode) {
1166         final String methodStr = "setVoipMode";
1167         synchronized (mLock) {
1168             try {
1169                 if (!checkIfaceAndLogFailure(methodStr)
1170                         || !WifiHalAidlImpl.isServiceVersionAtLeast(2)
1171                         || !bitmapContains(mHalFeatureSet, FeatureSetMask.SET_VOIP_MODE)) {
1172                     return false;
1173                 }
1174                 mWifiChip.setVoipMode(frameworkToHalVoipMode(mode));
1175                 return true;
1176             } catch (RemoteException e) {
1177                 handleRemoteException(e, methodStr);
1178             } catch (ServiceSpecificException e) {
1179                 handleServiceSpecificException(e, methodStr);
1180             } catch (IllegalArgumentException e) {
1181                 handleIllegalArgumentException(e, methodStr);
1182             }
1183             return false;
1184         }
1185     }
1186 
1187     private class ChipEventCallback extends IWifiChipEventCallback.Stub {
1188         @Override
onChipReconfigured(int modeId)1189         public void onChipReconfigured(int modeId) throws RemoteException {
1190             if (mFrameworkCallback == null) return;
1191             mFrameworkCallback.onChipReconfigured(modeId);
1192         }
1193 
1194         @Override
onChipReconfigureFailure(int statusCode)1195         public void onChipReconfigureFailure(int statusCode) {
1196             if (mFrameworkCallback == null) return;
1197             // TODO: convert to framework status code once WifiHalAidlImpl exists
1198             mFrameworkCallback.onChipReconfigureFailure(statusCode);
1199         }
1200 
1201         @Override
onIfaceAdded(int type, String name)1202         public void onIfaceAdded(int type, String name) {
1203             if (mFrameworkCallback == null) return;
1204             mFrameworkCallback.onIfaceAdded(halToFrameworkIfaceType(type), name);
1205         }
1206 
1207         @Override
onIfaceRemoved(int type, String name)1208         public void onIfaceRemoved(int type, String name) {
1209             if (mFrameworkCallback == null) return;
1210             mFrameworkCallback.onIfaceRemoved(halToFrameworkIfaceType(type), name);
1211         }
1212 
1213         @Override
onDebugRingBufferDataAvailable(WifiDebugRingBufferStatus status, byte[] data)1214         public void onDebugRingBufferDataAvailable(WifiDebugRingBufferStatus status, byte[] data) {
1215             if (mFrameworkCallback == null) return;
1216             try {
1217                 mFrameworkCallback.onDebugRingBufferDataAvailable(
1218                         halToFrameworkRingBufferStatus(status), data);
1219             } catch (IllegalArgumentException e) {
1220                 handleIllegalArgumentException(e, "onDebugRingBufferDataAvailable");
1221             }
1222         }
1223 
1224         @Override
onDebugErrorAlert(int errorCode, byte[] debugData)1225         public void onDebugErrorAlert(int errorCode, byte[] debugData) {
1226             if (mFrameworkCallback == null) return;
1227             mFrameworkCallback.onDebugErrorAlert(errorCode, debugData);
1228         }
1229 
1230         @Override
onRadioModeChange(RadioModeInfo[] radioModeInfoList)1231         public void onRadioModeChange(RadioModeInfo[] radioModeInfoList) {
1232             if (mFrameworkCallback == null) return;
1233             List<WifiChip.RadioModeInfo> frameworkRadioModeInfos = new ArrayList<>();
1234             for (RadioModeInfo radioInfo : radioModeInfoList) {
1235                 List<WifiChip.IfaceInfo> frameworkIfaceInfos = new ArrayList<>();
1236                 for (IfaceInfo ifaceInfo : radioInfo.ifaceInfos) {
1237                     frameworkIfaceInfos.add(
1238                             new WifiChip.IfaceInfo(ifaceInfo.name, ifaceInfo.channel));
1239                 }
1240                 frameworkRadioModeInfos.add(
1241                         new WifiChip.RadioModeInfo(
1242                                 radioInfo.radioId, radioInfo.bandInfo, frameworkIfaceInfos));
1243             }
1244             mFrameworkCallback.onRadioModeChange(frameworkRadioModeInfos);
1245         }
1246 
1247         @Override
getInterfaceHash()1248         public String getInterfaceHash() {
1249             return IWifiChipEventCallback.HASH;
1250         }
1251 
1252         @Override
getInterfaceVersion()1253         public int getInterfaceVersion() {
1254             return IWifiChipEventCallback.VERSION;
1255         }
1256     }
1257 
1258 
1259     // Utilities
1260 
halToFrameworkIfaceConcurrencyType(int type)1261     private static @WifiChip.IfaceConcurrencyType int halToFrameworkIfaceConcurrencyType(int type) {
1262         switch (type) {
1263             case IfaceConcurrencyType.STA:
1264                 return WifiChip.IFACE_CONCURRENCY_TYPE_STA;
1265             case IfaceConcurrencyType.AP:
1266                 return WifiChip.IFACE_CONCURRENCY_TYPE_AP;
1267             case IfaceConcurrencyType.AP_BRIDGED:
1268                 return WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED;
1269             case IfaceConcurrencyType.P2P:
1270                 return WifiChip.IFACE_CONCURRENCY_TYPE_P2P;
1271             case IfaceConcurrencyType.NAN_IFACE:
1272                 return WifiChip.IFACE_CONCURRENCY_TYPE_NAN;
1273             default:
1274                 Log.e(TAG, "Invalid IfaceConcurrencyType received: " + type);
1275                 return -1;
1276         }
1277     }
1278 
halToFrameworkIfaceType(int type)1279     private static @WifiChip.IfaceType int halToFrameworkIfaceType(int type) {
1280         switch (type) {
1281             case IfaceType.STA:
1282                 return WifiChip.IFACE_TYPE_STA;
1283             case IfaceType.AP:
1284                 return WifiChip.IFACE_TYPE_AP;
1285             case IfaceType.P2P:
1286                 return WifiChip.IFACE_TYPE_P2P;
1287             case IfaceType.NAN_IFACE:
1288                 return WifiChip.IFACE_TYPE_NAN;
1289             default:
1290                 Log.e(TAG, "Invalid IfaceType received: " + type);
1291                 return -1;
1292         }
1293     }
1294 
halToFrameworkRingBufferStatusList( WifiDebugRingBufferStatus[] ringBuffers)1295     private static @Nullable List<WifiNative.RingBufferStatus> halToFrameworkRingBufferStatusList(
1296             WifiDebugRingBufferStatus[] ringBuffers) throws IllegalArgumentException {
1297         if (ringBuffers == null) return null;
1298         List<WifiNative.RingBufferStatus> ans = new ArrayList<>();
1299         for (WifiDebugRingBufferStatus b : ringBuffers) {
1300             ans.add(halToFrameworkRingBufferStatus(b));
1301         }
1302         return ans;
1303     }
1304 
halToFrameworkRingBufferStatus( WifiDebugRingBufferStatus h)1305     private static WifiNative.RingBufferStatus halToFrameworkRingBufferStatus(
1306             WifiDebugRingBufferStatus h) throws IllegalArgumentException {
1307         WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus();
1308         ans.name = h.ringName;
1309         ans.flag = halToFrameworkRingBufferFlags(h.flags);
1310         ans.ringBufferId = h.ringId;
1311         ans.ringBufferByteSize = h.sizeInBytes;
1312         ans.verboseLevel = h.verboseLevel;
1313         // Remaining fields are unavailable
1314         //  writtenBytes;
1315         //  readBytes;
1316         //  writtenRecords;
1317         return ans;
1318     }
1319 
halToFrameworkRingBufferFlags(int wifiDebugRingBufferFlag)1320     private static int halToFrameworkRingBufferFlags(int wifiDebugRingBufferFlag)
1321             throws IllegalArgumentException {
1322         BitMask checkoff = new BitMask(wifiDebugRingBufferFlag);
1323         int flags = 0;
1324         if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) {
1325             flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES;
1326         }
1327         if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) {
1328             flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES;
1329         }
1330         if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) {
1331             flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES;
1332         }
1333         if (checkoff.value != 0) {
1334             throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value);
1335         }
1336         return flags;
1337     }
1338 
halToFrameworkWakeReasons( WifiDebugHostWakeReasonStats h)1339     private static WlanWakeReasonAndCounts halToFrameworkWakeReasons(
1340             WifiDebugHostWakeReasonStats h) {
1341         if (h == null) return null;
1342         WlanWakeReasonAndCounts ans = new WlanWakeReasonAndCounts();
1343         ans.totalCmdEventWake = h.totalCmdEventWakeCnt;
1344         ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt;
1345         ans.totalRxDataWake = h.totalRxPacketWakeCnt;
1346         ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt;
1347         ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt;
1348         ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt;
1349         ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt;
1350         ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt;
1351         ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra;
1352         ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na;
1353         ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns;
1354         ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt;
1355         ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt;
1356         ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt;
1357         ans.cmdEventWakeCntArray = h.cmdEventWakeCntPerType;
1358         ans.driverFWLocalWakeCntArray = h.driverFwLocalWakeCntPerType;
1359         return ans;
1360     }
1361 
frameworkToHalMultiStaUseCase(@ifiNative.MultiStaUseCase int useCase)1362     private static byte frameworkToHalMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase)
1363             throws IllegalArgumentException {
1364         switch (useCase) {
1365             case WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY:
1366                 return MultiStaUseCase.DUAL_STA_TRANSIENT_PREFER_PRIMARY;
1367             case WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED:
1368                 return MultiStaUseCase.DUAL_STA_NON_TRANSIENT_UNBIASED;
1369             default:
1370                 throw new IllegalArgumentException("Invalid use case " + useCase);
1371         }
1372     }
1373 
1374     private static @NonNull android.hardware.wifi.IWifiChip.CoexUnsafeChannel[]
frameworkToHalCoexUnsafeChannels( @onNull List<android.net.wifi.CoexUnsafeChannel> frameworkUnsafeChannels)1375             frameworkToHalCoexUnsafeChannels(
1376             @NonNull List<android.net.wifi.CoexUnsafeChannel> frameworkUnsafeChannels) {
1377         final ArrayList<android.hardware.wifi.IWifiChip.CoexUnsafeChannel> halList =
1378                 new ArrayList<>();
1379         if (!SdkLevel.isAtLeastS()) {
1380             return new android.hardware.wifi.IWifiChip.CoexUnsafeChannel[0];
1381         }
1382         for (android.net.wifi.CoexUnsafeChannel frameworkUnsafeChannel : frameworkUnsafeChannels) {
1383             final android.hardware.wifi.IWifiChip.CoexUnsafeChannel halUnsafeChannel =
1384                     new android.hardware.wifi.IWifiChip.CoexUnsafeChannel();
1385             switch (frameworkUnsafeChannel.getBand()) {
1386                 case (WifiScanner.WIFI_BAND_24_GHZ):
1387                     halUnsafeChannel.band = WifiBand.BAND_24GHZ;
1388                     break;
1389                 case (WifiScanner.WIFI_BAND_5_GHZ):
1390                     halUnsafeChannel.band = WifiBand.BAND_5GHZ;
1391                     break;
1392                 case (WifiScanner.WIFI_BAND_6_GHZ):
1393                     halUnsafeChannel.band = WifiBand.BAND_6GHZ;
1394                     break;
1395                 case (WifiScanner.WIFI_BAND_60_GHZ):
1396                     halUnsafeChannel.band = WifiBand.BAND_60GHZ;
1397                     break;
1398                 default:
1399                     Log.e(TAG, "Tried to set unsafe channel with unknown band: "
1400                             + frameworkUnsafeChannel.getBand());
1401                     continue;
1402             }
1403             halUnsafeChannel.channel = frameworkUnsafeChannel.getChannel();
1404             final int powerCapDbm = frameworkUnsafeChannel.getPowerCapDbm();
1405             if (powerCapDbm != POWER_CAP_NONE) {
1406                 halUnsafeChannel.powerCapDbm = powerCapDbm;
1407             } else {
1408                 halUnsafeChannel.powerCapDbm =
1409                         android.hardware.wifi.IWifiChip.NO_POWER_CAP_CONSTANT;
1410             }
1411             halList.add(halUnsafeChannel);
1412         }
1413 
1414         android.hardware.wifi.IWifiChip.CoexUnsafeChannel[] halArray =
1415                 new android.hardware.wifi.IWifiChip.CoexUnsafeChannel[halList.size()];
1416         for (int i = 0; i < halList.size(); i++) {
1417             halArray[i] = halList.get(i);
1418         }
1419         return halArray;
1420     }
1421 
frameworkToHalCoexRestrictions( @ifiManager.CoexRestriction int restrictions)1422     private static int frameworkToHalCoexRestrictions(
1423             @WifiManager.CoexRestriction int restrictions) {
1424         int halRestrictions = 0;
1425         if (!SdkLevel.isAtLeastS()) {
1426             return halRestrictions;
1427         }
1428         if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) {
1429             halRestrictions |= CoexRestriction.WIFI_DIRECT;
1430         }
1431         if ((restrictions & WifiManager.COEX_RESTRICTION_SOFTAP) != 0) {
1432             halRestrictions |= CoexRestriction.SOFTAP;
1433         }
1434         if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_AWARE) != 0) {
1435             halRestrictions |= CoexRestriction.WIFI_AWARE;
1436         }
1437         return halRestrictions;
1438     }
1439 
1440     /**
1441      * Check if we need to backoff wifi Tx power due to SAR requirements.
1442      */
sarPowerBackoffRequired(SarInfo sarInfo)1443     private static boolean sarPowerBackoffRequired(SarInfo sarInfo) {
1444         if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) {
1445             return true;
1446         }
1447         if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) {
1448             return true;
1449         }
1450         return false;
1451     }
1452 
1453     /**
1454      * Maps the information in the SarInfo instance to a TxPowerScenario.
1455      * If SAR SoftAP input is supported, we make these assumptions:
1456      *   - All voice calls are treated as if device is near the head.
1457      *   - SoftAP scenario is treated as if device is near the body.
1458      * If SoftAP is not supported, the only valid scenario is when a voice call is ongoing.
1459      */
frameworkToHalTxPowerScenario(SarInfo sarInfo)1460     private static int frameworkToHalTxPowerScenario(SarInfo sarInfo)
1461             throws IllegalArgumentException {
1462         if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) {
1463             if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) {
1464                 return TxPowerScenario.ON_HEAD_CELL_ON;
1465             } else if (sarInfo.isWifiSapEnabled) {
1466                 return TxPowerScenario.ON_BODY_CELL_ON;
1467             } else {
1468                 throw new IllegalArgumentException("bad scenario: no voice call/softAP active");
1469             }
1470         } else if (sarInfo.sarVoiceCallSupported) {
1471             if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) {
1472                 return TxPowerScenario.VOICE_CALL;
1473             } else {
1474                 throw new IllegalArgumentException("bad scenario: voice call not active");
1475             }
1476         } else {
1477             throw new IllegalArgumentException("Invalid case: voice call not supported");
1478         }
1479     }
1480 
frameworkToHalWifiBand(int frameworkBand)1481     private static int frameworkToHalWifiBand(int frameworkBand) throws IllegalArgumentException {
1482         switch (frameworkBand) {
1483             case WifiScanner.WIFI_BAND_UNSPECIFIED:
1484                 return WifiBand.BAND_UNSPECIFIED;
1485             case WifiScanner.WIFI_BAND_24_GHZ:
1486                 return WifiBand.BAND_24GHZ;
1487             case WifiScanner.WIFI_BAND_5_GHZ:
1488                 return WifiBand.BAND_5GHZ;
1489             case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
1490                 return WifiBand.BAND_5GHZ_DFS;
1491             case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS:
1492                 return WifiBand.BAND_5GHZ_WITH_DFS;
1493             case WifiScanner.WIFI_BAND_BOTH:
1494                 return WifiBand.BAND_24GHZ_5GHZ;
1495             case WifiScanner.WIFI_BAND_BOTH_WITH_DFS:
1496                 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS;
1497             case WifiScanner.WIFI_BAND_6_GHZ:
1498                 return WifiBand.BAND_6GHZ;
1499             case WifiScanner.WIFI_BAND_24_5_6_GHZ:
1500                 return WifiBand.BAND_24GHZ_5GHZ_6GHZ;
1501             case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ:
1502                 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ;
1503             case WifiScanner.WIFI_BAND_60_GHZ:
1504                 return WifiBand.BAND_60GHZ;
1505             case WifiScanner.WIFI_BAND_24_5_6_60_GHZ:
1506                 return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ;
1507             case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ:
1508                 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ;
1509             case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS:
1510             default:
1511                 throw new IllegalArgumentException("bad band " + frameworkBand);
1512         }
1513     }
1514 
frameworkToHalIfaceMode(@ifiAvailableChannel.OpMode int mode)1515     private static int frameworkToHalIfaceMode(@WifiAvailableChannel.OpMode int mode) {
1516         int halMode = 0;
1517         if ((mode & WifiAvailableChannel.OP_MODE_STA) != 0) {
1518             halMode |= WifiIfaceMode.IFACE_MODE_STA;
1519         }
1520         if ((mode & WifiAvailableChannel.OP_MODE_SAP) != 0) {
1521             halMode |= WifiIfaceMode.IFACE_MODE_SOFTAP;
1522         }
1523         if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI) != 0) {
1524             halMode |= WifiIfaceMode.IFACE_MODE_P2P_CLIENT;
1525         }
1526         if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO) != 0) {
1527             halMode |= WifiIfaceMode.IFACE_MODE_P2P_GO;
1528         }
1529         if ((mode & WifiAvailableChannel.OP_MODE_WIFI_AWARE) != 0) {
1530             halMode |= WifiIfaceMode.IFACE_MODE_NAN;
1531         }
1532         if ((mode & WifiAvailableChannel.OP_MODE_TDLS) != 0) {
1533             halMode |= WifiIfaceMode.IFACE_MODE_TDLS;
1534         }
1535         return halMode;
1536     }
1537 
halToFrameworkIfaceMode(int halMode)1538     private static @WifiAvailableChannel.OpMode int halToFrameworkIfaceMode(int halMode) {
1539         int mode = 0;
1540         if ((halMode & WifiIfaceMode.IFACE_MODE_STA) != 0) {
1541             mode |= WifiAvailableChannel.OP_MODE_STA;
1542         }
1543         if ((halMode & WifiIfaceMode.IFACE_MODE_SOFTAP) != 0) {
1544             mode |= WifiAvailableChannel.OP_MODE_SAP;
1545         }
1546         if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_CLIENT) != 0) {
1547             mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI;
1548         }
1549         if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_GO) != 0) {
1550             mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO;
1551         }
1552         if ((halMode & WifiIfaceMode.IFACE_MODE_NAN) != 0) {
1553             mode |= WifiAvailableChannel.OP_MODE_WIFI_AWARE;
1554         }
1555         if ((halMode & WifiIfaceMode.IFACE_MODE_TDLS) != 0) {
1556             mode |= WifiAvailableChannel.OP_MODE_TDLS;
1557         }
1558         return mode;
1559     }
1560 
frameworkToHalUsableFilter(@ifiAvailableChannel.Filter int filter)1561     private static int frameworkToHalUsableFilter(@WifiAvailableChannel.Filter int filter) {
1562         int halFilter = 0;  // O implies no additional filter other than regulatory (default)
1563         if ((filter & WifiAvailableChannel.FILTER_CONCURRENCY) != 0) {
1564             halFilter |= UsableChannelFilter.CONCURRENCY;
1565         }
1566         if ((filter & WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE) != 0) {
1567             halFilter |= UsableChannelFilter.CELLULAR_COEXISTENCE;
1568         }
1569         if ((filter & WifiAvailableChannel.FILTER_NAN_INSTANT_MODE) != 0) {
1570             halFilter |= UsableChannelFilter.NAN_INSTANT_MODE;
1571         }
1572 
1573         return halFilter;
1574     }
1575 
frameworkToHalVoipMode(@ifiChip.WifiVoipMode int mode)1576     private static int frameworkToHalVoipMode(@WifiChip.WifiVoipMode int mode)
1577             throws IllegalArgumentException {
1578         switch (mode) {
1579             case WifiChip.WIFI_VOIP_MODE_OFF:
1580                 return VoipMode.OFF;
1581             case WifiChip.WIFI_VOIP_MODE_VOICE:
1582                 return VoipMode.VOICE;
1583             default:
1584                 throw new IllegalArgumentException("bad voip mode " + mode);
1585         }
1586     }
1587 
bitmapContains(long bitmap, long expectedBit)1588     private static boolean bitmapContains(long bitmap, long expectedBit) {
1589         return (bitmap & expectedBit) != 0;
1590     }
1591 
1592     @VisibleForTesting
halToFrameworkChipFeatureSet(long halFeatureSet)1593     protected static long halToFrameworkChipFeatureSet(long halFeatureSet) {
1594         long features = 0;
1595         if (bitmapContains(halFeatureSet, FeatureSetMask.SET_TX_POWER_LIMIT)) {
1596             features |= WifiManager.WIFI_FEATURE_TX_POWER_LIMIT;
1597         }
1598         if (bitmapContains(halFeatureSet, FeatureSetMask.D2D_RTT)) {
1599             features |= WifiManager.WIFI_FEATURE_D2D_RTT;
1600         }
1601         if (bitmapContains(halFeatureSet, FeatureSetMask.D2AP_RTT)) {
1602             features |= WifiManager.WIFI_FEATURE_D2AP_RTT;
1603         }
1604         if (bitmapContains(halFeatureSet, FeatureSetMask.SET_LATENCY_MODE)) {
1605             features |= WifiManager.WIFI_FEATURE_LOW_LATENCY;
1606         }
1607         if (bitmapContains(halFeatureSet, FeatureSetMask.P2P_RAND_MAC)) {
1608             features |= WifiManager.WIFI_FEATURE_P2P_RAND_MAC;
1609         }
1610         if (bitmapContains(halFeatureSet, FeatureSetMask.WIGIG)) {
1611             features |= WifiManager.WIFI_FEATURE_INFRA_60G;
1612         }
1613         if (bitmapContains(halFeatureSet, FeatureSetMask.T2LM_NEGOTIATION)) {
1614             features |= WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION;
1615         }
1616         return features;
1617     }
1618 
halToFrameworkWifiBand(int halBand)1619     private static int halToFrameworkWifiBand(int halBand) {
1620         int frameworkBand = 0;
1621         if (bitmapContains(halBand, WifiBand.BAND_24GHZ)) {
1622             frameworkBand |= WifiScanner.WIFI_BAND_24_GHZ;
1623         }
1624         if (bitmapContains(halBand, WifiBand.BAND_5GHZ)) {
1625             frameworkBand |= WifiScanner.WIFI_BAND_5_GHZ;
1626         }
1627         if (bitmapContains(halBand, WifiBand.BAND_5GHZ_DFS)) {
1628             frameworkBand |= WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY;
1629         }
1630         if (bitmapContains(halBand, WifiBand.BAND_6GHZ)) {
1631             frameworkBand |= WifiScanner.WIFI_BAND_6_GHZ;
1632         }
1633         if (bitmapContains(halBand, WifiBand.BAND_60GHZ)) {
1634             frameworkBand |= WifiScanner.WIFI_BAND_60_GHZ;
1635         }
1636         return frameworkBand;
1637     }
1638 
halToFrameworkAntennaMode(int mode)1639     private static @WifiChip.WifiAntennaMode int halToFrameworkAntennaMode(int mode) {
1640         switch (mode) {
1641             case WifiAntennaMode.WIFI_ANTENNA_MODE_UNSPECIFIED:
1642                 return WifiChip.WIFI_ANTENNA_MODE_UNSPECIFIED;
1643             case WifiAntennaMode.WIFI_ANTENNA_MODE_1X1:
1644                 return WifiChip.WIFI_ANTENNA_MODE_1X1;
1645             case WifiAntennaMode.WIFI_ANTENNA_MODE_2X2:
1646                 return WifiChip.WIFI_ANTENNA_MODE_2X2;
1647             case WifiAntennaMode.WIFI_ANTENNA_MODE_3X3:
1648                 return WifiChip.WIFI_ANTENNA_MODE_3X3;
1649             case WifiAntennaMode.WIFI_ANTENNA_MODE_4X4:
1650                 return WifiChip.WIFI_ANTENNA_MODE_4X4;
1651             default:
1652                 Log.e(TAG, "Invalid WifiAntennaMode: " + mode);
1653                 return WifiChip.WIFI_ANTENNA_MODE_UNSPECIFIED;
1654         }
1655     }
1656 
halToFrameworkChipModeList( android.hardware.wifi.IWifiChip.ChipMode[] halModes)1657     private static List<WifiChip.ChipMode> halToFrameworkChipModeList(
1658             android.hardware.wifi.IWifiChip.ChipMode[] halModes) {
1659         List<WifiChip.ChipMode> frameworkModes = new ArrayList<>();
1660         for (android.hardware.wifi.IWifiChip.ChipMode halMode : halModes) {
1661             frameworkModes.add(halToFrameworkChipMode(halMode));
1662         }
1663         return frameworkModes;
1664     }
1665 
halToFrameworkChipMode( android.hardware.wifi.IWifiChip.ChipMode halMode)1666     private static WifiChip.ChipMode halToFrameworkChipMode(
1667             android.hardware.wifi.IWifiChip.ChipMode halMode) {
1668         List<WifiChip.ChipConcurrencyCombination> frameworkCombos = new ArrayList<>();
1669         for (android.hardware.wifi.IWifiChip.ChipConcurrencyCombination halCombo :
1670                 halMode.availableCombinations) {
1671             frameworkCombos.add(halToFrameworkChipConcurrencyCombination(halCombo));
1672         }
1673         return new WifiChip.ChipMode(halMode.id, frameworkCombos);
1674     }
1675 
halToFrameworkChipConcurrencyCombination( android.hardware.wifi.IWifiChip.ChipConcurrencyCombination halCombo)1676     private static WifiChip.ChipConcurrencyCombination halToFrameworkChipConcurrencyCombination(
1677             android.hardware.wifi.IWifiChip.ChipConcurrencyCombination halCombo) {
1678         List<WifiChip.ChipConcurrencyCombinationLimit> frameworkLimits = new ArrayList<>();
1679         for (android.hardware.wifi.IWifiChip.ChipConcurrencyCombinationLimit halLimit :
1680                 halCombo.limits) {
1681             frameworkLimits.add(halToFrameworkChipConcurrencyCombinationLimit(halLimit));
1682         }
1683         return new WifiChip.ChipConcurrencyCombination(frameworkLimits);
1684     }
1685 
1686     private static WifiChip.ChipConcurrencyCombinationLimit
halToFrameworkChipConcurrencyCombinationLimit( android.hardware.wifi.IWifiChip.ChipConcurrencyCombinationLimit halLimit)1687             halToFrameworkChipConcurrencyCombinationLimit(
1688             android.hardware.wifi.IWifiChip.ChipConcurrencyCombinationLimit halLimit) {
1689         List<Integer> frameworkTypes = new ArrayList<>();
1690         for (int halType : halLimit.types) {
1691             frameworkTypes.add(halToFrameworkIfaceConcurrencyType(halType));
1692         }
1693         return new WifiChip.ChipConcurrencyCombinationLimit(halLimit.maxIfaces, frameworkTypes);
1694     }
1695 
halToFrameworkRadioCombinations( WifiRadioCombination[] halCombos)1696     private static List<WifiChip.WifiRadioCombination> halToFrameworkRadioCombinations(
1697             WifiRadioCombination[] halCombos) {
1698         List<WifiChip.WifiRadioCombination> frameworkCombos = new ArrayList<>();
1699         for (WifiRadioCombination combo : halCombos) {
1700             frameworkCombos.add(halToFrameworkRadioCombination(combo));
1701         }
1702         return frameworkCombos;
1703     }
1704 
1705     /**
1706      * Converts the framework version of an AvailableAfcFrequencyInfo object to its AIDL equivalent.
1707      */
frameworkToHalAvailableAfcFrequencyInfo( WifiChip.AvailableAfcFrequencyInfo availableFrequencyInfo)1708     private static AvailableAfcFrequencyInfo frameworkToHalAvailableAfcFrequencyInfo(
1709             WifiChip.AvailableAfcFrequencyInfo availableFrequencyInfo) {
1710         if (availableFrequencyInfo == null) {
1711             return null;
1712         }
1713 
1714         AvailableAfcFrequencyInfo halAvailableAfcFrequencyInfo = new AvailableAfcFrequencyInfo();
1715         halAvailableAfcFrequencyInfo.startFrequencyMhz = availableFrequencyInfo.startFrequencyMhz;
1716         halAvailableAfcFrequencyInfo.endFrequencyMhz = availableFrequencyInfo.endFrequencyMhz;
1717         halAvailableAfcFrequencyInfo.maxPsd = availableFrequencyInfo.maxPsdDbmPerMhz;
1718 
1719         return halAvailableAfcFrequencyInfo;
1720     }
1721 
1722     /**
1723      * Converts the framework version of an AvailableAfcChannelInfo object to its AIDL equivalent.
1724      */
frameworkToHalAvailableAfcChannelInfo( WifiChip.AvailableAfcChannelInfo availableChannelInfo)1725     private static AvailableAfcChannelInfo frameworkToHalAvailableAfcChannelInfo(
1726             WifiChip.AvailableAfcChannelInfo availableChannelInfo) {
1727         if (availableChannelInfo == null) {
1728             return null;
1729         }
1730 
1731         AvailableAfcChannelInfo halAvailableAfcChannelInfo = new AvailableAfcChannelInfo();
1732         halAvailableAfcChannelInfo.globalOperatingClass = availableChannelInfo.globalOperatingClass;
1733         halAvailableAfcChannelInfo.channelCfi = availableChannelInfo.channelCfi;
1734         halAvailableAfcChannelInfo.maxEirpDbm = availableChannelInfo.maxEirpDbm;
1735 
1736         return halAvailableAfcChannelInfo;
1737     }
1738 
frameworkToHalAfcChannelAllowance( WifiChip.AfcChannelAllowance afcChannelAllowance)1739     private static AfcChannelAllowance frameworkToHalAfcChannelAllowance(
1740             WifiChip.AfcChannelAllowance afcChannelAllowance) {
1741         AfcChannelAllowance halAfcChannelAllowance = new AfcChannelAllowance();
1742 
1743         // convert allowed frequencies and channels to their HAL version
1744         if (afcChannelAllowance.availableAfcFrequencyInfos == null) {
1745             // this should not be left uninitialized, or it may result in an exception
1746             halAfcChannelAllowance.availableAfcFrequencyInfos = new AvailableAfcFrequencyInfo[0];
1747         } else {
1748             halAfcChannelAllowance.availableAfcFrequencyInfos = new AvailableAfcFrequencyInfo[
1749                     afcChannelAllowance.availableAfcFrequencyInfos.size()];
1750 
1751             for (int i = 0; i < afcChannelAllowance.availableAfcFrequencyInfos.size(); ++i) {
1752                 halAfcChannelAllowance.availableAfcFrequencyInfos[i] =
1753                         frameworkToHalAvailableAfcFrequencyInfo(
1754                                 afcChannelAllowance.availableAfcFrequencyInfos.get(i));
1755             }
1756         }
1757 
1758         if (afcChannelAllowance.availableAfcChannelInfos == null) {
1759             // this should not be left uninitialized, or it may result in an exception
1760             halAfcChannelAllowance.availableAfcChannelInfos = new AvailableAfcChannelInfo[0];
1761         } else {
1762             halAfcChannelAllowance.availableAfcChannelInfos = new AvailableAfcChannelInfo[
1763                     afcChannelAllowance.availableAfcChannelInfos.size()];
1764 
1765             for (int i = 0; i < afcChannelAllowance.availableAfcChannelInfos.size(); ++i) {
1766                 halAfcChannelAllowance.availableAfcChannelInfos[i] =
1767                         frameworkToHalAvailableAfcChannelInfo(
1768                                 afcChannelAllowance.availableAfcChannelInfos.get(i));
1769             }
1770         }
1771 
1772         halAfcChannelAllowance.availabilityExpireTimeMs =
1773                 afcChannelAllowance.availabilityExpireTimeMs;
1774 
1775         return halAfcChannelAllowance;
1776     }
1777 
halToFrameworkWifiChipCapabilities( WifiChipCapabilities halCapabilities)1778     private static WifiChip.WifiChipCapabilities halToFrameworkWifiChipCapabilities(
1779             WifiChipCapabilities halCapabilities) {
1780         return new WifiChip.WifiChipCapabilities(halCapabilities.maxMloAssociationLinkCount,
1781                 halCapabilities.maxMloStrLinkCount, halCapabilities.maxConcurrentTdlsSessionCount);
1782     }
1783 
halToFrameworkRadioCombination( WifiRadioCombination halCombo)1784     private static WifiChip.WifiRadioCombination halToFrameworkRadioCombination(
1785             WifiRadioCombination halCombo) {
1786         List<WifiChip.WifiRadioConfiguration> frameworkConfigs = new ArrayList<>();
1787         for (WifiRadioConfiguration config : halCombo.radioConfigurations) {
1788             frameworkConfigs.add(halToFrameworkRadioConfiguration(config));
1789         }
1790         return new WifiChip.WifiRadioCombination(frameworkConfigs);
1791     }
1792 
halToFrameworkRadioConfiguration( WifiRadioConfiguration halConfig)1793     private static WifiChip.WifiRadioConfiguration halToFrameworkRadioConfiguration(
1794             WifiRadioConfiguration halConfig) {
1795         return new WifiChip.WifiRadioConfiguration(halToFrameworkWifiBand(halConfig.bandInfo),
1796                 halToFrameworkAntennaMode(halConfig.antennaMode));
1797     }
1798 
checkIfaceAndLogFailure(String methodStr)1799     private boolean checkIfaceAndLogFailure(String methodStr) {
1800         if (mWifiChip == null) {
1801             Log.e(TAG, "Unable to call " + methodStr + " because iface is null.");
1802             return false;
1803         }
1804         return true;
1805     }
1806 
handleRemoteException(RemoteException e, String methodStr)1807     private void handleRemoteException(RemoteException e, String methodStr) {
1808         mWifiChip = null;
1809         Log.e(TAG, methodStr + " failed with remote exception: " + e);
1810     }
1811 
handleServiceSpecificException(ServiceSpecificException e, String methodStr)1812     private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) {
1813         Log.e(TAG, methodStr + " failed with service-specific exception: " + e);
1814     }
1815 
handleIllegalArgumentException(IllegalArgumentException e, String methodStr)1816     private void handleIllegalArgumentException(IllegalArgumentException e, String methodStr) {
1817         Log.e(TAG, methodStr + " failed with illegal argument exception: " + e);
1818     }
1819 
1820     /**
1821      * See comments for {@link IWifiChip#setMloMode(int)}.
1822      */
1823     @Override
setMloMode(@ifiManager.MloMode int mode)1824     public @WifiStatusCode int setMloMode(@WifiManager.MloMode int mode) {
1825         final String methodStr = "setMloMode";
1826         @WifiStatusCode int errorCode = WifiStatusCode.ERROR_UNKNOWN;
1827         synchronized (mLock) {
1828             try {
1829                 if (checkIfaceAndLogFailure(methodStr)) {
1830                     mWifiChip.setMloMode(frameworkToAidlMloMode(mode));
1831                     errorCode = WifiStatusCode.SUCCESS;
1832                 }
1833             } catch (RemoteException e) {
1834                 handleRemoteException(e, methodStr);
1835             } catch (ServiceSpecificException e) {
1836                 handleServiceSpecificException(e, methodStr);
1837                 errorCode = e.errorCode;
1838             } catch (IllegalArgumentException e) {
1839                 handleIllegalArgumentException(e, methodStr);
1840                 errorCode = WifiStatusCode.ERROR_INVALID_ARGS;
1841             }
1842             return errorCode;
1843         }
1844     }
1845 
1846     /**
1847      * See comments for {@link IWifiChip#setAfcChannelAllowance(WifiChip.AfcChannelAllowance)}
1848      */
1849     @Override
setAfcChannelAllowance(WifiChip.AfcChannelAllowance afcChannelAllowance)1850     public boolean setAfcChannelAllowance(WifiChip.AfcChannelAllowance afcChannelAllowance) {
1851         final String methodStr = "setAfcChannelAllowance";
1852 
1853         try {
1854             AfcChannelAllowance halAfcChannelAllowance =
1855                     frameworkToHalAfcChannelAllowance(afcChannelAllowance);
1856             mWifiChip.setAfcChannelAllowance(halAfcChannelAllowance);
1857             return true;
1858         } catch (RemoteException e) {
1859             handleRemoteException(e, methodStr);
1860         } catch (ServiceSpecificException e) {
1861             handleServiceSpecificException(e, methodStr);
1862         }
1863         return false;
1864     }
1865 
frameworkToAidlMloMode( @ifiManager.MloMode int mode)1866     private @android.hardware.wifi.IWifiChip.ChipMloMode int frameworkToAidlMloMode(
1867             @WifiManager.MloMode int mode) {
1868         switch(mode) {
1869             case WifiManager.MLO_MODE_DEFAULT:
1870                 return android.hardware.wifi.IWifiChip.ChipMloMode.DEFAULT;
1871             case WifiManager.MLO_MODE_LOW_LATENCY:
1872                 return android.hardware.wifi.IWifiChip.ChipMloMode.LOW_LATENCY;
1873             case WifiManager.MLO_MODE_HIGH_THROUGHPUT:
1874                 return android.hardware.wifi.IWifiChip.ChipMloMode.HIGH_THROUGHPUT;
1875             case WifiManager.MLO_MODE_LOW_POWER:
1876                 return android.hardware.wifi.IWifiChip.ChipMloMode.LOW_POWER;
1877             default:
1878                 throw new IllegalArgumentException("frameworkToAidlMloMode: Invalid mode: " + mode);
1879         }
1880     }
1881 }
1882