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 #include "wifi.h"
18
19 #include <android-base/logging.h>
20
21 #include "aidl_return_util.h"
22 #include "aidl_sync_util.h"
23 #include "wifi_status_util.h"
24
25 namespace {
26 // Starting Chip ID, will be assigned to primary chip
27 static constexpr int32_t kPrimaryChipId = 0;
28 } // namespace
29
30 namespace aidl {
31 namespace android {
32 namespace hardware {
33 namespace wifi {
34 using aidl_return_util::validateAndCall;
35 using aidl_return_util::validateAndCallWithLock;
36 using aidl_sync_util::acquireGlobalLock;
37
Wifi(const std::shared_ptr<::android::wifi_system::InterfaceTool> iface_tool,const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,const std::shared_ptr<mode_controller::WifiModeController> mode_controller,const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)38 Wifi::Wifi(const std::shared_ptr<::android::wifi_system::InterfaceTool> iface_tool,
39 const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
40 const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
41 const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
42 : iface_tool_(iface_tool),
43 legacy_hal_factory_(legacy_hal_factory),
44 mode_controller_(mode_controller),
45 feature_flags_(feature_flags),
46 run_state_(RunState::STOPPED) {}
47
isValid()48 bool Wifi::isValid() {
49 // This object is always valid.
50 return true;
51 }
52
registerEventCallback(const std::shared_ptr<IWifiEventCallback> & in_callback)53 ndk::ScopedAStatus Wifi::registerEventCallback(
54 const std::shared_ptr<IWifiEventCallback>& in_callback) {
55 return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
56 &Wifi::registerEventCallbackInternal, in_callback);
57 }
58
isStarted(bool * _aidl_return)59 ndk::ScopedAStatus Wifi::isStarted(bool* _aidl_return) {
60 *_aidl_return = (run_state_ != RunState::STOPPED);
61 return ndk::ScopedAStatus::ok();
62 }
63
start()64 ndk::ScopedAStatus Wifi::start() {
65 return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal);
66 }
67
stop()68 ndk::ScopedAStatus Wifi::stop() {
69 return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal);
70 }
71
getChipIds(std::vector<int32_t> * _aidl_return)72 ndk::ScopedAStatus Wifi::getChipIds(std::vector<int32_t>* _aidl_return) {
73 return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal,
74 _aidl_return);
75 }
76
getChip(int32_t in_chipId,std::shared_ptr<IWifiChip> * _aidl_return)77 ndk::ScopedAStatus Wifi::getChip(int32_t in_chipId, std::shared_ptr<IWifiChip>* _aidl_return) {
78 return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal,
79 _aidl_return, in_chipId);
80 }
81
dump(int fd,const char ** args,uint32_t numArgs)82 binder_status_t Wifi::dump(int fd, const char** args, uint32_t numArgs) {
83 const auto lock = acquireGlobalLock();
84 LOG(INFO) << "-----------Debug was called----------------";
85 if (chips_.size() == 0) {
86 LOG(INFO) << "No chips to display.";
87 return STATUS_OK;
88 }
89
90 for (std::shared_ptr<WifiChip> chip : chips_) {
91 if (!chip.get()) continue;
92 chip->dump(fd, args, numArgs);
93 }
94 return STATUS_OK;
95 }
96
registerEventCallbackInternal(const std::shared_ptr<IWifiEventCallback> & event_callback)97 ndk::ScopedAStatus Wifi::registerEventCallbackInternal(
98 const std::shared_ptr<IWifiEventCallback>& event_callback) {
99 if (!event_cb_handler_.addCallback(event_callback)) {
100 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
101 }
102 return ndk::ScopedAStatus::ok();
103 }
104
startInternal()105 ndk::ScopedAStatus Wifi::startInternal() {
106 if (run_state_ == RunState::STARTED) {
107 return ndk::ScopedAStatus::ok();
108 } else if (run_state_ == RunState::STOPPING) {
109 return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
110 }
111 ndk::ScopedAStatus wifi_status = initializeModeControllerAndLegacyHal();
112 if (wifi_status.isOk()) {
113 // Register the callback for subsystem restart
114 const auto& on_subsystem_restart_callback = [this](const std::string& error) {
115 ndk::ScopedAStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
116 for (const auto& callback : event_cb_handler_.getCallbacks()) {
117 LOG(INFO) << "Attempting to invoke onSubsystemRestart "
118 "callback";
119 WifiStatusCode errorCode =
120 static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
121 if (!callback->onSubsystemRestart(errorCode).isOk()) {
122 LOG(ERROR) << "Failed to invoke onSubsystemRestart callback";
123 } else {
124 LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
125 "callback";
126 }
127 }
128 };
129
130 // Create the chip instance once the HAL is started.
131 int32_t chipId = kPrimaryChipId;
132 for (auto& hal : legacy_hals_) {
133 chips_.push_back(
134 WifiChip::create(chipId, chipId == kPrimaryChipId, hal, mode_controller_,
135 std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
136 feature_flags_, on_subsystem_restart_callback, false));
137 chipId++;
138 }
139 run_state_ = RunState::STARTED;
140 for (const auto& callback : event_cb_handler_.getCallbacks()) {
141 if (!callback->onStart().isOk()) {
142 LOG(ERROR) << "Failed to invoke onStart callback";
143 };
144 }
145 LOG(INFO) << "Wifi HAL started";
146 } else {
147 for (const auto& callback : event_cb_handler_.getCallbacks()) {
148 WifiStatusCode errorCode =
149 static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
150 if (!callback->onFailure(errorCode).isOk()) {
151 LOG(ERROR) << "Failed to invoke onFailure callback";
152 }
153 }
154 LOG(ERROR) << "Wifi HAL start failed";
155 // Clear the event callback objects since the HAL start failed.
156 event_cb_handler_.invalidate();
157 }
158 return wifi_status;
159 }
160
stopInternal(std::unique_lock<std::recursive_mutex> * lock)161 ndk::ScopedAStatus Wifi::stopInternal(
162 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
163 if (run_state_ == RunState::STOPPED) {
164 return ndk::ScopedAStatus::ok();
165 } else if (run_state_ == RunState::STOPPING) {
166 return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
167 }
168 // Clear the chip object and its child objects since the HAL is now
169 // stopped.
170 for (auto& chip : chips_) {
171 if (chip.get()) {
172 chip->invalidate();
173 chip.reset();
174 }
175 }
176 chips_.clear();
177 ndk::ScopedAStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
178 if (wifi_status.isOk()) {
179 for (const auto& callback : event_cb_handler_.getCallbacks()) {
180 if (!callback->onStop().isOk()) {
181 LOG(ERROR) << "Failed to invoke onStop callback";
182 };
183 }
184 LOG(INFO) << "Wifi HAL stopped";
185 } else {
186 for (const auto& callback : event_cb_handler_.getCallbacks()) {
187 WifiStatusCode errorCode =
188 static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
189 if (!callback->onFailure(errorCode).isOk()) {
190 LOG(ERROR) << "Failed to invoke onFailure callback";
191 }
192 }
193 LOG(ERROR) << "Wifi HAL stop failed";
194 }
195 // Clear the event callback objects since the HAL is now stopped.
196 event_cb_handler_.invalidate();
197 return wifi_status;
198 }
199
getChipIdsInternal()200 std::pair<std::vector<int32_t>, ndk::ScopedAStatus> Wifi::getChipIdsInternal() {
201 std::vector<int32_t> chip_ids;
202
203 for (auto& chip : chips_) {
204 int32_t chip_id = getChipIdFromWifiChip(chip);
205 if (chip_id != INT32_MAX) chip_ids.emplace_back(chip_id);
206 }
207 return {std::move(chip_ids), ndk::ScopedAStatus::ok()};
208 }
209
getChipInternal(int32_t chip_id)210 std::pair<std::shared_ptr<IWifiChip>, ndk::ScopedAStatus> Wifi::getChipInternal(int32_t chip_id) {
211 for (auto& chip : chips_) {
212 int32_t cand_id = getChipIdFromWifiChip(chip);
213 if ((cand_id != INT32_MAX) && (cand_id == chip_id)) return {chip, ndk::ScopedAStatus::ok()};
214 }
215
216 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
217 }
218
initializeModeControllerAndLegacyHal()219 ndk::ScopedAStatus Wifi::initializeModeControllerAndLegacyHal() {
220 if (!mode_controller_->initialize()) {
221 LOG(ERROR) << "Failed to initialize firmware mode controller";
222 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
223 }
224
225 legacy_hals_ = legacy_hal_factory_->getHals();
226 if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
227 int index = 0; // for failure log
228 for (auto& hal : legacy_hals_) {
229 legacy_hal::wifi_error legacy_status = hal->initialize();
230 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
231 // Currently WifiLegacyHal::initialize does not allocate extra mem,
232 // only initializes the function table. If this changes, need to
233 // implement WifiLegacyHal::deinitialize and deinitalize the
234 // HALs already initialized
235 LOG(ERROR) << "Failed to initialize legacy HAL index: " << index
236 << " error: " << legacyErrorToString(legacy_status);
237 return createWifiStatusFromLegacyError(legacy_status);
238 }
239 index++;
240 }
241 return ndk::ScopedAStatus::ok();
242 }
243
stopLegacyHalAndDeinitializeModeController(std::unique_lock<std::recursive_mutex> * lock)244 ndk::ScopedAStatus Wifi::stopLegacyHalAndDeinitializeModeController(
245 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
246 legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS;
247 int index = 0;
248
249 run_state_ = RunState::STOPPING;
250 for (auto& hal : legacy_hals_) {
251 legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {});
252 if (tmp != legacy_hal::WIFI_SUCCESS) {
253 LOG(ERROR) << "Failed to stop legacy HAL index: " << index
254 << " error: " << legacyErrorToString(legacy_status);
255 legacy_status = tmp;
256 }
257 index++;
258 }
259 run_state_ = RunState::STOPPED;
260
261 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
262 LOG(ERROR) << "One or more legacy HALs failed to stop";
263 return createWifiStatusFromLegacyError(legacy_status);
264 }
265 if (!mode_controller_->deinitialize()) {
266 LOG(ERROR) << "Failed to deinitialize firmware mode controller";
267 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
268 }
269 return ndk::ScopedAStatus::ok();
270 }
271
getChipIdFromWifiChip(std::shared_ptr<WifiChip> & chip)272 int32_t Wifi::getChipIdFromWifiChip(std::shared_ptr<WifiChip>& chip) {
273 int32_t chip_id = INT32_MAX;
274 if (chip.get()) {
275 ndk::ScopedAStatus status = chip->getId(&chip_id);
276 if (!status.isOk()) {
277 // Reset value if operation failed.
278 chip_id = INT32_MAX;
279 }
280 }
281 return chip_id;
282 }
283
284 } // namespace wifi
285 } // namespace hardware
286 } // namespace android
287 } // namespace aidl
288