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