• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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