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 android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.Context;
23 import android.util.Log;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.server.wifi.SsidTranslator;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.List;
31 import java.util.function.Supplier;
32 
33 /**
34  * Wrapper around the root Wifi HAL.
35  * Depending on the service available, may initialize using HIDL or AIDL.
36  */
37 public class WifiHal {
38     private static final String TAG = "WifiHal";
39     private IWifiHal mWifiHal;
40 
41     /**
42      * Wifi operation status codes.
43      */
44     public static final int WIFI_STATUS_SUCCESS = 0;
45     public static final int WIFI_STATUS_ERROR_WIFI_CHIP_INVALID = 1;
46     public static final int WIFI_STATUS_ERROR_WIFI_IFACE_INVALID = 2;
47     public static final int WIFI_STATUS_ERROR_WIFI_RTT_CONTROLLER_INVALID = 3;
48     public static final int WIFI_STATUS_ERROR_NOT_SUPPORTED = 4;
49     public static final int WIFI_STATUS_ERROR_NOT_AVAILABLE = 5;
50     public static final int WIFI_STATUS_ERROR_NOT_STARTED = 6;
51     public static final int WIFI_STATUS_ERROR_INVALID_ARGS = 7;
52     public static final int WIFI_STATUS_ERROR_BUSY = 8;
53     public static final int WIFI_STATUS_ERROR_UNKNOWN = 9;
54     public static final int WIFI_STATUS_ERROR_REMOTE_EXCEPTION = 10;
55 
56     @IntDef(prefix = { "WIFI_STATUS_" }, value = {
57             WIFI_STATUS_SUCCESS,
58             WIFI_STATUS_ERROR_WIFI_CHIP_INVALID,
59             WIFI_STATUS_ERROR_WIFI_IFACE_INVALID,
60             WIFI_STATUS_ERROR_WIFI_RTT_CONTROLLER_INVALID,
61             WIFI_STATUS_ERROR_NOT_SUPPORTED,
62             WIFI_STATUS_ERROR_NOT_AVAILABLE,
63             WIFI_STATUS_ERROR_NOT_STARTED,
64             WIFI_STATUS_ERROR_INVALID_ARGS,
65             WIFI_STATUS_ERROR_BUSY,
66             WIFI_STATUS_ERROR_UNKNOWN,
67             WIFI_STATUS_ERROR_REMOTE_EXCEPTION,
68     })
69     @Retention(RetentionPolicy.SOURCE)
70     public @interface WifiStatusCode {}
71 
72     /**
73      * Interface that can be created by the Wi-Fi HAL.
74      */
75     public interface WifiInterface {
76         /**
77          * Get the name of this interface.
78          */
getName()79         String getName();
80     }
81 
82     /**
83      * Framework callback object. Will get called when the equivalent events are received
84      * from the HAL.
85      */
86     public interface Callback {
87         /**
88          * Called when the Wi-Fi system failed in a way that caused it be disabled.
89          * Calling start again must restart Wi-Fi as if stop then start was called
90          * (full state reset). When this event is received, all WifiChip & WifiIface
91          * objects retrieved after the last call to start will be considered invalid.
92          *
93          * @param status Failure reason code.
94          */
onFailure(@ifiStatusCode int status)95         void onFailure(@WifiStatusCode int status);
96 
97         /**
98          * Called in response to a call to start, indicating that the operation
99          * completed. After this callback the HAL must be fully operational.
100          */
onStart()101         void onStart();
102 
103         /**
104          * Called in response to a call to stop, indicating that the operation
105          * completed. When this event is received, all WifiChip objects retrieved
106          * after the last call to start will be considered invalid.
107          */
onStop()108         void onStop();
109 
110         /**
111          * Must be called when the Wi-Fi subsystem restart completes.
112          * Once this event is received, the framework must fully reset the Wi-Fi stack state.
113          *
114          * @param status Status code.
115          */
onSubsystemRestart(@ifiStatusCode int status)116         void onSubsystemRestart(@WifiStatusCode int status);
117     }
118 
119     /**
120      * Framework death recipient object. Called if the death recipient registered with the HAL
121      * indicates that the service died.
122      */
123     public interface DeathRecipient {
124         /**
125          * Called on service death.
126          */
onDeath()127         void onDeath();
128     }
129 
WifiHal(@onNull Context context, @NonNull SsidTranslator ssidTranslator)130     public WifiHal(@NonNull Context context, @NonNull SsidTranslator ssidTranslator) {
131         mWifiHal = createWifiHalMockable(context, ssidTranslator);
132     }
133 
134     @VisibleForTesting
createWifiHalMockable(@onNull Context context, @NonNull SsidTranslator ssidTranslator)135     protected IWifiHal createWifiHalMockable(@NonNull Context context,
136             @NonNull SsidTranslator ssidTranslator) {
137         if (WifiHalHidlImpl.serviceDeclared()) {
138             return new WifiHalHidlImpl(context, ssidTranslator);
139         } else if (WifiHalAidlImpl.serviceDeclared()) {
140             return new WifiHalAidlImpl(context, ssidTranslator);
141         } else {
142             Log.e(TAG, "No HIDL or AIDL service available for the Wifi Vendor HAL.");
143             return null;
144         }
145     }
146 
validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier)147     private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) {
148         if (mWifiHal == null) {
149             Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiHal is null");
150             return defaultVal;
151         }
152         return supplier.get();
153     }
154 
155     /**
156      * See comments for {@link IWifiHal#getChip(int)}
157      */
158     @Nullable
getChip(int chipId)159     public WifiChip getChip(int chipId) {
160         return validateAndCall("getChip", null,
161                 () -> mWifiHal.getChip(chipId));
162     }
163 
164     /**
165      * See comments for {@link IWifiHal#getChipIds()}
166      */
167     @Nullable
getChipIds()168     public List<Integer> getChipIds() {
169         return validateAndCall("getChipIds", null,
170                 () -> mWifiHal.getChipIds());
171     }
172 
173     /**
174      * See comments for {@link IWifiHal#registerEventCallback(Callback)}
175      */
registerEventCallback(Callback callback)176     public boolean registerEventCallback(Callback callback) {
177         return validateAndCall("registerEventCallback", false,
178                 () -> mWifiHal.registerEventCallback(callback));
179     }
180 
181     /**
182      * See comments for {@link IWifiHal#initialize(DeathRecipient)}
183      */
initialize(WifiHal.DeathRecipient deathRecipient)184     public void initialize(WifiHal.DeathRecipient deathRecipient) {
185         if (mWifiHal != null) {
186             mWifiHal.initialize(deathRecipient);
187         }
188     }
189 
190     /**
191      * See comments for {@link IWifiHal#isInitializationComplete()}
192      */
isInitializationComplete()193     public boolean isInitializationComplete() {
194         return validateAndCall("isInitializationComplete", false,
195                 () -> mWifiHal.isInitializationComplete());
196     }
197 
198     /**
199      * See comments for {@link IWifiHal#isSupported()}
200      */
isSupported()201     public boolean isSupported() {
202         return validateAndCall("isSupported", false,
203                 () -> mWifiHal.isSupported());
204     }
205 
206     /**
207      * See comments for {@link IWifiHal#start()}
208      */
start()209     public @WifiStatusCode int start() {
210         return validateAndCall("start", WIFI_STATUS_ERROR_UNKNOWN,
211                 () -> mWifiHal.start());
212     }
213 
214     /**
215      * See comments for {@link IWifiHal#isStarted()}
216      */
isStarted()217     public boolean isStarted() {
218         return validateAndCall("isStarted", false,
219                 () -> mWifiHal.isStarted());
220     }
221 
222     /**
223      * See comments for {@link IWifiHal#stop()}
224      */
stop()225     public boolean stop() {
226         return validateAndCall("stop", false,
227                 () -> mWifiHal.stop());
228     }
229 
230     /**
231      * See comments for {@link IWifiHal#invalidate()}
232      */
invalidate()233     public void invalidate() {
234         if (mWifiHal != null) {
235             mWifiHal.invalidate();
236         }
237     }
238 }
239