blob: 076f35144857eb3c33e5cb3b8f29583b0059ded7 [file] [log] [blame]
Gabriel Birenf3262f92022-07-15 23:25:39 +00001/*
2 * Copyright (C) 2022 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 "wifi_chip.h"
18
19#include <android-base/logging.h>
20#include <android-base/unique_fd.h>
21#include <cutils/properties.h>
22#include <fcntl.h>
23#include <net/if.h>
24#include <sys/stat.h>
25#include <sys/sysmacros.h>
26
27#include "aidl_return_util.h"
28#include "aidl_struct_util.h"
29#include "wifi_status_util.h"
30
31#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
32
33namespace {
34using aidl::android::hardware::wifi::IfaceType;
35using aidl::android::hardware::wifi::IWifiChip;
36using CoexRestriction = aidl::android::hardware::wifi::IWifiChip::CoexRestriction;
37using android::base::unique_fd;
38
39constexpr char kCpioMagic[] = "070701";
40constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3;
41constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
42constexpr uint32_t kMaxRingBufferFileNum = 20;
43constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
44constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
45constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
46constexpr unsigned kMaxWlanIfaces = 5;
47constexpr char kApBridgeIfacePrefix[] = "ap_br_";
48
49template <typename Iface>
50void invalidateAndClear(std::vector<std::shared_ptr<Iface>>& ifaces, std::shared_ptr<Iface> iface) {
51 iface->invalidate();
52 ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), ifaces.end());
53}
54
55template <typename Iface>
56void invalidateAndClearAll(std::vector<std::shared_ptr<Iface>>& ifaces) {
57 for (const auto& iface : ifaces) {
58 iface->invalidate();
59 }
60 ifaces.clear();
61}
62
63template <typename Iface>
64std::vector<std::string> getNames(std::vector<std::shared_ptr<Iface>>& ifaces) {
65 std::vector<std::string> names;
66 for (const auto& iface : ifaces) {
67 names.emplace_back(iface->getName());
68 }
69 return names;
70}
71
72template <typename Iface>
73std::shared_ptr<Iface> findUsingName(std::vector<std::shared_ptr<Iface>>& ifaces,
74 const std::string& name) {
75 std::vector<std::string> names;
76 for (const auto& iface : ifaces) {
77 if (name == iface->getName()) {
78 return iface;
79 }
80 }
81 return nullptr;
82}
83
84std::string getWlanIfaceName(unsigned idx) {
85 if (idx >= kMaxWlanIfaces) {
86 CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces;
87 return {};
88 }
89
90 std::array<char, PROPERTY_VALUE_MAX> buffer;
91 if (idx == 0 || idx == 1) {
92 const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
93 auto res = property_get(altPropName, buffer.data(), nullptr);
94 if (res > 0) return buffer.data();
95 }
96 std::string propName = "wifi.interface." + std::to_string(idx);
97 auto res = property_get(propName.c_str(), buffer.data(), nullptr);
98 if (res > 0) return buffer.data();
99
100 return "wlan" + std::to_string(idx);
101}
102
103// Returns the dedicated iface name if defined.
104// Returns two ifaces in bridged mode.
105std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) {
106 std::vector<std::string> ifnames;
107 std::array<char, PROPERTY_VALUE_MAX> buffer;
108 buffer.fill(0);
109 if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) {
110 return ifnames;
111 }
112 ifnames.push_back(buffer.data());
113 if (is_bridged) {
114 buffer.fill(0);
115 if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), nullptr) == 0) {
116 return ifnames;
117 }
118 ifnames.push_back(buffer.data());
119 }
120 return ifnames;
121}
122
123std::string getPredefinedP2pIfaceName() {
124 std::array<char, PROPERTY_VALUE_MAX> primaryIfaceName;
125 char p2pParentIfname[100];
126 std::string p2pDevIfName = "";
127 std::array<char, PROPERTY_VALUE_MAX> buffer;
128 property_get("wifi.direct.interface", buffer.data(), "p2p0");
129 if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX, strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
130 /* Get the p2p parent interface name from p2p device interface name set
131 * in property */
132 strlcpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX),
133 strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX));
134 if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(), nullptr) == 0) {
135 return buffer.data();
136 }
137 /* Check if the parent interface derived from p2p device interface name
138 * is active */
139 if (strncmp(p2pParentIfname, primaryIfaceName.data(),
140 strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) != 0) {
141 /*
142 * Update the predefined p2p device interface parent interface name
143 * with current active wlan interface
144 */
145 p2pDevIfName += P2P_MGMT_DEVICE_PREFIX;
146 p2pDevIfName += primaryIfaceName.data();
147 LOG(INFO) << "update the p2p device interface name to " << p2pDevIfName.c_str();
148 return p2pDevIfName;
149 }
150 }
151 return buffer.data();
152}
153
154// Returns the dedicated iface name if one is defined.
155std::string getPredefinedNanIfaceName() {
156 std::array<char, PROPERTY_VALUE_MAX> buffer;
157 if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
158 return {};
159 }
160 return buffer.data();
161}
162
163void setActiveWlanIfaceNameProperty(const std::string& ifname) {
164 auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data());
165 if (res != 0) {
166 PLOG(ERROR) << "Failed to set active wlan iface name property";
167 }
168}
169
170// Delete files that meet either condition:
171// 1. Older than a predefined time in the wifi tombstone dir.
172// 2. Files in excess to a predefined amount, starting from the oldest ones
173bool removeOldFilesInternal() {
174 time_t now = time(0);
175 const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
176 std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(kTombstoneFolderPath), closedir);
177 if (!dir_dump) {
178 PLOG(ERROR) << "Failed to open directory";
179 return false;
180 }
181 struct dirent* dp;
182 bool success = true;
183 std::list<std::pair<const time_t, std::string>> valid_files;
184 while ((dp = readdir(dir_dump.get()))) {
185 if (dp->d_type != DT_REG) {
186 continue;
187 }
188 std::string cur_file_name(dp->d_name);
189 struct stat cur_file_stat;
190 std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
191 if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
192 PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
193 success = false;
194 continue;
195 }
196 const time_t cur_file_time = cur_file_stat.st_mtime;
197 valid_files.push_back(std::pair<const time_t, std::string>(cur_file_time, cur_file_path));
198 }
199 valid_files.sort(); // sort the list of files by last modified time from
200 // small to big.
201 uint32_t cur_file_count = valid_files.size();
202 for (auto cur_file : valid_files) {
203 if (cur_file_count > kMaxRingBufferFileNum || cur_file.first < delete_files_before) {
204 if (unlink(cur_file.second.c_str()) != 0) {
205 PLOG(ERROR) << "Error deleting file";
206 success = false;
207 }
208 cur_file_count--;
209 } else {
210 break;
211 }
212 }
213 return success;
214}
215
216// Helper function for |cpioArchiveFilesInDir|
217bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
218 const int buf_size = 32 * 1024;
219 std::array<char, buf_size> read_buf;
220 ssize_t llen = snprintf(
221 read_buf.data(), buf_size, "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
222 kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, st.st_gid,
223 static_cast<int>(st.st_nlink), static_cast<int>(st.st_mtime),
224 static_cast<int>(st.st_size), major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
225 minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
226 if (write(out_fd, read_buf.data(), llen < buf_size ? llen : buf_size - 1) == -1) {
227 PLOG(ERROR) << "Error writing cpio header to file " << file_name;
228 return false;
229 }
230 if (write(out_fd, file_name, file_name_len) == -1) {
231 PLOG(ERROR) << "Error writing filename to file " << file_name;
232 return false;
233 }
234
235 // NUL Pad header up to 4 multiple bytes.
236 llen = (llen + file_name_len) % 4;
237 if (llen != 0) {
238 const uint32_t zero = 0;
239 if (write(out_fd, &zero, 4 - llen) == -1) {
240 PLOG(ERROR) << "Error padding 0s to file " << file_name;
241 return false;
242 }
243 }
244 return true;
245}
246
247// Helper function for |cpioArchiveFilesInDir|
248size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
249 // writing content of file
250 std::array<char, 32 * 1024> read_buf;
251 ssize_t llen = st.st_size;
252 size_t n_error = 0;
253 while (llen > 0) {
254 ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
255 if (bytes_read == -1) {
256 PLOG(ERROR) << "Error reading file";
257 return ++n_error;
258 }
259 llen -= bytes_read;
260 if (write(out_fd, read_buf.data(), bytes_read) == -1) {
261 PLOG(ERROR) << "Error writing data to file";
262 return ++n_error;
263 }
264 if (bytes_read == 0) { // this should never happen, but just in case
265 // to unstuck from while loop
266 PLOG(ERROR) << "Unexpected read result";
267 n_error++;
268 break;
269 }
270 }
271 llen = st.st_size % 4;
272 if (llen != 0) {
273 const uint32_t zero = 0;
274 if (write(out_fd, &zero, 4 - llen) == -1) {
275 PLOG(ERROR) << "Error padding 0s to file";
276 return ++n_error;
277 }
278 }
279 return n_error;
280}
281
282// Helper function for |cpioArchiveFilesInDir|
283bool cpioWriteFileTrailer(int out_fd) {
284 const int buf_size = 4096;
285 std::array<char, buf_size> read_buf;
286 read_buf.fill(0);
287 ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0);
288 if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) {
289 PLOG(ERROR) << "Error writing trailing bytes";
290 return false;
291 }
292 return true;
293}
294
295// Archives all files in |input_dir| and writes result into |out_fd|
296// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
297// portion
298size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
299 struct dirent* dp;
300 size_t n_error = 0;
301 std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
302 if (!dir_dump) {
303 PLOG(ERROR) << "Failed to open directory";
304 return ++n_error;
305 }
306 while ((dp = readdir(dir_dump.get()))) {
307 if (dp->d_type != DT_REG) {
308 continue;
309 }
310 std::string cur_file_name(dp->d_name);
311 struct stat st;
312 const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
313 if (stat(cur_file_path.c_str(), &st) == -1) {
314 PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
315 n_error++;
316 continue;
317 }
318 const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
319 if (fd_read == -1) {
320 PLOG(ERROR) << "Failed to open file " << cur_file_path;
321 n_error++;
322 continue;
323 }
324 std::string file_name_with_last_modified_time =
325 cur_file_name + "-" + std::to_string(st.st_mtime);
326 // string.size() does not include the null terminator. The cpio FreeBSD
327 // file header expects the null character to be included in the length.
328 const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
329 unique_fd file_auto_closer(fd_read);
330 if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
331 file_name_len)) {
332 return ++n_error;
333 }
334 size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
335 if (write_error) {
336 return n_error + write_error;
337 }
338 }
339 if (!cpioWriteFileTrailer(out_fd)) {
340 return ++n_error;
341 }
342 return n_error;
343}
344
345// Helper function to create a non-const char*.
346std::vector<char> makeCharVec(const std::string& str) {
347 std::vector<char> vec(str.size() + 1);
348 vec.assign(str.begin(), str.end());
349 vec.push_back('\0');
350 return vec;
351}
352
353} // namespace
354
355namespace aidl {
356namespace android {
357namespace hardware {
358namespace wifi {
359using aidl_return_util::validateAndCall;
360using aidl_return_util::validateAndCallWithLock;
361
362WifiChip::WifiChip(int32_t chip_id, bool is_primary,
363 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
364 const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
365 const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
366 const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
367 const std::function<void(const std::string&)>& handler)
368 : chip_id_(chip_id),
369 legacy_hal_(legacy_hal),
370 mode_controller_(mode_controller),
371 iface_util_(iface_util),
372 is_valid_(true),
373 current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
374 modes_(feature_flags.lock()->getChipModes(is_primary)),
375 debug_ring_buffer_cb_registered_(false),
376 subsystemCallbackHandler_(handler) {
377 setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
378}
379
380std::shared_ptr<WifiChip> WifiChip::create(
381 int32_t chip_id, bool is_primary, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
382 const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
383 const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
384 const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
385 const std::function<void(const std::string&)>& handler) {
386 std::shared_ptr<WifiChip> ptr = ndk::SharedRefBase::make<WifiChip>(
387 chip_id, is_primary, legacy_hal, mode_controller, iface_util, feature_flags, handler);
388 std::weak_ptr<WifiChip> weak_ptr_this(ptr);
389 ptr->setWeakPtr(weak_ptr_this);
390 return ptr;
391}
392
393void WifiChip::invalidate() {
394 if (!writeRingbufferFilesInternal()) {
395 LOG(ERROR) << "Error writing files to flash";
396 }
397 invalidateAndRemoveAllIfaces();
398 setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
399 legacy_hal_.reset();
400 event_cb_handler_.invalidate();
401 is_valid_ = false;
402}
403
404void WifiChip::setWeakPtr(std::weak_ptr<WifiChip> ptr) {
405 weak_ptr_this_ = ptr;
406}
407
408bool WifiChip::isValid() {
409 return is_valid_;
410}
411
412std::set<std::shared_ptr<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
413 return event_cb_handler_.getCallbacks();
414}
415
416ndk::ScopedAStatus WifiChip::getId(int32_t* _aidl_return) {
417 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getIdInternal,
418 _aidl_return);
419}
420
421ndk::ScopedAStatus WifiChip::registerEventCallback(
422 const std::shared_ptr<IWifiChipEventCallback>& event_callback) {
423 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
424 &WifiChip::registerEventCallbackInternal, event_callback);
425}
426
427ndk::ScopedAStatus WifiChip::getCapabilities(IWifiChip::ChipCapabilityMask* _aidl_return) {
428 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
429 &WifiChip::getCapabilitiesInternal, _aidl_return);
430}
431
432ndk::ScopedAStatus WifiChip::getAvailableModes(std::vector<IWifiChip::ChipMode>* _aidl_return) {
433 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
434 &WifiChip::getAvailableModesInternal, _aidl_return);
435}
436
437ndk::ScopedAStatus WifiChip::configureChip(int32_t in_modeId) {
438 return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
439 &WifiChip::configureChipInternal, in_modeId);
440}
441
442ndk::ScopedAStatus WifiChip::getMode(int32_t* _aidl_return) {
443 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
444 &WifiChip::getModeInternal, _aidl_return);
445}
446
447ndk::ScopedAStatus WifiChip::requestChipDebugInfo(IWifiChip::ChipDebugInfo* _aidl_return) {
448 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
449 &WifiChip::requestChipDebugInfoInternal, _aidl_return);
450}
451
452ndk::ScopedAStatus WifiChip::requestDriverDebugDump(std::vector<uint8_t>* _aidl_return) {
453 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
454 &WifiChip::requestDriverDebugDumpInternal, _aidl_return);
455}
456
457ndk::ScopedAStatus WifiChip::requestFirmwareDebugDump(std::vector<uint8_t>* _aidl_return) {
458 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
459 &WifiChip::requestFirmwareDebugDumpInternal, _aidl_return);
460}
461
462ndk::ScopedAStatus WifiChip::createApIface(std::shared_ptr<IWifiApIface>* _aidl_return) {
463 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
464 &WifiChip::createApIfaceInternal, _aidl_return);
465}
466
467ndk::ScopedAStatus WifiChip::createBridgedApIface(std::shared_ptr<IWifiApIface>* _aidl_return) {
468 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
469 &WifiChip::createBridgedApIfaceInternal, _aidl_return);
470}
471
472ndk::ScopedAStatus WifiChip::getApIfaceNames(std::vector<std::string>* _aidl_return) {
473 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
474 &WifiChip::getApIfaceNamesInternal, _aidl_return);
475}
476
477ndk::ScopedAStatus WifiChip::getApIface(const std::string& in_ifname,
478 std::shared_ptr<IWifiApIface>* _aidl_return) {
479 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
480 &WifiChip::getApIfaceInternal, _aidl_return, in_ifname);
481}
482
483ndk::ScopedAStatus WifiChip::removeApIface(const std::string& in_ifname) {
484 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
485 &WifiChip::removeApIfaceInternal, in_ifname);
486}
487
488ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIface(
489 const std::string& in_brIfaceName, const std::string& in_ifaceInstanceName) {
490 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
491 &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, in_brIfaceName,
492 in_ifaceInstanceName);
493}
494
495ndk::ScopedAStatus WifiChip::createNanIface(std::shared_ptr<IWifiNanIface>* _aidl_return) {
496 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
497 &WifiChip::createNanIfaceInternal, _aidl_return);
498}
499
500ndk::ScopedAStatus WifiChip::getNanIfaceNames(std::vector<std::string>* _aidl_return) {
501 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
502 &WifiChip::getNanIfaceNamesInternal, _aidl_return);
503}
504
505ndk::ScopedAStatus WifiChip::getNanIface(const std::string& in_ifname,
506 std::shared_ptr<IWifiNanIface>* _aidl_return) {
507 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
508 &WifiChip::getNanIfaceInternal, _aidl_return, in_ifname);
509}
510
511ndk::ScopedAStatus WifiChip::removeNanIface(const std::string& in_ifname) {
512 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
513 &WifiChip::removeNanIfaceInternal, in_ifname);
514}
515
516ndk::ScopedAStatus WifiChip::createP2pIface(std::shared_ptr<IWifiP2pIface>* _aidl_return) {
517 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
518 &WifiChip::createP2pIfaceInternal, _aidl_return);
519}
520
521ndk::ScopedAStatus WifiChip::getP2pIfaceNames(std::vector<std::string>* _aidl_return) {
522 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
523 &WifiChip::getP2pIfaceNamesInternal, _aidl_return);
524}
525
526ndk::ScopedAStatus WifiChip::getP2pIface(const std::string& in_ifname,
527 std::shared_ptr<IWifiP2pIface>* _aidl_return) {
528 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
529 &WifiChip::getP2pIfaceInternal, _aidl_return, in_ifname);
530}
531
532ndk::ScopedAStatus WifiChip::removeP2pIface(const std::string& in_ifname) {
533 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
534 &WifiChip::removeP2pIfaceInternal, in_ifname);
535}
536
537ndk::ScopedAStatus WifiChip::createStaIface(std::shared_ptr<IWifiStaIface>* _aidl_return) {
538 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
539 &WifiChip::createStaIfaceInternal, _aidl_return);
540}
541
542ndk::ScopedAStatus WifiChip::getStaIfaceNames(std::vector<std::string>* _aidl_return) {
543 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
544 &WifiChip::getStaIfaceNamesInternal, _aidl_return);
545}
546
547ndk::ScopedAStatus WifiChip::getStaIface(const std::string& in_ifname,
548 std::shared_ptr<IWifiStaIface>* _aidl_return) {
549 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
550 &WifiChip::getStaIfaceInternal, _aidl_return, in_ifname);
551}
552
553ndk::ScopedAStatus WifiChip::removeStaIface(const std::string& in_ifname) {
554 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
555 &WifiChip::removeStaIfaceInternal, in_ifname);
556}
557
558ndk::ScopedAStatus WifiChip::createRttController(
559 const std::shared_ptr<IWifiStaIface>& in_boundIface,
560 std::shared_ptr<IWifiRttController>* _aidl_return) {
561 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
562 &WifiChip::createRttControllerInternal, _aidl_return, in_boundIface);
563}
564
565ndk::ScopedAStatus WifiChip::getDebugRingBuffersStatus(
566 std::vector<WifiDebugRingBufferStatus>* _aidl_return) {
567 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
568 &WifiChip::getDebugRingBuffersStatusInternal, _aidl_return);
569}
570
571ndk::ScopedAStatus WifiChip::startLoggingToDebugRingBuffer(
572 const std::string& in_ringName, WifiDebugRingBufferVerboseLevel in_verboseLevel,
573 int32_t in_maxIntervalInSec, int32_t in_minDataSizeInBytes) {
574 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
575 &WifiChip::startLoggingToDebugRingBufferInternal, in_ringName,
576 in_verboseLevel, in_maxIntervalInSec, in_minDataSizeInBytes);
577}
578
579ndk::ScopedAStatus WifiChip::forceDumpToDebugRingBuffer(const std::string& in_ringName) {
580 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
581 &WifiChip::forceDumpToDebugRingBufferInternal, in_ringName);
582}
583
584ndk::ScopedAStatus WifiChip::flushRingBufferToFile() {
585 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
586 &WifiChip::flushRingBufferToFileInternal);
587}
588
589ndk::ScopedAStatus WifiChip::stopLoggingToDebugRingBuffer() {
590 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
591 &WifiChip::stopLoggingToDebugRingBufferInternal);
592}
593
594ndk::ScopedAStatus WifiChip::getDebugHostWakeReasonStats(
595 WifiDebugHostWakeReasonStats* _aidl_return) {
596 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
597 &WifiChip::getDebugHostWakeReasonStatsInternal, _aidl_return);
598}
599
600ndk::ScopedAStatus WifiChip::enableDebugErrorAlerts(bool in_enable) {
601 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
602 &WifiChip::enableDebugErrorAlertsInternal, in_enable);
603}
604
605ndk::ScopedAStatus WifiChip::selectTxPowerScenario(IWifiChip::TxPowerScenario in_scenario) {
606 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
607 &WifiChip::selectTxPowerScenarioInternal, in_scenario);
608}
609
610ndk::ScopedAStatus WifiChip::resetTxPowerScenario() {
611 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
612 &WifiChip::resetTxPowerScenarioInternal);
613}
614
615ndk::ScopedAStatus WifiChip::setLatencyMode(IWifiChip::LatencyMode in_mode) {
616 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
617 &WifiChip::setLatencyModeInternal, in_mode);
618}
619
620binder_status_t WifiChip::dump(int fd, const char**, uint32_t) {
621 {
622 std::unique_lock<std::mutex> lk(lock_t);
623 for (const auto& item : ringbuffer_map_) {
624 forceDumpToDebugRingBufferInternal(item.first);
625 }
626 // unique_lock unlocked here
627 }
628 usleep(100 * 1000); // sleep for 100 milliseconds to wait for
629 // ringbuffer updates.
630 if (!writeRingbufferFilesInternal()) {
631 LOG(ERROR) << "Error writing files to flash";
632 }
633 uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
634 if (n_error != 0) {
635 LOG(ERROR) << n_error << " errors occurred in cpio function";
636 }
637 fsync(fd);
638 return STATUS_OK;
639}
640
641ndk::ScopedAStatus WifiChip::setMultiStaPrimaryConnection(const std::string& in_ifName) {
642 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
643 &WifiChip::setMultiStaPrimaryConnectionInternal, in_ifName);
644}
645
646ndk::ScopedAStatus WifiChip::setMultiStaUseCase(IWifiChip::MultiStaUseCase in_useCase) {
647 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
648 &WifiChip::setMultiStaUseCaseInternal, in_useCase);
649}
650
651ndk::ScopedAStatus WifiChip::setCoexUnsafeChannels(
652 const std::vector<IWifiChip::CoexUnsafeChannel>& in_unsafeChannels,
653 CoexRestriction in_restrictions) {
654 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
655 &WifiChip::setCoexUnsafeChannelsInternal, in_unsafeChannels,
656 in_restrictions);
657}
658
659ndk::ScopedAStatus WifiChip::setCountryCode(const std::array<uint8_t, 2>& in_code) {
660 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
661 &WifiChip::setCountryCodeInternal, in_code);
662}
663
664ndk::ScopedAStatus WifiChip::getUsableChannels(WifiBand in_band, WifiIfaceMode in_ifaceModeMask,
665 UsableChannelFilter in_filterMask,
666 std::vector<WifiUsableChannel>* _aidl_return) {
667 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
668 &WifiChip::getUsableChannelsInternal, _aidl_return, in_band,
669 in_ifaceModeMask, in_filterMask);
670}
671
672ndk::ScopedAStatus WifiChip::triggerSubsystemRestart() {
673 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
674 &WifiChip::triggerSubsystemRestartInternal);
675}
676
677ndk::ScopedAStatus WifiChip::getSupportedRadioCombinationsMatrix(
678 WifiRadioCombinationMatrix* _aidl_return) {
679 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
680 &WifiChip::getSupportedRadioCombinationsMatrixInternal, _aidl_return);
681}
682
683void WifiChip::invalidateAndRemoveAllIfaces() {
684 invalidateAndClearBridgedApAll();
685 invalidateAndClearAll(ap_ifaces_);
686 invalidateAndClearAll(nan_ifaces_);
687 invalidateAndClearAll(p2p_ifaces_);
688 invalidateAndClearAll(sta_ifaces_);
689 // Since all the ifaces are invalid now, all RTT controller objects
690 // using those ifaces also need to be invalidated.
691 for (const auto& rtt : rtt_controllers_) {
692 rtt->invalidate();
693 }
694 rtt_controllers_.clear();
695}
696
697void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) {
698 for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) {
699 auto nan_iface = *it;
700 if (nan_iface->getName() == removed_iface_name) {
701 nan_iface->invalidate();
702 for (const auto& callback : event_cb_handler_.getCallbacks()) {
703 if (!callback->onIfaceRemoved(IfaceType::NAN_IFACE, removed_iface_name).isOk()) {
704 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
705 }
706 }
707 it = nan_ifaces_.erase(it);
708 } else {
709 ++it;
710 }
711 }
712
713 for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) {
714 auto rtt = *it;
715 if (rtt->getIfaceName() == removed_iface_name) {
716 rtt->invalidate();
717 it = rtt_controllers_.erase(it);
718 } else {
719 ++it;
720 }
721 }
722}
723
724std::pair<int32_t, ndk::ScopedAStatus> WifiChip::getIdInternal() {
725 return {chip_id_, ndk::ScopedAStatus::ok()};
726}
727
728ndk::ScopedAStatus WifiChip::registerEventCallbackInternal(
729 const std::shared_ptr<IWifiChipEventCallback>& event_callback) {
730 if (!event_cb_handler_.addCallback(event_callback)) {
731 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
732 }
733 return ndk::ScopedAStatus::ok();
734}
735
736std::pair<IWifiChip::ChipCapabilityMask, ndk::ScopedAStatus> WifiChip::getCapabilitiesInternal() {
737 legacy_hal::wifi_error legacy_status;
738 uint64_t legacy_feature_set;
739 uint32_t legacy_logger_feature_set;
740 const auto ifname = getFirstActiveWlanIfaceName();
741 std::tie(legacy_status, legacy_feature_set) =
742 legacy_hal_.lock()->getSupportedFeatureSet(ifname);
743 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
744 return {IWifiChip::ChipCapabilityMask{}, createWifiStatusFromLegacyError(legacy_status)};
745 }
746 std::tie(legacy_status, legacy_logger_feature_set) =
747 legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
748 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
749 // some devices don't support querying logger feature set
750 legacy_logger_feature_set = 0;
751 }
752 uint32_t aidl_caps;
753 if (!aidl_struct_util::convertLegacyFeaturesToAidlChipCapabilities(
754 legacy_feature_set, legacy_logger_feature_set, &aidl_caps)) {
755 return {IWifiChip::ChipCapabilityMask{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
756 }
757 return {static_cast<IWifiChip::ChipCapabilityMask>(aidl_caps), ndk::ScopedAStatus::ok()};
758}
759
760std::pair<std::vector<IWifiChip::ChipMode>, ndk::ScopedAStatus>
761WifiChip::getAvailableModesInternal() {
762 return {modes_, ndk::ScopedAStatus::ok()};
763}
764
765ndk::ScopedAStatus WifiChip::configureChipInternal(
766 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, int32_t mode_id) {
767 if (!isValidModeId(mode_id)) {
768 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
769 }
770 if (mode_id == current_mode_id_) {
771 LOG(DEBUG) << "Already in the specified mode " << mode_id;
772 return ndk::ScopedAStatus::ok();
773 }
774 ndk::ScopedAStatus status = handleChipConfiguration(lock, mode_id);
775 if (!status.isOk()) {
776 WifiStatusCode errorCode = static_cast<WifiStatusCode>(status.getServiceSpecificError());
777 for (const auto& callback : event_cb_handler_.getCallbacks()) {
778 if (!callback->onChipReconfigureFailure(errorCode).isOk()) {
779 LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
780 }
781 }
782 return status;
783 }
784 for (const auto& callback : event_cb_handler_.getCallbacks()) {
785 if (!callback->onChipReconfigured(mode_id).isOk()) {
786 LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
787 }
788 }
789 current_mode_id_ = mode_id;
790 LOG(INFO) << "Configured chip in mode " << mode_id;
791 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
792
793 legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_);
794
795 return status;
796}
797
798std::pair<int32_t, ndk::ScopedAStatus> WifiChip::getModeInternal() {
799 if (!isValidModeId(current_mode_id_)) {
800 return {current_mode_id_, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
801 }
802 return {current_mode_id_, ndk::ScopedAStatus::ok()};
803}
804
805std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> WifiChip::requestChipDebugInfoInternal() {
806 IWifiChip::ChipDebugInfo result;
807 legacy_hal::wifi_error legacy_status;
808 std::string driver_desc;
809 const auto ifname = getFirstActiveWlanIfaceName();
810 std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname);
811 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
812 LOG(ERROR) << "Failed to get driver version: " << legacyErrorToString(legacy_status);
813 ndk::ScopedAStatus status =
814 createWifiStatusFromLegacyError(legacy_status, "failed to get driver version");
815 return {std::move(result), std::move(status)};
816 }
817 result.driverDescription = driver_desc.c_str();
818
819 std::string firmware_desc;
820 std::tie(legacy_status, firmware_desc) = legacy_hal_.lock()->getFirmwareVersion(ifname);
821 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
822 LOG(ERROR) << "Failed to get firmware version: " << legacyErrorToString(legacy_status);
823 ndk::ScopedAStatus status =
824 createWifiStatusFromLegacyError(legacy_status, "failed to get firmware version");
825 return {std::move(result), std::move(status)};
826 }
827 result.firmwareDescription = firmware_desc.c_str();
828
829 return {std::move(result), ndk::ScopedAStatus::ok()};
830}
831
832std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> WifiChip::requestDriverDebugDumpInternal() {
833 legacy_hal::wifi_error legacy_status;
834 std::vector<uint8_t> driver_dump;
835 std::tie(legacy_status, driver_dump) =
836 legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName());
837 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
838 LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status);
839 return {std::vector<uint8_t>(), createWifiStatusFromLegacyError(legacy_status)};
840 }
841 return {driver_dump, ndk::ScopedAStatus::ok()};
842}
843
844std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> WifiChip::requestFirmwareDebugDumpInternal() {
845 legacy_hal::wifi_error legacy_status;
846 std::vector<uint8_t> firmware_dump;
847 std::tie(legacy_status, firmware_dump) =
848 legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName());
849 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
850 LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status);
851 return {std::vector<uint8_t>(), createWifiStatusFromLegacyError(legacy_status)};
852 }
853 return {firmware_dump, ndk::ScopedAStatus::ok()};
854}
855
856ndk::ScopedAStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
857 legacy_hal::wifi_error legacy_status;
858 legacy_status = legacy_hal_.lock()->createVirtualInterface(
859 apVirtIf, aidl_struct_util::convertAidlIfaceTypeToLegacy(IfaceType::AP));
860 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
861 LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
862 << legacyErrorToString(legacy_status);
863 return createWifiStatusFromLegacyError(legacy_status);
864 }
865 return ndk::ScopedAStatus::ok();
866}
867
868std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
869 std::vector<std::string> ap_instances;
870 for (auto const& it : br_ifaces_ap_instances_) {
871 if (it.first == ifname) {
872 ap_instances = it.second;
873 }
874 }
875 std::shared_ptr<WifiApIface> iface =
876 ndk::SharedRefBase::make<WifiApIface>(ifname, ap_instances, legacy_hal_, iface_util_);
877 ap_ifaces_.push_back(iface);
878 for (const auto& callback : event_cb_handler_.getCallbacks()) {
879 if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
880 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
881 }
882 }
883 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
884 return iface;
885}
886
887std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createApIfaceInternal() {
888 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP)) {
889 return {std::shared_ptr<WifiApIface>(),
890 createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
891 }
892 std::string ifname = allocateApIfaceName();
893 ndk::ScopedAStatus status = createVirtualApInterface(ifname);
894 if (!status.isOk()) {
895 return {std::shared_ptr<WifiApIface>(), std::move(status)};
896 }
897 std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname);
898 return {iface, ndk::ScopedAStatus::ok()};
899}
900
901std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
902WifiChip::createBridgedApIfaceInternal() {
903 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
904 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
905 }
906 std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
907 if (ap_instances.size() < 2) {
908 LOG(ERROR) << "Fail to allocate two instances";
909 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
910 }
911 std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
912 for (int i = 0; i < 2; i++) {
913 ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
914 if (!status.isOk()) {
915 if (i != 0) { // The failure happened when creating second virtual
916 // iface.
917 legacy_hal_.lock()->deleteVirtualInterface(
918 ap_instances.front()); // Remove the first virtual iface.
919 }
920 return {nullptr, std::move(status)};
921 }
922 }
923 br_ifaces_ap_instances_[br_ifname] = ap_instances;
924 if (!iface_util_->createBridge(br_ifname)) {
925 LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
926 invalidateAndClearBridgedAp(br_ifname);
927 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
928 }
929 for (auto const& instance : ap_instances) {
930 // Bind ap instance interface to AP bridge
931 if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
932 LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
933 invalidateAndClearBridgedAp(br_ifname);
934 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
935 }
936 }
937 std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname);
938 return {iface, ndk::ScopedAStatus::ok()};
939}
940
941std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getApIfaceNamesInternal() {
942 if (ap_ifaces_.empty()) {
943 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
944 }
945 return {getNames(ap_ifaces_), ndk::ScopedAStatus::ok()};
946}
947
948std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::getApIfaceInternal(
949 const std::string& ifname) {
950 const auto iface = findUsingName(ap_ifaces_, ifname);
951 if (!iface.get()) {
952 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
953 }
954 return {iface, ndk::ScopedAStatus::ok()};
955}
956
957ndk::ScopedAStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
958 const auto iface = findUsingName(ap_ifaces_, ifname);
959 if (!iface.get()) {
960 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
961 }
962 // Invalidate & remove any dependent objects first.
963 // Note: This is probably not required because we never create
964 // nan/rtt objects over AP iface. But, there is no harm to do it
965 // here and not make that assumption all over the place.
966 invalidateAndRemoveDependencies(ifname);
967 // Clear the bridge interface and the iface instance.
968 invalidateAndClearBridgedAp(ifname);
969 invalidateAndClear(ap_ifaces_, iface);
970 for (const auto& callback : event_cb_handler_.getCallbacks()) {
971 if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
972 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
973 }
974 }
975 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
976 return ndk::ScopedAStatus::ok();
977}
978
979ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
980 const std::string& ifname, const std::string& ifInstanceName) {
981 const auto iface = findUsingName(ap_ifaces_, ifname);
982 if (!iface.get() || ifInstanceName.empty()) {
983 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
984 }
985 // Requires to remove one of the instance in bridge mode
986 for (auto const& it : br_ifaces_ap_instances_) {
987 if (it.first == ifname) {
988 std::vector<std::string> ap_instances = it.second;
989 for (auto const& iface : ap_instances) {
990 if (iface == ifInstanceName) {
991 if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
992 LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
993 << ifname;
994 return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
995 }
996 legacy_hal::wifi_error legacy_status =
997 legacy_hal_.lock()->deleteVirtualInterface(iface);
998 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
999 LOG(ERROR) << "Failed to del interface: " << iface << " "
1000 << legacyErrorToString(legacy_status);
1001 return createWifiStatusFromLegacyError(legacy_status);
1002 }
1003 ap_instances.erase(
1004 std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
1005 ap_instances.end());
1006 br_ifaces_ap_instances_[ifname] = ap_instances;
1007 break;
1008 }
1009 }
1010 break;
1011 }
1012 }
1013 iface->removeInstance(ifInstanceName);
1014 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
1015
1016 return ndk::ScopedAStatus::ok();
1017}
1018
1019std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> WifiChip::createNanIfaceInternal() {
1020 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::NAN_IFACE)) {
1021 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1022 }
1023 bool is_dedicated_iface = true;
1024 std::string ifname = getPredefinedNanIfaceName();
1025 if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) {
1026 // Use the first shared STA iface (wlan0) if a dedicated aware iface is
1027 // not defined.
1028 ifname = getFirstActiveWlanIfaceName();
1029 is_dedicated_iface = false;
1030 }
1031 std::shared_ptr<WifiNanIface> iface =
1032 WifiNanIface::create(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
1033 nan_ifaces_.push_back(iface);
1034 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1035 if (!callback->onIfaceAdded(IfaceType::NAN_IFACE, ifname).isOk()) {
1036 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1037 }
1038 }
1039 return {iface, ndk::ScopedAStatus::ok()};
1040}
1041
1042std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getNanIfaceNamesInternal() {
1043 if (nan_ifaces_.empty()) {
1044 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
1045 }
1046 return {getNames(nan_ifaces_), ndk::ScopedAStatus::ok()};
1047}
1048
1049std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> WifiChip::getNanIfaceInternal(
1050 const std::string& ifname) {
1051 const auto iface = findUsingName(nan_ifaces_, ifname);
1052 if (!iface.get()) {
1053 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1054 }
1055 return {iface, ndk::ScopedAStatus::ok()};
1056}
1057
1058ndk::ScopedAStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
1059 const auto iface = findUsingName(nan_ifaces_, ifname);
1060 if (!iface.get()) {
1061 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1062 }
1063 invalidateAndClear(nan_ifaces_, iface);
1064 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1065 if (!callback->onIfaceRemoved(IfaceType::NAN_IFACE, ifname).isOk()) {
1066 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1067 }
1068 }
1069 return ndk::ScopedAStatus::ok();
1070}
1071
1072std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> WifiChip::createP2pIfaceInternal() {
1073 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::P2P)) {
1074 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1075 }
1076 std::string ifname = getPredefinedP2pIfaceName();
1077 std::shared_ptr<WifiP2pIface> iface =
1078 ndk::SharedRefBase::make<WifiP2pIface>(ifname, legacy_hal_);
1079 p2p_ifaces_.push_back(iface);
1080 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1081 if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
1082 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1083 }
1084 }
1085 return {iface, ndk::ScopedAStatus::ok()};
1086}
1087
1088std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getP2pIfaceNamesInternal() {
1089 if (p2p_ifaces_.empty()) {
1090 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
1091 }
1092 return {getNames(p2p_ifaces_), ndk::ScopedAStatus::ok()};
1093}
1094
1095std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> WifiChip::getP2pIfaceInternal(
1096 const std::string& ifname) {
1097 const auto iface = findUsingName(p2p_ifaces_, ifname);
1098 if (!iface.get()) {
1099 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1100 }
1101 return {iface, ndk::ScopedAStatus::ok()};
1102}
1103
1104ndk::ScopedAStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
1105 const auto iface = findUsingName(p2p_ifaces_, ifname);
1106 if (!iface.get()) {
1107 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1108 }
1109 invalidateAndClear(p2p_ifaces_, iface);
1110 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1111 if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
1112 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
1113 }
1114 }
1115 return ndk::ScopedAStatus::ok();
1116}
1117
1118std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> WifiChip::createStaIfaceInternal() {
1119 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
1120 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1121 }
1122 std::string ifname = allocateStaIfaceName();
1123 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->createVirtualInterface(
1124 ifname, aidl_struct_util::convertAidlIfaceTypeToLegacy(IfaceType::STA));
1125 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1126 LOG(ERROR) << "Failed to add interface: " << ifname << " "
1127 << legacyErrorToString(legacy_status);
1128 return {nullptr, createWifiStatusFromLegacyError(legacy_status)};
1129 }
1130 std::shared_ptr<WifiStaIface> iface =
1131 ndk::SharedRefBase::make<WifiStaIface>(ifname, legacy_hal_, iface_util_);
1132 sta_ifaces_.push_back(iface);
1133 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1134 if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
1135 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1136 }
1137 }
1138 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
1139 return {iface, ndk::ScopedAStatus::ok()};
1140}
1141
1142std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getStaIfaceNamesInternal() {
1143 if (sta_ifaces_.empty()) {
1144 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
1145 }
1146 return {getNames(sta_ifaces_), ndk::ScopedAStatus::ok()};
1147}
1148
1149std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> WifiChip::getStaIfaceInternal(
1150 const std::string& ifname) {
1151 const auto iface = findUsingName(sta_ifaces_, ifname);
1152 if (!iface.get()) {
1153 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1154 }
1155 return {iface, ndk::ScopedAStatus::ok()};
1156}
1157
1158ndk::ScopedAStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
1159 const auto iface = findUsingName(sta_ifaces_, ifname);
1160 if (!iface.get()) {
1161 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1162 }
1163 // Invalidate & remove any dependent objects first.
1164 invalidateAndRemoveDependencies(ifname);
1165 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(ifname);
1166 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1167 LOG(ERROR) << "Failed to remove interface: " << ifname << " "
1168 << legacyErrorToString(legacy_status);
1169 }
1170 invalidateAndClear(sta_ifaces_, iface);
1171 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1172 if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
1173 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
1174 }
1175 }
1176 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
1177 return ndk::ScopedAStatus::ok();
1178}
1179
1180std::pair<std::shared_ptr<IWifiRttController>, ndk::ScopedAStatus>
1181WifiChip::createRttControllerInternal(const std::shared_ptr<IWifiStaIface>& bound_iface) {
1182 if (sta_ifaces_.size() == 0 &&
1183 !canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
1184 LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs "
1185 "(and RTT by extension)";
1186 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1187 }
1188 std::shared_ptr<WifiRttController> rtt =
1189 WifiRttController::create(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
1190 rtt_controllers_.emplace_back(rtt);
1191 return {rtt, ndk::ScopedAStatus::ok()};
1192}
1193
1194std::pair<std::vector<WifiDebugRingBufferStatus>, ndk::ScopedAStatus>
1195WifiChip::getDebugRingBuffersStatusInternal() {
1196 legacy_hal::wifi_error legacy_status;
1197 std::vector<legacy_hal::wifi_ring_buffer_status> legacy_ring_buffer_status_vec;
1198 std::tie(legacy_status, legacy_ring_buffer_status_vec) =
1199 legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
1200 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1201 return {std::vector<WifiDebugRingBufferStatus>(),
1202 createWifiStatusFromLegacyError(legacy_status)};
1203 }
1204 std::vector<WifiDebugRingBufferStatus> aidl_ring_buffer_status_vec;
1205 if (!aidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToAidl(
1206 legacy_ring_buffer_status_vec, &aidl_ring_buffer_status_vec)) {
1207 return {std::vector<WifiDebugRingBufferStatus>(),
1208 createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
1209 }
1210 return {aidl_ring_buffer_status_vec, ndk::ScopedAStatus::ok()};
1211}
1212
1213ndk::ScopedAStatus WifiChip::startLoggingToDebugRingBufferInternal(
1214 const std::string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
1215 uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
1216 ndk::ScopedAStatus status = registerDebugRingBufferCallback();
1217 if (!status.isOk()) {
1218 return status;
1219 }
1220 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging(
1221 getFirstActiveWlanIfaceName(), ring_name,
1222 static_cast<std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(verbose_level),
1223 max_interval_in_sec, min_data_size_in_bytes);
1224 ringbuffer_map_.insert(
1225 std::pair<std::string, Ringbuffer>(ring_name, Ringbuffer(kMaxBufferSizeBytes)));
1226 // if verbose logging enabled, turn up HAL daemon logging as well.
1227 if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) {
1228 ::android::base::SetMinimumLogSeverity(::android::base::DEBUG);
1229 } else {
1230 ::android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
1231 }
1232 return createWifiStatusFromLegacyError(legacy_status);
1233}
1234
1235ndk::ScopedAStatus WifiChip::forceDumpToDebugRingBufferInternal(const std::string& ring_name) {
1236 ndk::ScopedAStatus status = registerDebugRingBufferCallback();
1237 if (!status.isOk()) {
1238 return status;
1239 }
1240 legacy_hal::wifi_error legacy_status =
1241 legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), ring_name);
1242
1243 return createWifiStatusFromLegacyError(legacy_status);
1244}
1245
1246ndk::ScopedAStatus WifiChip::flushRingBufferToFileInternal() {
1247 if (!writeRingbufferFilesInternal()) {
1248 LOG(ERROR) << "Error writing files to flash";
1249 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
1250 }
1251 return ndk::ScopedAStatus::ok();
1252}
1253
1254ndk::ScopedAStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
1255 legacy_hal::wifi_error legacy_status =
1256 legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName());
1257 if (legacy_status == legacy_hal::WIFI_SUCCESS) {
1258 debug_ring_buffer_cb_registered_ = false;
1259 }
1260 return createWifiStatusFromLegacyError(legacy_status);
1261}
1262
1263std::pair<WifiDebugHostWakeReasonStats, ndk::ScopedAStatus>
1264WifiChip::getDebugHostWakeReasonStatsInternal() {
1265 legacy_hal::wifi_error legacy_status;
1266 legacy_hal::WakeReasonStats legacy_stats;
1267 std::tie(legacy_status, legacy_stats) =
1268 legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
1269 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1270 return {WifiDebugHostWakeReasonStats{}, createWifiStatusFromLegacyError(legacy_status)};
1271 }
1272 WifiDebugHostWakeReasonStats aidl_stats;
1273 if (!aidl_struct_util::convertLegacyWakeReasonStatsToAidl(legacy_stats, &aidl_stats)) {
1274 return {WifiDebugHostWakeReasonStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
1275 }
1276 return {aidl_stats, ndk::ScopedAStatus::ok()};
1277}
1278
1279ndk::ScopedAStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
1280 legacy_hal::wifi_error legacy_status;
1281 if (enable) {
1282 std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
1283 const auto& on_alert_callback = [weak_ptr_this](int32_t error_code,
1284 std::vector<uint8_t> debug_data) {
1285 const auto shared_ptr_this = weak_ptr_this.lock();
1286 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1287 LOG(ERROR) << "Callback invoked on an invalid object";
1288 return;
1289 }
1290 for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
1291 if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) {
1292 LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
1293 }
1294 }
1295 };
1296 legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
1297 getFirstActiveWlanIfaceName(), on_alert_callback);
1298 } else {
1299 legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
1300 getFirstActiveWlanIfaceName());
1301 }
1302 return createWifiStatusFromLegacyError(legacy_status);
1303}
1304
1305ndk::ScopedAStatus WifiChip::selectTxPowerScenarioInternal(IWifiChip::TxPowerScenario scenario) {
1306 auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
1307 getFirstActiveWlanIfaceName(),
1308 aidl_struct_util::convertAidlTxPowerScenarioToLegacy(scenario));
1309 return createWifiStatusFromLegacyError(legacy_status);
1310}
1311
1312ndk::ScopedAStatus WifiChip::resetTxPowerScenarioInternal() {
1313 auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
1314 return createWifiStatusFromLegacyError(legacy_status);
1315}
1316
1317ndk::ScopedAStatus WifiChip::setLatencyModeInternal(IWifiChip::LatencyMode mode) {
1318 auto legacy_status = legacy_hal_.lock()->setLatencyMode(
1319 getFirstActiveWlanIfaceName(), aidl_struct_util::convertAidlLatencyModeToLegacy(mode));
1320 return createWifiStatusFromLegacyError(legacy_status);
1321}
1322
1323ndk::ScopedAStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) {
1324 auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
1325 return createWifiStatusFromLegacyError(legacy_status);
1326}
1327
1328ndk::ScopedAStatus WifiChip::setMultiStaUseCaseInternal(IWifiChip::MultiStaUseCase use_case) {
1329 auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase(
1330 aidl_struct_util::convertAidlMultiStaUseCaseToLegacy(use_case));
1331 return createWifiStatusFromLegacyError(legacy_status);
1332}
1333
1334ndk::ScopedAStatus WifiChip::setCoexUnsafeChannelsInternal(
1335 std::vector<IWifiChip::CoexUnsafeChannel> unsafe_channels, CoexRestriction restrictions) {
1336 std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels;
1337 if (!aidl_struct_util::convertAidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels,
1338 &legacy_unsafe_channels)) {
1339 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1340 }
1341 uint32_t aidl_restrictions = static_cast<uint32_t>(restrictions);
1342 uint32_t legacy_restrictions = 0;
1343 if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::WIFI_DIRECT)) {
1344 legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT;
1345 }
1346 if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::SOFTAP)) {
1347 legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP;
1348 }
1349 if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::WIFI_AWARE)) {
1350 legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE;
1351 }
1352 auto legacy_status =
1353 legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions);
1354 return createWifiStatusFromLegacyError(legacy_status);
1355}
1356
1357ndk::ScopedAStatus WifiChip::setCountryCodeInternal(const std::array<uint8_t, 2>& code) {
1358 auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
1359 return createWifiStatusFromLegacyError(legacy_status);
1360}
1361
1362std::pair<std::vector<WifiUsableChannel>, ndk::ScopedAStatus> WifiChip::getUsableChannelsInternal(
1363 WifiBand band, WifiIfaceMode ifaceModeMask, UsableChannelFilter filterMask) {
1364 legacy_hal::wifi_error legacy_status;
1365 std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels;
1366 std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels(
1367 aidl_struct_util::convertAidlWifiBandToLegacyMacBand(band),
1368 aidl_struct_util::convertAidlWifiIfaceModeToLegacy(
1369 static_cast<uint32_t>(ifaceModeMask)),
1370 aidl_struct_util::convertAidlUsableChannelFilterToLegacy(
1371 static_cast<uint32_t>(filterMask)));
1372
1373 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1374 return {std::vector<WifiUsableChannel>(), createWifiStatusFromLegacyError(legacy_status)};
1375 }
1376 std::vector<WifiUsableChannel> aidl_usable_channels;
1377 if (!aidl_struct_util::convertLegacyWifiUsableChannelsToAidl(legacy_usable_channels,
1378 &aidl_usable_channels)) {
1379 return {std::vector<WifiUsableChannel>(), createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
1380 }
1381 return {aidl_usable_channels, ndk::ScopedAStatus::ok()};
1382}
1383
1384std::pair<WifiRadioCombinationMatrix, ndk::ScopedAStatus>
1385WifiChip::getSupportedRadioCombinationsMatrixInternal() {
1386 legacy_hal::wifi_error legacy_status;
1387 legacy_hal::wifi_radio_combination_matrix* legacy_matrix;
1388
1389 std::tie(legacy_status, legacy_matrix) =
1390 legacy_hal_.lock()->getSupportedRadioCombinationsMatrix();
1391 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1392 LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: "
1393 << legacyErrorToString(legacy_status);
1394 return {WifiRadioCombinationMatrix{}, createWifiStatusFromLegacyError(legacy_status)};
1395 }
1396
1397 WifiRadioCombinationMatrix aidl_matrix;
1398 if (!aidl_struct_util::convertLegacyRadioCombinationsMatrixToAidl(legacy_matrix,
1399 &aidl_matrix)) {
1400 LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToAidl() ";
1401 return {WifiRadioCombinationMatrix(), createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1402 }
1403 return {aidl_matrix, ndk::ScopedAStatus::ok()};
1404}
1405
1406ndk::ScopedAStatus WifiChip::triggerSubsystemRestartInternal() {
1407 auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
1408 return createWifiStatusFromLegacyError(legacy_status);
1409}
1410
1411ndk::ScopedAStatus WifiChip::handleChipConfiguration(
1412 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, int32_t mode_id) {
1413 // If the chip is already configured in a different mode, stop
1414 // the legacy HAL and then start it after firmware mode change.
1415 if (isValidModeId(current_mode_id_)) {
1416 LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id;
1417 invalidateAndRemoveAllIfaces();
1418 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {});
1419 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1420 LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status);
1421 return createWifiStatusFromLegacyError(legacy_status);
1422 }
1423 }
1424 // Firmware mode change not needed for V2 devices.
1425 bool success = true;
1426 if (mode_id == feature_flags::chip_mode_ids::kV1Sta) {
1427 success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
1428 } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) {
1429 success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
1430 }
1431 if (!success) {
1432 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
1433 }
1434 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
1435 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1436 LOG(ERROR) << "Failed to start legacy HAL: " << legacyErrorToString(legacy_status);
1437 return createWifiStatusFromLegacyError(legacy_status);
1438 }
1439 // Every time the HAL is restarted, we need to register the
1440 // radio mode change callback.
1441 ndk::ScopedAStatus status = registerRadioModeChangeCallback();
1442 if (!status.isOk()) {
1443 // This is probably not a critical failure?
1444 LOG(ERROR) << "Failed to register radio mode change callback";
1445 }
1446 // Extract and save the version information into property.
1447 std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> version_info;
1448 version_info = WifiChip::requestChipDebugInfoInternal();
1449 if (version_info.second.isOk()) {
1450 property_set("vendor.wlan.firmware.version",
1451 version_info.first.firmwareDescription.c_str());
1452 property_set("vendor.wlan.driver.version", version_info.first.driverDescription.c_str());
1453 }
1454
1455 return ndk::ScopedAStatus::ok();
1456}
1457
1458ndk::ScopedAStatus WifiChip::registerDebugRingBufferCallback() {
1459 if (debug_ring_buffer_cb_registered_) {
1460 return ndk::ScopedAStatus::ok();
1461 }
1462
1463 std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
1464 const auto& on_ring_buffer_data_callback =
1465 [weak_ptr_this](const std::string& name, const std::vector<uint8_t>& data,
1466 const legacy_hal::wifi_ring_buffer_status& status) {
1467 const auto shared_ptr_this = weak_ptr_this.lock();
1468 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1469 LOG(ERROR) << "Callback invoked on an invalid object";
1470 return;
1471 }
1472 WifiDebugRingBufferStatus aidl_status;
1473 Ringbuffer::AppendStatus appendstatus;
1474 if (!aidl_struct_util::convertLegacyDebugRingBufferStatusToAidl(status,
1475 &aidl_status)) {
1476 LOG(ERROR) << "Error converting ring buffer status";
1477 return;
1478 }
1479 {
1480 std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
1481 const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
1482 if (target != shared_ptr_this->ringbuffer_map_.end()) {
1483 Ringbuffer& cur_buffer = target->second;
1484 appendstatus = cur_buffer.append(data);
1485 } else {
1486 LOG(ERROR) << "Ringname " << name << " not found";
1487 return;
1488 }
1489 // unique_lock unlocked here
1490 }
1491 if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) {
1492 LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer";
1493 shared_ptr_this->writeRingbufferFilesInternal();
1494 return;
1495 }
1496 };
1497 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler(
1498 getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
1499
1500 if (legacy_status == legacy_hal::WIFI_SUCCESS) {
1501 debug_ring_buffer_cb_registered_ = true;
1502 }
1503 return createWifiStatusFromLegacyError(legacy_status);
1504}
1505
1506ndk::ScopedAStatus WifiChip::registerRadioModeChangeCallback() {
1507 std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
1508 const auto& on_radio_mode_change_callback =
1509 [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
1510 const auto shared_ptr_this = weak_ptr_this.lock();
1511 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1512 LOG(ERROR) << "Callback invoked on an invalid object";
1513 return;
1514 }
1515 std::vector<IWifiChipEventCallback::RadioModeInfo> aidl_radio_mode_infos;
1516 if (!aidl_struct_util::convertLegacyWifiMacInfosToAidl(mac_infos,
1517 &aidl_radio_mode_infos)) {
1518 LOG(ERROR) << "Error converting wifi mac info";
1519 return;
1520 }
1521 for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
1522 if (!callback->onRadioModeChange(aidl_radio_mode_infos).isOk()) {
1523 LOG(ERROR) << "Failed to invoke onRadioModeChange callback";
1524 }
1525 }
1526 };
1527 legacy_hal::wifi_error legacy_status =
1528 legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
1529 getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
1530 return createWifiStatusFromLegacyError(legacy_status);
1531}
1532
1533std::vector<IWifiChip::ChipConcurrencyCombination>
1534WifiChip::getCurrentModeConcurrencyCombinations() {
1535 if (!isValidModeId(current_mode_id_)) {
1536 LOG(ERROR) << "Chip not configured in a mode yet";
1537 return std::vector<IWifiChip::ChipConcurrencyCombination>();
1538 }
1539 for (const auto& mode : modes_) {
1540 if (mode.id == current_mode_id_) {
1541 return mode.availableCombinations;
1542 }
1543 }
1544 CHECK(0) << "Expected to find concurrency combinations for current mode!";
1545 return std::vector<IWifiChip::ChipConcurrencyCombination>();
1546}
1547
1548// Returns a map indexed by IfaceConcurrencyType with the number of ifaces currently
1549// created of the corresponding concurrency type.
1550std::map<IfaceConcurrencyType, size_t> WifiChip::getCurrentConcurrencyCombination() {
1551 std::map<IfaceConcurrencyType, size_t> iface_counts;
1552 uint32_t num_ap = 0;
1553 uint32_t num_ap_bridged = 0;
1554 for (const auto& ap_iface : ap_ifaces_) {
1555 std::string ap_iface_name = ap_iface->getName();
1556 if (br_ifaces_ap_instances_.count(ap_iface_name) > 0 &&
1557 br_ifaces_ap_instances_[ap_iface_name].size() > 1) {
1558 num_ap_bridged++;
1559 } else {
1560 num_ap++;
1561 }
1562 }
1563 iface_counts[IfaceConcurrencyType::AP] = num_ap;
1564 iface_counts[IfaceConcurrencyType::AP_BRIDGED] = num_ap_bridged;
1565 iface_counts[IfaceConcurrencyType::NAN_IFACE] = nan_ifaces_.size();
1566 iface_counts[IfaceConcurrencyType::P2P] = p2p_ifaces_.size();
1567 iface_counts[IfaceConcurrencyType::STA] = sta_ifaces_.size();
1568 return iface_counts;
1569}
1570
1571// This expands the provided concurrency combinations to a more parseable
1572// form. Returns a vector of available combinations possible with the number
1573// of each concurrency type in the combination.
1574// This method is a port of HalDeviceManager.expandConcurrencyCombos() from framework.
1575std::vector<std::map<IfaceConcurrencyType, size_t>> WifiChip::expandConcurrencyCombinations(
1576 const IWifiChip::ChipConcurrencyCombination& combination) {
1577 int32_t num_expanded_combos = 1;
1578 for (const auto& limit : combination.limits) {
1579 for (int32_t i = 0; i < limit.maxIfaces; i++) {
1580 num_expanded_combos *= limit.types.size();
1581 }
1582 }
1583
1584 // Allocate the vector of expanded combos and reset all concurrency type counts to 0
1585 // in each combo.
1586 std::vector<std::map<IfaceConcurrencyType, size_t>> expanded_combos;
1587 expanded_combos.resize(num_expanded_combos);
1588 for (auto& expanded_combo : expanded_combos) {
1589 for (const auto type : {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
1590 IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P,
1591 IfaceConcurrencyType::STA}) {
1592 expanded_combo[type] = 0;
1593 }
1594 }
1595 int32_t span = num_expanded_combos;
1596 for (const auto& limit : combination.limits) {
1597 for (int32_t i = 0; i < limit.maxIfaces; i++) {
1598 span /= limit.types.size();
1599 for (int32_t k = 0; k < num_expanded_combos; ++k) {
1600 const auto iface_type = limit.types[(k / span) % limit.types.size()];
1601 expanded_combos[k][iface_type]++;
1602 }
1603 }
1604 }
1605 return expanded_combos;
1606}
1607
1608bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(
1609 const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
1610 IfaceConcurrencyType requested_type) {
1611 const auto current_combo = getCurrentConcurrencyCombination();
1612
1613 // Check if we have space for 1 more iface of |type| in this combo
1614 for (const auto type :
1615 {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
1616 IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
1617 size_t num_ifaces_needed = current_combo.at(type);
1618 if (type == requested_type) {
1619 num_ifaces_needed++;
1620 }
1621 size_t num_ifaces_allowed = expanded_combo.at(type);
1622 if (num_ifaces_needed > num_ifaces_allowed) {
1623 return false;
1624 }
1625 }
1626 return true;
1627}
1628
1629// This method does the following:
1630// a) Enumerate all possible concurrency combos by expanding the current
1631// ChipConcurrencyCombination.
1632// b) Check if the requested concurrency type can be added to the current mode
1633// with the concurrency combination that is already active.
1634bool WifiChip::canCurrentModeSupportConcurrencyTypeWithCurrentTypes(
1635 IfaceConcurrencyType requested_type) {
1636 if (!isValidModeId(current_mode_id_)) {
1637 LOG(ERROR) << "Chip not configured in a mode yet";
1638 return false;
1639 }
1640 const auto combinations = getCurrentModeConcurrencyCombinations();
1641 for (const auto& combination : combinations) {
1642 const auto expanded_combos = expandConcurrencyCombinations(combination);
1643 for (const auto& expanded_combo : expanded_combos) {
1644 if (canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(expanded_combo,
1645 requested_type)) {
1646 return true;
1647 }
1648 }
1649 }
1650 return false;
1651}
1652
1653// Note: This does not consider concurrency types already active. It only checks if the
1654// provided expanded concurrency combination can support the requested combo.
1655bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyCombo(
1656 const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
1657 const std::map<IfaceConcurrencyType, size_t>& req_combo) {
1658 // Check if we have space for 1 more |type| in this combo
1659 for (const auto type :
1660 {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
1661 IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
1662 if (req_combo.count(type) == 0) {
1663 // Concurrency type not in the req_combo.
1664 continue;
1665 }
1666 size_t num_ifaces_needed = req_combo.at(type);
1667 size_t num_ifaces_allowed = expanded_combo.at(type);
1668 if (num_ifaces_needed > num_ifaces_allowed) {
1669 return false;
1670 }
1671 }
1672 return true;
1673}
1674
1675// This method does the following:
1676// a) Enumerate all possible concurrency combos by expanding the current
1677// ChipConcurrencyCombination.
1678// b) Check if the requested concurrency combo can be added to the current mode.
1679// Note: This does not consider concurrency types already active. It only checks if the
1680// current mode can support the requested combo.
1681bool WifiChip::canCurrentModeSupportConcurrencyCombo(
1682 const std::map<IfaceConcurrencyType, size_t>& req_combo) {
1683 if (!isValidModeId(current_mode_id_)) {
1684 LOG(ERROR) << "Chip not configured in a mode yet";
1685 return false;
1686 }
1687 const auto combinations = getCurrentModeConcurrencyCombinations();
1688 for (const auto& combination : combinations) {
1689 const auto expanded_combos = expandConcurrencyCombinations(combination);
1690 for (const auto& expanded_combo : expanded_combos) {
1691 if (canExpandedConcurrencyComboSupportConcurrencyCombo(expanded_combo, req_combo)) {
1692 return true;
1693 }
1694 }
1695 }
1696 return false;
1697}
1698
1699// This method does the following:
1700// a) Enumerate all possible concurrency combos by expanding the current
1701// ChipConcurrencyCombination.
1702// b) Check if the requested concurrency type can be added to the current mode.
1703bool WifiChip::canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type) {
1704 // Check if we can support at least 1 of the requested concurrency type.
1705 std::map<IfaceConcurrencyType, size_t> req_iface_combo;
1706 req_iface_combo[requested_type] = 1;
1707 return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
1708}
1709
1710bool WifiChip::isValidModeId(int32_t mode_id) {
1711 for (const auto& mode : modes_) {
1712 if (mode.id == mode_id) {
1713 return true;
1714 }
1715 }
1716 return false;
1717}
1718
1719bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
1720 // Check if we can support at least 1 STA & 1 AP concurrently.
1721 std::map<IfaceConcurrencyType, size_t> req_iface_combo;
1722 req_iface_combo[IfaceConcurrencyType::STA] = 1;
1723 req_iface_combo[IfaceConcurrencyType::AP] = 1;
1724 return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
1725}
1726
1727bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() {
1728 // Check if we can support at least 2 STA concurrently.
1729 std::map<IfaceConcurrencyType, size_t> req_iface_combo;
1730 req_iface_combo[IfaceConcurrencyType::STA] = 2;
1731 return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
1732}
1733
1734std::string WifiChip::getFirstActiveWlanIfaceName() {
1735 if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
1736 if (ap_ifaces_.size() > 0) {
1737 // If the first active wlan iface is bridged iface.
1738 // Return first instance name.
1739 for (auto const& it : br_ifaces_ap_instances_) {
1740 if (it.first == ap_ifaces_[0]->getName()) {
1741 return it.second[0];
1742 }
1743 }
1744 return ap_ifaces_[0]->getName();
1745 }
1746 // This could happen if the chip call is made before any STA/AP
1747 // iface is created. Default to wlan0 for such cases.
1748 LOG(WARNING) << "No active wlan interfaces in use! Using default";
1749 return getWlanIfaceNameWithType(IfaceType::STA, 0);
1750}
1751
1752// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
1753// not already in use.
1754// Note: This doesn't check the actual presence of these interfaces.
1755std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) {
1756 for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
1757 const auto ifname = getWlanIfaceNameWithType(type, idx);
1758 if (findUsingNameFromBridgedApInstances(ifname)) continue;
1759 if (findUsingName(ap_ifaces_, ifname)) continue;
1760 if (findUsingName(sta_ifaces_, ifname)) continue;
1761 return ifname;
1762 }
1763 // This should never happen. We screwed up somewhere if it did.
1764 CHECK(false) << "All wlan interfaces in use already!";
1765 return {};
1766}
1767
1768uint32_t WifiChip::startIdxOfApIface() {
1769 if (isDualStaConcurrencyAllowedInCurrentMode()) {
1770 // When the HAL support dual STAs, AP should start with idx 2.
1771 return 2;
1772 } else if (isStaApConcurrencyAllowedInCurrentMode()) {
1773 // When the HAL support STA + AP but it doesn't support dual STAs.
1774 // AP should start with idx 1.
1775 return 1;
1776 }
1777 // No concurrency support.
1778 return 0;
1779}
1780
1781// AP iface names start with idx 1 for modes supporting
1782// concurrent STA and not dual AP, else start with idx 0.
1783std::string WifiChip::allocateApIfaceName() {
1784 // Check if we have a dedicated iface for AP.
1785 std::vector<std::string> ifnames = getPredefinedApIfaceNames(true);
1786 for (auto const& ifname : ifnames) {
1787 if (findUsingName(ap_ifaces_, ifname)) continue;
1788 return ifname;
1789 }
1790 return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
1791}
1792
1793std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
1794 // Check if we have a dedicated iface for AP.
1795 std::vector<std::string> instances = getPredefinedApIfaceNames(true);
1796 if (instances.size() == 2) {
1797 return instances;
1798 } else {
1799 int num_ifaces_need_to_allocate = 2 - instances.size();
1800 for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
1801 std::string instance_name =
1802 allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i);
1803 if (!instance_name.empty()) {
1804 instances.push_back(instance_name);
1805 }
1806 }
1807 }
1808 return instances;
1809}
1810
1811// STA iface names start with idx 0.
1812// Primary STA iface will always be 0.
1813std::string WifiChip::allocateStaIfaceName() {
1814 return allocateApOrStaIfaceName(IfaceType::STA, 0);
1815}
1816
1817bool WifiChip::writeRingbufferFilesInternal() {
1818 if (!removeOldFilesInternal()) {
1819 LOG(ERROR) << "Error occurred while deleting old tombstone files";
1820 return false;
1821 }
1822 // write ringbuffers to file
1823 {
1824 std::unique_lock<std::mutex> lk(lock_t);
1825 for (auto& item : ringbuffer_map_) {
1826 Ringbuffer& cur_buffer = item.second;
1827 if (cur_buffer.getData().empty()) {
1828 continue;
1829 }
1830 const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX";
1831 const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
1832 if (dump_fd == -1) {
1833 PLOG(ERROR) << "create file failed";
1834 return false;
1835 }
1836 unique_fd file_auto_closer(dump_fd);
1837 for (const auto& cur_block : cur_buffer.getData()) {
1838 if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) {
1839 PLOG(ERROR) << "Ring buffer: " << item.first
1840 << " is corrupted. Invalid block size: " << cur_block.size();
1841 break;
1842 }
1843 if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) ==
1844 -1) {
1845 PLOG(ERROR) << "Error writing to file";
1846 }
1847 }
1848 cur_buffer.clear();
1849 }
1850 // unique_lock unlocked here
1851 }
1852 return true;
1853}
1854
1855std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
1856 std::string ifname;
1857
1858 // let the legacy hal override the interface name
1859 legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
1860 if (err == legacy_hal::WIFI_SUCCESS) return ifname;
1861
1862 return getWlanIfaceName(idx);
1863}
1864
1865void WifiChip::invalidateAndClearBridgedApAll() {
1866 for (auto const& it : br_ifaces_ap_instances_) {
1867 for (auto const& iface : it.second) {
1868 iface_util_->removeIfaceFromBridge(it.first, iface);
1869 legacy_hal_.lock()->deleteVirtualInterface(iface);
1870 }
1871 iface_util_->deleteBridge(it.first);
1872 }
1873 br_ifaces_ap_instances_.clear();
1874}
1875
1876void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) {
1877 if (br_name.empty()) return;
1878 // delete managed interfaces
1879 for (auto const& it : br_ifaces_ap_instances_) {
1880 if (it.first == br_name) {
1881 for (auto const& iface : it.second) {
1882 iface_util_->removeIfaceFromBridge(br_name, iface);
1883 legacy_hal_.lock()->deleteVirtualInterface(iface);
1884 }
1885 iface_util_->deleteBridge(br_name);
1886 br_ifaces_ap_instances_.erase(br_name);
1887 break;
1888 }
1889 }
1890 return;
1891}
1892
1893bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
1894 for (auto const& it : br_ifaces_ap_instances_) {
1895 if (it.first == name) {
1896 return true;
1897 }
1898 for (auto const& iface : it.second) {
1899 if (iface == name) {
1900 return true;
1901 }
1902 }
1903 }
1904 return false;
1905}
1906
1907} // namespace wifi
1908} // namespace hardware
1909} // namespace android
1910} // namespace aidl