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