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 35 Wifi::Wifi() 36 : legacy_hal_(new legacy_hal::WifiLegacyHal()), 37 mode_controller_(new mode_controller::WifiModeController()), 38 run_state_(RunState::STOPPED) {} 39 40 bool Wifi::isValid() { 41 // This object is always valid. 42 return true; 43 } 44 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 55 Return<bool> Wifi::isStarted() { 56 return run_state_ != RunState::STOPPED; 57 } 58 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 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 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 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 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 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 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 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 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 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 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