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