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