xref: /aosp_15_r20/hardware/interfaces/wifi/aidl/default/wifi.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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