1 /*
2 * Copyright (C) 2016 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 <android-base/logging.h>
18
19 #include "hidl_return_util.h"
20 #include "wifi.h"
21 #include "wifi_status_util.h"
22
23 namespace {
24 // Chip ID to use for the only supported chip.
25 static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0;
26 } // namespace
27
28 namespace android {
29 namespace hardware {
30 namespace wifi {
31 namespace V1_0 {
32 namespace implementation {
33 using hidl_return_util::validateAndCall;
34
Wifi()35 Wifi::Wifi()
36 : legacy_hal_(new legacy_hal::WifiLegacyHal()),
37 mode_controller_(new mode_controller::WifiModeController()),
38 run_state_(RunState::STOPPED) {}
39
isValid()40 bool Wifi::isValid() {
41 // This object is always valid.
42 return true;
43 }
44
registerEventCallback(const sp<IWifiEventCallback> & event_callback,registerEventCallback_cb hidl_status_cb)45 Return<void> Wifi::registerEventCallback(
46 const sp<IWifiEventCallback>& event_callback,
47 registerEventCallback_cb hidl_status_cb) {
48 return validateAndCall(this,
49 WifiStatusCode::ERROR_UNKNOWN,
50 &Wifi::registerEventCallbackInternal,
51 hidl_status_cb,
52 event_callback);
53 }
54
isStarted()55 Return<bool> Wifi::isStarted() {
56 return run_state_ != RunState::STOPPED;
57 }
58
start(start_cb hidl_status_cb)59 Return<void> Wifi::start(start_cb hidl_status_cb) {
60 return validateAndCall(this,
61 WifiStatusCode::ERROR_UNKNOWN,
62 &Wifi::startInternal,
63 hidl_status_cb);
64 }
65
stop(stop_cb hidl_status_cb)66 Return<void> Wifi::stop(stop_cb hidl_status_cb) {
67 return validateAndCall(
68 this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb);
69 }
70
getChipIds(getChipIds_cb hidl_status_cb)71 Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
72 return validateAndCall(this,
73 WifiStatusCode::ERROR_UNKNOWN,
74 &Wifi::getChipIdsInternal,
75 hidl_status_cb);
76 }
77
getChip(ChipId chip_id,getChip_cb hidl_status_cb)78 Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
79 return validateAndCall(this,
80 WifiStatusCode::ERROR_UNKNOWN,
81 &Wifi::getChipInternal,
82 hidl_status_cb,
83 chip_id);
84 }
85
registerEventCallbackInternal(const sp<IWifiEventCallback> & event_callback)86 WifiStatus Wifi::registerEventCallbackInternal(
87 const sp<IWifiEventCallback>& event_callback) {
88 if (!event_cb_handler_.addCallback(event_callback)) {
89 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
90 }
91 return createWifiStatus(WifiStatusCode::SUCCESS);
92 }
93
startInternal()94 WifiStatus Wifi::startInternal() {
95 if (run_state_ == RunState::STARTED) {
96 return createWifiStatus(WifiStatusCode::SUCCESS);
97 } else if (run_state_ == RunState::STOPPING) {
98 return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
99 "HAL is stopping");
100 }
101 WifiStatus wifi_status = initializeLegacyHal();
102 if (wifi_status.code == WifiStatusCode::SUCCESS) {
103 // Create the chip instance once the HAL is started.
104 chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
105 run_state_ = RunState::STARTED;
106 for (const auto& callback : event_cb_handler_.getCallbacks()) {
107 if (!callback->onStart().isOk()) {
108 LOG(ERROR) << "Failed to invoke onStart callback";
109 };
110 }
111 } else {
112 for (const auto& callback : event_cb_handler_.getCallbacks()) {
113 if (!callback->onFailure(wifi_status).isOk()) {
114 LOG(ERROR) << "Failed to invoke onFailure callback";
115 }
116 }
117 }
118 LOG(INFO) << "Wifi HAL started";
119 return wifi_status;
120 }
121
stopInternal()122 WifiStatus Wifi::stopInternal() {
123 if (run_state_ == RunState::STOPPED) {
124 return createWifiStatus(WifiStatusCode::SUCCESS);
125 } else if (run_state_ == RunState::STOPPING) {
126 return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
127 "HAL is stopping");
128 }
129 WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
130 if (wifi_status.code == WifiStatusCode::SUCCESS) {
131 for (const auto& callback : event_cb_handler_.getCallbacks()) {
132 if (!callback->onStop().isOk()) {
133 LOG(ERROR) << "Failed to invoke onStop callback";
134 };
135 }
136 } else {
137 for (const auto& callback : event_cb_handler_.getCallbacks()) {
138 if (!callback->onFailure(wifi_status).isOk()) {
139 LOG(ERROR) << "Failed to invoke onFailure callback";
140 }
141 }
142 }
143 // Clear the chip object and its child objects since the HAL is now
144 // stopped.
145 if (chip_.get()) {
146 chip_->invalidate();
147 chip_.clear();
148 }
149 LOG(INFO) << "Wifi HAL stopped";
150 return wifi_status;
151 }
152
getChipIdsInternal()153 std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
154 std::vector<ChipId> chip_ids;
155 if (chip_.get()) {
156 chip_ids.emplace_back(kChipId);
157 }
158 return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
159 }
160
getChipInternal(ChipId chip_id)161 std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
162 if (!chip_.get()) {
163 return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
164 }
165 if (chip_id != kChipId) {
166 return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
167 }
168 return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
169 }
170
initializeLegacyHal()171 WifiStatus Wifi::initializeLegacyHal() {
172 legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
173 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
174 LOG(ERROR) << "Failed to initialize legacy HAL: "
175 << legacyErrorToString(legacy_status);
176 return createWifiStatusFromLegacyError(legacy_status);
177 }
178 return createWifiStatus(WifiStatusCode::SUCCESS);
179 }
180
stopLegacyHalAndDeinitializeModeController()181 WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
182 run_state_ = RunState::STOPPING;
183 const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; };
184 legacy_hal::wifi_error legacy_status =
185 legacy_hal_->stop(on_complete_callback_);
186 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
187 LOG(ERROR) << "Failed to stop legacy HAL: "
188 << legacyErrorToString(legacy_status);
189 return createWifiStatusFromLegacyError(legacy_status);
190 }
191 if (!mode_controller_->deinitialize()) {
192 LOG(ERROR) << "Failed to deinitialize firmware mode controller";
193 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
194 }
195 return createWifiStatus(WifiStatusCode::SUCCESS);
196 }
197 } // namespace implementation
198 } // namespace V1_0
199 } // namespace wifi
200 } // namespace hardware
201 } // namespace android
202