1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include "wifi.h"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include <android-base/file.h>
20*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <cutils/properties.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <sys/stat.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
24*4d7e907cSAndroid Build Coastguard Worker
25*4d7e907cSAndroid Build Coastguard Worker #include "aidl_return_util.h"
26*4d7e907cSAndroid Build Coastguard Worker #include "aidl_sync_util.h"
27*4d7e907cSAndroid Build Coastguard Worker #include "wifi_status_util.h"
28*4d7e907cSAndroid Build Coastguard Worker
29*4d7e907cSAndroid Build Coastguard Worker namespace {
30*4d7e907cSAndroid Build Coastguard Worker using android::base::unique_fd;
31*4d7e907cSAndroid Build Coastguard Worker
32*4d7e907cSAndroid Build Coastguard Worker // Starting Chip ID, will be assigned to primary chip
33*4d7e907cSAndroid Build Coastguard Worker static constexpr int32_t kPrimaryChipId = 0;
34*4d7e907cSAndroid Build Coastguard Worker constexpr char kCpioMagic[] = "070701";
35*4d7e907cSAndroid Build Coastguard Worker constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
36*4d7e907cSAndroid Build Coastguard Worker
37*4d7e907cSAndroid Build Coastguard Worker // Helper function for |cpioArchiveFilesInDir|
cpioWriteHeader(int out_fd,struct stat & st,const char * file_name,size_t file_name_len)38*4d7e907cSAndroid Build Coastguard Worker bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
39*4d7e907cSAndroid Build Coastguard Worker const int buf_size = 32 * 1024;
40*4d7e907cSAndroid Build Coastguard Worker std::array<char, buf_size> read_buf;
41*4d7e907cSAndroid Build Coastguard Worker ssize_t llen = snprintf(
42*4d7e907cSAndroid Build Coastguard Worker read_buf.data(), buf_size, "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
43*4d7e907cSAndroid Build Coastguard Worker kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, st.st_gid,
44*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(st.st_nlink), static_cast<int>(st.st_mtime),
45*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(st.st_size), major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
46*4d7e907cSAndroid Build Coastguard Worker minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
47*4d7e907cSAndroid Build Coastguard Worker if (write(out_fd, read_buf.data(), llen < buf_size ? llen : buf_size - 1) == -1) {
48*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error writing cpio header to file " << file_name;
49*4d7e907cSAndroid Build Coastguard Worker return false;
50*4d7e907cSAndroid Build Coastguard Worker }
51*4d7e907cSAndroid Build Coastguard Worker if (write(out_fd, file_name, file_name_len) == -1) {
52*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error writing filename to file " << file_name;
53*4d7e907cSAndroid Build Coastguard Worker return false;
54*4d7e907cSAndroid Build Coastguard Worker }
55*4d7e907cSAndroid Build Coastguard Worker
56*4d7e907cSAndroid Build Coastguard Worker // NUL Pad header up to 4 multiple bytes.
57*4d7e907cSAndroid Build Coastguard Worker llen = (llen + file_name_len) % 4;
58*4d7e907cSAndroid Build Coastguard Worker if (llen != 0) {
59*4d7e907cSAndroid Build Coastguard Worker const uint32_t zero = 0;
60*4d7e907cSAndroid Build Coastguard Worker if (write(out_fd, &zero, 4 - llen) == -1) {
61*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error padding 0s to file " << file_name;
62*4d7e907cSAndroid Build Coastguard Worker return false;
63*4d7e907cSAndroid Build Coastguard Worker }
64*4d7e907cSAndroid Build Coastguard Worker }
65*4d7e907cSAndroid Build Coastguard Worker return true;
66*4d7e907cSAndroid Build Coastguard Worker }
67*4d7e907cSAndroid Build Coastguard Worker
68*4d7e907cSAndroid Build Coastguard Worker // Helper function for |cpioArchiveFilesInDir|
cpioWriteFileContent(int fd_read,int out_fd,struct stat & st)69*4d7e907cSAndroid Build Coastguard Worker size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
70*4d7e907cSAndroid Build Coastguard Worker // writing content of file
71*4d7e907cSAndroid Build Coastguard Worker std::array<char, 32 * 1024> read_buf;
72*4d7e907cSAndroid Build Coastguard Worker ssize_t llen = st.st_size;
73*4d7e907cSAndroid Build Coastguard Worker size_t n_error = 0;
74*4d7e907cSAndroid Build Coastguard Worker while (llen > 0) {
75*4d7e907cSAndroid Build Coastguard Worker ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
76*4d7e907cSAndroid Build Coastguard Worker if (bytes_read == -1) {
77*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error reading file";
78*4d7e907cSAndroid Build Coastguard Worker return ++n_error;
79*4d7e907cSAndroid Build Coastguard Worker }
80*4d7e907cSAndroid Build Coastguard Worker llen -= bytes_read;
81*4d7e907cSAndroid Build Coastguard Worker if (write(out_fd, read_buf.data(), bytes_read) == -1) {
82*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error writing data to file";
83*4d7e907cSAndroid Build Coastguard Worker return ++n_error;
84*4d7e907cSAndroid Build Coastguard Worker }
85*4d7e907cSAndroid Build Coastguard Worker if (bytes_read == 0) { // this should never happen, but just in case
86*4d7e907cSAndroid Build Coastguard Worker // to unstuck from while loop
87*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Unexpected read result";
88*4d7e907cSAndroid Build Coastguard Worker n_error++;
89*4d7e907cSAndroid Build Coastguard Worker break;
90*4d7e907cSAndroid Build Coastguard Worker }
91*4d7e907cSAndroid Build Coastguard Worker }
92*4d7e907cSAndroid Build Coastguard Worker llen = st.st_size % 4;
93*4d7e907cSAndroid Build Coastguard Worker if (llen != 0) {
94*4d7e907cSAndroid Build Coastguard Worker const uint32_t zero = 0;
95*4d7e907cSAndroid Build Coastguard Worker if (write(out_fd, &zero, 4 - llen) == -1) {
96*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error padding 0s to file";
97*4d7e907cSAndroid Build Coastguard Worker return ++n_error;
98*4d7e907cSAndroid Build Coastguard Worker }
99*4d7e907cSAndroid Build Coastguard Worker }
100*4d7e907cSAndroid Build Coastguard Worker return n_error;
101*4d7e907cSAndroid Build Coastguard Worker }
102*4d7e907cSAndroid Build Coastguard Worker
103*4d7e907cSAndroid Build Coastguard Worker // Helper function for |cpioArchiveFilesInDir|
cpioWriteFileTrailer(int out_fd)104*4d7e907cSAndroid Build Coastguard Worker bool cpioWriteFileTrailer(int out_fd) {
105*4d7e907cSAndroid Build Coastguard Worker const int buf_size = 4096;
106*4d7e907cSAndroid Build Coastguard Worker std::array<char, buf_size> read_buf;
107*4d7e907cSAndroid Build Coastguard Worker read_buf.fill(0);
108*4d7e907cSAndroid Build Coastguard Worker ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0);
109*4d7e907cSAndroid Build Coastguard Worker if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) {
110*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Error writing trailing bytes";
111*4d7e907cSAndroid Build Coastguard Worker return false;
112*4d7e907cSAndroid Build Coastguard Worker }
113*4d7e907cSAndroid Build Coastguard Worker return true;
114*4d7e907cSAndroid Build Coastguard Worker }
115*4d7e907cSAndroid Build Coastguard Worker
116*4d7e907cSAndroid Build Coastguard Worker // Archives all files in |input_dir| and writes result into |out_fd|
117*4d7e907cSAndroid Build Coastguard Worker // Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
118*4d7e907cSAndroid Build Coastguard Worker // portion
cpioArchiveFilesInDir(int out_fd,const char * input_dir)119*4d7e907cSAndroid Build Coastguard Worker size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
120*4d7e907cSAndroid Build Coastguard Worker struct dirent* dp;
121*4d7e907cSAndroid Build Coastguard Worker size_t n_error = 0;
122*4d7e907cSAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
123*4d7e907cSAndroid Build Coastguard Worker if (!dir_dump) {
124*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open directory";
125*4d7e907cSAndroid Build Coastguard Worker return ++n_error;
126*4d7e907cSAndroid Build Coastguard Worker }
127*4d7e907cSAndroid Build Coastguard Worker while ((dp = readdir(dir_dump.get()))) {
128*4d7e907cSAndroid Build Coastguard Worker if (dp->d_type != DT_REG) {
129*4d7e907cSAndroid Build Coastguard Worker continue;
130*4d7e907cSAndroid Build Coastguard Worker }
131*4d7e907cSAndroid Build Coastguard Worker std::string cur_file_name(dp->d_name);
132*4d7e907cSAndroid Build Coastguard Worker struct stat st;
133*4d7e907cSAndroid Build Coastguard Worker const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
134*4d7e907cSAndroid Build Coastguard Worker if (stat(cur_file_path.c_str(), &st) == -1) {
135*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
136*4d7e907cSAndroid Build Coastguard Worker n_error++;
137*4d7e907cSAndroid Build Coastguard Worker continue;
138*4d7e907cSAndroid Build Coastguard Worker }
139*4d7e907cSAndroid Build Coastguard Worker const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
140*4d7e907cSAndroid Build Coastguard Worker if (fd_read == -1) {
141*4d7e907cSAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open file " << cur_file_path;
142*4d7e907cSAndroid Build Coastguard Worker n_error++;
143*4d7e907cSAndroid Build Coastguard Worker continue;
144*4d7e907cSAndroid Build Coastguard Worker }
145*4d7e907cSAndroid Build Coastguard Worker std::string file_name_with_last_modified_time =
146*4d7e907cSAndroid Build Coastguard Worker cur_file_name + "-" + std::to_string(st.st_mtime);
147*4d7e907cSAndroid Build Coastguard Worker // string.size() does not include the null terminator. The cpio FreeBSD
148*4d7e907cSAndroid Build Coastguard Worker // file header expects the null character to be included in the length.
149*4d7e907cSAndroid Build Coastguard Worker const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
150*4d7e907cSAndroid Build Coastguard Worker unique_fd file_auto_closer(fd_read);
151*4d7e907cSAndroid Build Coastguard Worker if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
152*4d7e907cSAndroid Build Coastguard Worker file_name_len)) {
153*4d7e907cSAndroid Build Coastguard Worker return ++n_error;
154*4d7e907cSAndroid Build Coastguard Worker }
155*4d7e907cSAndroid Build Coastguard Worker size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
156*4d7e907cSAndroid Build Coastguard Worker if (write_error) {
157*4d7e907cSAndroid Build Coastguard Worker return n_error + write_error;
158*4d7e907cSAndroid Build Coastguard Worker }
159*4d7e907cSAndroid Build Coastguard Worker }
160*4d7e907cSAndroid Build Coastguard Worker if (!cpioWriteFileTrailer(out_fd)) {
161*4d7e907cSAndroid Build Coastguard Worker return ++n_error;
162*4d7e907cSAndroid Build Coastguard Worker }
163*4d7e907cSAndroid Build Coastguard Worker return n_error;
164*4d7e907cSAndroid Build Coastguard Worker }
165*4d7e907cSAndroid Build Coastguard Worker
166*4d7e907cSAndroid Build Coastguard Worker } // namespace
167*4d7e907cSAndroid Build Coastguard Worker
168*4d7e907cSAndroid Build Coastguard Worker namespace aidl {
169*4d7e907cSAndroid Build Coastguard Worker namespace android {
170*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
171*4d7e907cSAndroid Build Coastguard Worker namespace wifi {
172*4d7e907cSAndroid Build Coastguard Worker using aidl_return_util::validateAndCall;
173*4d7e907cSAndroid Build Coastguard Worker using aidl_return_util::validateAndCallWithLock;
174*4d7e907cSAndroid Build Coastguard Worker using aidl_sync_util::acquireGlobalLock;
175*4d7e907cSAndroid Build Coastguard Worker
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)176*4d7e907cSAndroid Build Coastguard Worker Wifi::Wifi(const std::shared_ptr<::android::wifi_system::InterfaceTool> iface_tool,
177*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
178*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
179*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
180*4d7e907cSAndroid Build Coastguard Worker : iface_tool_(iface_tool),
181*4d7e907cSAndroid Build Coastguard Worker legacy_hal_factory_(legacy_hal_factory),
182*4d7e907cSAndroid Build Coastguard Worker mode_controller_(mode_controller),
183*4d7e907cSAndroid Build Coastguard Worker feature_flags_(feature_flags),
184*4d7e907cSAndroid Build Coastguard Worker run_state_(RunState::STOPPED) {}
185*4d7e907cSAndroid Build Coastguard Worker
isValid()186*4d7e907cSAndroid Build Coastguard Worker bool Wifi::isValid() {
187*4d7e907cSAndroid Build Coastguard Worker // This object is always valid.
188*4d7e907cSAndroid Build Coastguard Worker return true;
189*4d7e907cSAndroid Build Coastguard Worker }
190*4d7e907cSAndroid Build Coastguard Worker
registerEventCallback(const std::shared_ptr<IWifiEventCallback> & in_callback)191*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::registerEventCallback(
192*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<IWifiEventCallback>& in_callback) {
193*4d7e907cSAndroid Build Coastguard Worker return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
194*4d7e907cSAndroid Build Coastguard Worker &Wifi::registerEventCallbackInternal, in_callback);
195*4d7e907cSAndroid Build Coastguard Worker }
196*4d7e907cSAndroid Build Coastguard Worker
isStarted(bool * _aidl_return)197*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::isStarted(bool* _aidl_return) {
198*4d7e907cSAndroid Build Coastguard Worker *_aidl_return = (run_state_ != RunState::STOPPED);
199*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
200*4d7e907cSAndroid Build Coastguard Worker }
201*4d7e907cSAndroid Build Coastguard Worker
start()202*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::start() {
203*4d7e907cSAndroid Build Coastguard Worker return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal);
204*4d7e907cSAndroid Build Coastguard Worker }
205*4d7e907cSAndroid Build Coastguard Worker
stop()206*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::stop() {
207*4d7e907cSAndroid Build Coastguard Worker return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal);
208*4d7e907cSAndroid Build Coastguard Worker }
209*4d7e907cSAndroid Build Coastguard Worker
getChipIds(std::vector<int32_t> * _aidl_return)210*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::getChipIds(std::vector<int32_t>* _aidl_return) {
211*4d7e907cSAndroid Build Coastguard Worker return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal,
212*4d7e907cSAndroid Build Coastguard Worker _aidl_return);
213*4d7e907cSAndroid Build Coastguard Worker }
214*4d7e907cSAndroid Build Coastguard Worker
getChip(int32_t in_chipId,std::shared_ptr<IWifiChip> * _aidl_return)215*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::getChip(int32_t in_chipId, std::shared_ptr<IWifiChip>* _aidl_return) {
216*4d7e907cSAndroid Build Coastguard Worker return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal,
217*4d7e907cSAndroid Build Coastguard Worker _aidl_return, in_chipId);
218*4d7e907cSAndroid Build Coastguard Worker }
219*4d7e907cSAndroid Build Coastguard Worker
dump(int fd,const char ** args,uint32_t numArgs)220*4d7e907cSAndroid Build Coastguard Worker binder_status_t Wifi::dump(int fd, const char** args, uint32_t numArgs) {
221*4d7e907cSAndroid Build Coastguard Worker const auto lock = acquireGlobalLock();
222*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "-----------Debug was called----------------";
223*4d7e907cSAndroid Build Coastguard Worker if (chips_.size() != 0) {
224*4d7e907cSAndroid Build Coastguard Worker for (std::shared_ptr<WifiChip> chip : chips_) {
225*4d7e907cSAndroid Build Coastguard Worker if (!chip.get()) continue;
226*4d7e907cSAndroid Build Coastguard Worker chip->dump(fd, args, numArgs);
227*4d7e907cSAndroid Build Coastguard Worker }
228*4d7e907cSAndroid Build Coastguard Worker }
229*4d7e907cSAndroid Build Coastguard Worker uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
230*4d7e907cSAndroid Build Coastguard Worker if (n_error != 0) {
231*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << n_error << " errors occurred in cpio function";
232*4d7e907cSAndroid Build Coastguard Worker }
233*4d7e907cSAndroid Build Coastguard Worker ::android::base::WriteStringToFd("\n", fd);
234*4d7e907cSAndroid Build Coastguard Worker fsync(fd);
235*4d7e907cSAndroid Build Coastguard Worker return STATUS_OK;
236*4d7e907cSAndroid Build Coastguard Worker }
237*4d7e907cSAndroid Build Coastguard Worker
registerEventCallbackInternal(const std::shared_ptr<IWifiEventCallback> & event_callback)238*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::registerEventCallbackInternal(
239*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<IWifiEventCallback>& event_callback) {
240*4d7e907cSAndroid Build Coastguard Worker if (!event_cb_handler_.addCallback(event_callback)) {
241*4d7e907cSAndroid Build Coastguard Worker return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
242*4d7e907cSAndroid Build Coastguard Worker }
243*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
244*4d7e907cSAndroid Build Coastguard Worker }
245*4d7e907cSAndroid Build Coastguard Worker
startInternal()246*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::startInternal() {
247*4d7e907cSAndroid Build Coastguard Worker if (run_state_ == RunState::STARTED) {
248*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
249*4d7e907cSAndroid Build Coastguard Worker } else if (run_state_ == RunState::STOPPING) {
250*4d7e907cSAndroid Build Coastguard Worker return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
251*4d7e907cSAndroid Build Coastguard Worker }
252*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus wifi_status = initializeModeControllerAndLegacyHal();
253*4d7e907cSAndroid Build Coastguard Worker if (wifi_status.isOk()) {
254*4d7e907cSAndroid Build Coastguard Worker // Register the callback for subsystem restart
255*4d7e907cSAndroid Build Coastguard Worker const auto& on_subsystem_restart_callback = [this](const std::string& error) {
256*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
257*4d7e907cSAndroid Build Coastguard Worker for (const auto& callback : event_cb_handler_.getCallbacks()) {
258*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Attempting to invoke onSubsystemRestart "
259*4d7e907cSAndroid Build Coastguard Worker "callback";
260*4d7e907cSAndroid Build Coastguard Worker WifiStatusCode errorCode =
261*4d7e907cSAndroid Build Coastguard Worker static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
262*4d7e907cSAndroid Build Coastguard Worker if (!callback->onSubsystemRestart(errorCode).isOk()) {
263*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to invoke onSubsystemRestart callback";
264*4d7e907cSAndroid Build Coastguard Worker } else {
265*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
266*4d7e907cSAndroid Build Coastguard Worker "callback";
267*4d7e907cSAndroid Build Coastguard Worker }
268*4d7e907cSAndroid Build Coastguard Worker }
269*4d7e907cSAndroid Build Coastguard Worker };
270*4d7e907cSAndroid Build Coastguard Worker
271*4d7e907cSAndroid Build Coastguard Worker // Create the chip instance once the HAL is started.
272*4d7e907cSAndroid Build Coastguard Worker int32_t chipId = kPrimaryChipId;
273*4d7e907cSAndroid Build Coastguard Worker for (auto& hal : legacy_hals_) {
274*4d7e907cSAndroid Build Coastguard Worker chips_.push_back(
275*4d7e907cSAndroid Build Coastguard Worker WifiChip::create(chipId, chipId == kPrimaryChipId, hal, mode_controller_,
276*4d7e907cSAndroid Build Coastguard Worker std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
277*4d7e907cSAndroid Build Coastguard Worker feature_flags_, on_subsystem_restart_callback, false));
278*4d7e907cSAndroid Build Coastguard Worker chipId++;
279*4d7e907cSAndroid Build Coastguard Worker }
280*4d7e907cSAndroid Build Coastguard Worker run_state_ = RunState::STARTED;
281*4d7e907cSAndroid Build Coastguard Worker for (const auto& callback : event_cb_handler_.getCallbacks()) {
282*4d7e907cSAndroid Build Coastguard Worker if (!callback->onStart().isOk()) {
283*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to invoke onStart callback";
284*4d7e907cSAndroid Build Coastguard Worker };
285*4d7e907cSAndroid Build Coastguard Worker }
286*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Wifi HAL started";
287*4d7e907cSAndroid Build Coastguard Worker } else {
288*4d7e907cSAndroid Build Coastguard Worker for (const auto& callback : event_cb_handler_.getCallbacks()) {
289*4d7e907cSAndroid Build Coastguard Worker WifiStatusCode errorCode =
290*4d7e907cSAndroid Build Coastguard Worker static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
291*4d7e907cSAndroid Build Coastguard Worker if (!callback->onFailure(errorCode).isOk()) {
292*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to invoke onFailure callback";
293*4d7e907cSAndroid Build Coastguard Worker }
294*4d7e907cSAndroid Build Coastguard Worker }
295*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Wifi HAL start failed";
296*4d7e907cSAndroid Build Coastguard Worker // Clear the event callback objects since the HAL start failed.
297*4d7e907cSAndroid Build Coastguard Worker event_cb_handler_.invalidate();
298*4d7e907cSAndroid Build Coastguard Worker }
299*4d7e907cSAndroid Build Coastguard Worker return wifi_status;
300*4d7e907cSAndroid Build Coastguard Worker }
301*4d7e907cSAndroid Build Coastguard Worker
stopInternal(std::unique_lock<std::recursive_mutex> * lock)302*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::stopInternal(
303*4d7e907cSAndroid Build Coastguard Worker /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
304*4d7e907cSAndroid Build Coastguard Worker if (run_state_ == RunState::STOPPED) {
305*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
306*4d7e907cSAndroid Build Coastguard Worker } else if (run_state_ == RunState::STOPPING) {
307*4d7e907cSAndroid Build Coastguard Worker return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
308*4d7e907cSAndroid Build Coastguard Worker }
309*4d7e907cSAndroid Build Coastguard Worker // Clear the chip object and its child objects since the HAL is now
310*4d7e907cSAndroid Build Coastguard Worker // stopped.
311*4d7e907cSAndroid Build Coastguard Worker for (auto& chip : chips_) {
312*4d7e907cSAndroid Build Coastguard Worker if (chip.get()) {
313*4d7e907cSAndroid Build Coastguard Worker chip->invalidate();
314*4d7e907cSAndroid Build Coastguard Worker chip.reset();
315*4d7e907cSAndroid Build Coastguard Worker }
316*4d7e907cSAndroid Build Coastguard Worker }
317*4d7e907cSAndroid Build Coastguard Worker chips_.clear();
318*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
319*4d7e907cSAndroid Build Coastguard Worker if (wifi_status.isOk()) {
320*4d7e907cSAndroid Build Coastguard Worker for (const auto& callback : event_cb_handler_.getCallbacks()) {
321*4d7e907cSAndroid Build Coastguard Worker if (!callback->onStop().isOk()) {
322*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to invoke onStop callback";
323*4d7e907cSAndroid Build Coastguard Worker };
324*4d7e907cSAndroid Build Coastguard Worker }
325*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Wifi HAL stopped";
326*4d7e907cSAndroid Build Coastguard Worker } else {
327*4d7e907cSAndroid Build Coastguard Worker for (const auto& callback : event_cb_handler_.getCallbacks()) {
328*4d7e907cSAndroid Build Coastguard Worker WifiStatusCode errorCode =
329*4d7e907cSAndroid Build Coastguard Worker static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
330*4d7e907cSAndroid Build Coastguard Worker if (!callback->onFailure(errorCode).isOk()) {
331*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to invoke onFailure callback";
332*4d7e907cSAndroid Build Coastguard Worker }
333*4d7e907cSAndroid Build Coastguard Worker }
334*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Wifi HAL stop failed";
335*4d7e907cSAndroid Build Coastguard Worker }
336*4d7e907cSAndroid Build Coastguard Worker // Clear the event callback objects since the HAL is now stopped.
337*4d7e907cSAndroid Build Coastguard Worker event_cb_handler_.invalidate();
338*4d7e907cSAndroid Build Coastguard Worker return wifi_status;
339*4d7e907cSAndroid Build Coastguard Worker }
340*4d7e907cSAndroid Build Coastguard Worker
getChipIdsInternal()341*4d7e907cSAndroid Build Coastguard Worker std::pair<std::vector<int32_t>, ndk::ScopedAStatus> Wifi::getChipIdsInternal() {
342*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> chip_ids;
343*4d7e907cSAndroid Build Coastguard Worker
344*4d7e907cSAndroid Build Coastguard Worker for (auto& chip : chips_) {
345*4d7e907cSAndroid Build Coastguard Worker int32_t chip_id = getChipIdFromWifiChip(chip);
346*4d7e907cSAndroid Build Coastguard Worker if (chip_id != INT32_MAX) chip_ids.emplace_back(chip_id);
347*4d7e907cSAndroid Build Coastguard Worker }
348*4d7e907cSAndroid Build Coastguard Worker return {std::move(chip_ids), ndk::ScopedAStatus::ok()};
349*4d7e907cSAndroid Build Coastguard Worker }
350*4d7e907cSAndroid Build Coastguard Worker
getChipInternal(int32_t chip_id)351*4d7e907cSAndroid Build Coastguard Worker std::pair<std::shared_ptr<IWifiChip>, ndk::ScopedAStatus> Wifi::getChipInternal(int32_t chip_id) {
352*4d7e907cSAndroid Build Coastguard Worker for (auto& chip : chips_) {
353*4d7e907cSAndroid Build Coastguard Worker int32_t cand_id = getChipIdFromWifiChip(chip);
354*4d7e907cSAndroid Build Coastguard Worker if ((cand_id != INT32_MAX) && (cand_id == chip_id)) return {chip, ndk::ScopedAStatus::ok()};
355*4d7e907cSAndroid Build Coastguard Worker }
356*4d7e907cSAndroid Build Coastguard Worker
357*4d7e907cSAndroid Build Coastguard Worker return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
358*4d7e907cSAndroid Build Coastguard Worker }
359*4d7e907cSAndroid Build Coastguard Worker
initializeModeControllerAndLegacyHal()360*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::initializeModeControllerAndLegacyHal() {
361*4d7e907cSAndroid Build Coastguard Worker if (!mode_controller_->initialize()) {
362*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to initialize firmware mode controller";
363*4d7e907cSAndroid Build Coastguard Worker return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
364*4d7e907cSAndroid Build Coastguard Worker }
365*4d7e907cSAndroid Build Coastguard Worker
366*4d7e907cSAndroid Build Coastguard Worker legacy_hals_ = legacy_hal_factory_->getHals();
367*4d7e907cSAndroid Build Coastguard Worker if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
368*4d7e907cSAndroid Build Coastguard Worker int index = 0; // for failure log
369*4d7e907cSAndroid Build Coastguard Worker for (auto& hal : legacy_hals_) {
370*4d7e907cSAndroid Build Coastguard Worker legacy_hal::wifi_error legacy_status = hal->initialize();
371*4d7e907cSAndroid Build Coastguard Worker if (legacy_status != legacy_hal::WIFI_SUCCESS) {
372*4d7e907cSAndroid Build Coastguard Worker // Currently WifiLegacyHal::initialize does not allocate extra mem,
373*4d7e907cSAndroid Build Coastguard Worker // only initializes the function table. If this changes, need to
374*4d7e907cSAndroid Build Coastguard Worker // implement WifiLegacyHal::deinitialize and deinitalize the
375*4d7e907cSAndroid Build Coastguard Worker // HALs already initialized
376*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to initialize legacy HAL index: " << index
377*4d7e907cSAndroid Build Coastguard Worker << " error: " << legacyErrorToString(legacy_status);
378*4d7e907cSAndroid Build Coastguard Worker return createWifiStatusFromLegacyError(legacy_status);
379*4d7e907cSAndroid Build Coastguard Worker }
380*4d7e907cSAndroid Build Coastguard Worker index++;
381*4d7e907cSAndroid Build Coastguard Worker }
382*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
383*4d7e907cSAndroid Build Coastguard Worker }
384*4d7e907cSAndroid Build Coastguard Worker
stopLegacyHalAndDeinitializeModeController(std::unique_lock<std::recursive_mutex> * lock)385*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus Wifi::stopLegacyHalAndDeinitializeModeController(
386*4d7e907cSAndroid Build Coastguard Worker /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
387*4d7e907cSAndroid Build Coastguard Worker legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS;
388*4d7e907cSAndroid Build Coastguard Worker int index = 0;
389*4d7e907cSAndroid Build Coastguard Worker
390*4d7e907cSAndroid Build Coastguard Worker run_state_ = RunState::STOPPING;
391*4d7e907cSAndroid Build Coastguard Worker for (auto& hal : legacy_hals_) {
392*4d7e907cSAndroid Build Coastguard Worker legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {});
393*4d7e907cSAndroid Build Coastguard Worker if (tmp != legacy_hal::WIFI_SUCCESS) {
394*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to stop legacy HAL index: " << index
395*4d7e907cSAndroid Build Coastguard Worker << " error: " << legacyErrorToString(legacy_status);
396*4d7e907cSAndroid Build Coastguard Worker legacy_status = tmp;
397*4d7e907cSAndroid Build Coastguard Worker }
398*4d7e907cSAndroid Build Coastguard Worker index++;
399*4d7e907cSAndroid Build Coastguard Worker }
400*4d7e907cSAndroid Build Coastguard Worker run_state_ = RunState::STOPPED;
401*4d7e907cSAndroid Build Coastguard Worker
402*4d7e907cSAndroid Build Coastguard Worker if (legacy_status != legacy_hal::WIFI_SUCCESS) {
403*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "One or more legacy HALs failed to stop";
404*4d7e907cSAndroid Build Coastguard Worker return createWifiStatusFromLegacyError(legacy_status);
405*4d7e907cSAndroid Build Coastguard Worker }
406*4d7e907cSAndroid Build Coastguard Worker if (!mode_controller_->deinitialize()) {
407*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to deinitialize firmware mode controller";
408*4d7e907cSAndroid Build Coastguard Worker return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
409*4d7e907cSAndroid Build Coastguard Worker }
410*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
411*4d7e907cSAndroid Build Coastguard Worker }
412*4d7e907cSAndroid Build Coastguard Worker
getChipIdFromWifiChip(std::shared_ptr<WifiChip> & chip)413*4d7e907cSAndroid Build Coastguard Worker int32_t Wifi::getChipIdFromWifiChip(std::shared_ptr<WifiChip>& chip) {
414*4d7e907cSAndroid Build Coastguard Worker int32_t chip_id = INT32_MAX;
415*4d7e907cSAndroid Build Coastguard Worker if (chip.get()) {
416*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus status = chip->getId(&chip_id);
417*4d7e907cSAndroid Build Coastguard Worker if (!status.isOk()) {
418*4d7e907cSAndroid Build Coastguard Worker // Reset value if operation failed.
419*4d7e907cSAndroid Build Coastguard Worker chip_id = INT32_MAX;
420*4d7e907cSAndroid Build Coastguard Worker }
421*4d7e907cSAndroid Build Coastguard Worker }
422*4d7e907cSAndroid Build Coastguard Worker return chip_id;
423*4d7e907cSAndroid Build Coastguard Worker }
424*4d7e907cSAndroid Build Coastguard Worker
425*4d7e907cSAndroid Build Coastguard Worker } // namespace wifi
426*4d7e907cSAndroid Build Coastguard Worker } // namespace hardware
427*4d7e907cSAndroid Build Coastguard Worker } // namespace android
428*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl
429