blob: d6a85da198cada7716dac56d2702d3acdf4ab07e [file] [log] [blame]
Gabriel Birenf3262f92022-07-15 23:25:39 +00001/*
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"
Gabriel Biren57896d22023-04-10 23:47:45 +000022#include "aidl_sync_util.h"
Gabriel Birenf3262f92022-07-15 23:25:39 +000023#include "wifi_status_util.h"
24
25namespace {
26// Starting Chip ID, will be assigned to primary chip
27static constexpr int32_t kPrimaryChipId = 0;
28} // namespace
29
30namespace aidl {
31namespace android {
32namespace hardware {
33namespace wifi {
34using aidl_return_util::validateAndCall;
35using aidl_return_util::validateAndCallWithLock;
Gabriel Biren57896d22023-04-10 23:47:45 +000036using aidl_sync_util::acquireGlobalLock;
Gabriel Birenf3262f92022-07-15 23:25:39 +000037
38Wifi::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
48bool Wifi::isValid() {
49 // This object is always valid.
50 return true;
51}
52
53ndk::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
59ndk::ScopedAStatus Wifi::isStarted(bool* _aidl_return) {
60 *_aidl_return = (run_state_ != RunState::STOPPED);
61 return ndk::ScopedAStatus::ok();
62}
63
64ndk::ScopedAStatus Wifi::start() {
65 return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal);
66}
67
68ndk::ScopedAStatus Wifi::stop() {
69 return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal);
70}
71
72ndk::ScopedAStatus Wifi::getChipIds(std::vector<int32_t>* _aidl_return) {
73 return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal,
74 _aidl_return);
75}
76
77ndk::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
82binder_status_t Wifi::dump(int fd, const char** args, uint32_t numArgs) {
Gabriel Biren57896d22023-04-10 23:47:45 +000083 const auto lock = acquireGlobalLock();
Gabriel Birenf3262f92022-07-15 23:25:39 +000084 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
97ndk::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
105ndk::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));
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
161ndk::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
200std::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
210std::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
219ndk::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
244ndk::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
272int32_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