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