blob: 406169912f3ae21686570bc2ca812db4c3345372 [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
Mahesh KKVc84d3772022-12-02 16:53:28 -0800683ndk::ScopedAStatus WifiChip::getWifiChipCapabilities(WifiChipCapabilities* _aidl_return) {
684 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
685 &WifiChip::getWifiChipCapabilitiesInternal, _aidl_return);
686}
687
Gabriel Birenf3262f92022-07-15 23:25:39 +0000688void WifiChip::invalidateAndRemoveAllIfaces() {
689 invalidateAndClearBridgedApAll();
690 invalidateAndClearAll(ap_ifaces_);
691 invalidateAndClearAll(nan_ifaces_);
692 invalidateAndClearAll(p2p_ifaces_);
693 invalidateAndClearAll(sta_ifaces_);
694 // Since all the ifaces are invalid now, all RTT controller objects
695 // using those ifaces also need to be invalidated.
696 for (const auto& rtt : rtt_controllers_) {
697 rtt->invalidate();
698 }
699 rtt_controllers_.clear();
700}
701
702void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) {
703 for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) {
704 auto nan_iface = *it;
705 if (nan_iface->getName() == removed_iface_name) {
706 nan_iface->invalidate();
707 for (const auto& callback : event_cb_handler_.getCallbacks()) {
708 if (!callback->onIfaceRemoved(IfaceType::NAN_IFACE, removed_iface_name).isOk()) {
709 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
710 }
711 }
712 it = nan_ifaces_.erase(it);
713 } else {
714 ++it;
715 }
716 }
717
718 for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) {
719 auto rtt = *it;
720 if (rtt->getIfaceName() == removed_iface_name) {
721 rtt->invalidate();
722 it = rtt_controllers_.erase(it);
723 } else {
724 ++it;
725 }
726 }
727}
728
729std::pair<int32_t, ndk::ScopedAStatus> WifiChip::getIdInternal() {
730 return {chip_id_, ndk::ScopedAStatus::ok()};
731}
732
733ndk::ScopedAStatus WifiChip::registerEventCallbackInternal(
734 const std::shared_ptr<IWifiChipEventCallback>& event_callback) {
735 if (!event_cb_handler_.addCallback(event_callback)) {
736 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
737 }
738 return ndk::ScopedAStatus::ok();
739}
740
741std::pair<IWifiChip::ChipCapabilityMask, ndk::ScopedAStatus> WifiChip::getCapabilitiesInternal() {
742 legacy_hal::wifi_error legacy_status;
743 uint64_t legacy_feature_set;
744 uint32_t legacy_logger_feature_set;
745 const auto ifname = getFirstActiveWlanIfaceName();
746 std::tie(legacy_status, legacy_feature_set) =
747 legacy_hal_.lock()->getSupportedFeatureSet(ifname);
748 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
749 return {IWifiChip::ChipCapabilityMask{}, createWifiStatusFromLegacyError(legacy_status)};
750 }
751 std::tie(legacy_status, legacy_logger_feature_set) =
752 legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
753 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
754 // some devices don't support querying logger feature set
755 legacy_logger_feature_set = 0;
756 }
757 uint32_t aidl_caps;
758 if (!aidl_struct_util::convertLegacyFeaturesToAidlChipCapabilities(
759 legacy_feature_set, legacy_logger_feature_set, &aidl_caps)) {
760 return {IWifiChip::ChipCapabilityMask{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
761 }
762 return {static_cast<IWifiChip::ChipCapabilityMask>(aidl_caps), ndk::ScopedAStatus::ok()};
763}
764
765std::pair<std::vector<IWifiChip::ChipMode>, ndk::ScopedAStatus>
766WifiChip::getAvailableModesInternal() {
767 return {modes_, ndk::ScopedAStatus::ok()};
768}
769
770ndk::ScopedAStatus WifiChip::configureChipInternal(
771 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, int32_t mode_id) {
772 if (!isValidModeId(mode_id)) {
773 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
774 }
775 if (mode_id == current_mode_id_) {
776 LOG(DEBUG) << "Already in the specified mode " << mode_id;
777 return ndk::ScopedAStatus::ok();
778 }
779 ndk::ScopedAStatus status = handleChipConfiguration(lock, mode_id);
780 if (!status.isOk()) {
781 WifiStatusCode errorCode = static_cast<WifiStatusCode>(status.getServiceSpecificError());
782 for (const auto& callback : event_cb_handler_.getCallbacks()) {
783 if (!callback->onChipReconfigureFailure(errorCode).isOk()) {
784 LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
785 }
786 }
787 return status;
788 }
789 for (const auto& callback : event_cb_handler_.getCallbacks()) {
790 if (!callback->onChipReconfigured(mode_id).isOk()) {
791 LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
792 }
793 }
794 current_mode_id_ = mode_id;
795 LOG(INFO) << "Configured chip in mode " << mode_id;
796 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
797
798 legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_);
799
800 return status;
801}
802
803std::pair<int32_t, ndk::ScopedAStatus> WifiChip::getModeInternal() {
804 if (!isValidModeId(current_mode_id_)) {
805 return {current_mode_id_, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
806 }
807 return {current_mode_id_, ndk::ScopedAStatus::ok()};
808}
809
810std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> WifiChip::requestChipDebugInfoInternal() {
811 IWifiChip::ChipDebugInfo result;
812 legacy_hal::wifi_error legacy_status;
813 std::string driver_desc;
814 const auto ifname = getFirstActiveWlanIfaceName();
815 std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname);
816 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
817 LOG(ERROR) << "Failed to get driver version: " << legacyErrorToString(legacy_status);
818 ndk::ScopedAStatus status =
819 createWifiStatusFromLegacyError(legacy_status, "failed to get driver version");
820 return {std::move(result), std::move(status)};
821 }
822 result.driverDescription = driver_desc.c_str();
823
824 std::string firmware_desc;
825 std::tie(legacy_status, firmware_desc) = legacy_hal_.lock()->getFirmwareVersion(ifname);
826 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
827 LOG(ERROR) << "Failed to get firmware version: " << legacyErrorToString(legacy_status);
828 ndk::ScopedAStatus status =
829 createWifiStatusFromLegacyError(legacy_status, "failed to get firmware version");
830 return {std::move(result), std::move(status)};
831 }
832 result.firmwareDescription = firmware_desc.c_str();
833
834 return {std::move(result), ndk::ScopedAStatus::ok()};
835}
836
837std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> WifiChip::requestDriverDebugDumpInternal() {
838 legacy_hal::wifi_error legacy_status;
839 std::vector<uint8_t> driver_dump;
840 std::tie(legacy_status, driver_dump) =
841 legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName());
842 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
843 LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status);
844 return {std::vector<uint8_t>(), createWifiStatusFromLegacyError(legacy_status)};
845 }
846 return {driver_dump, ndk::ScopedAStatus::ok()};
847}
848
849std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> WifiChip::requestFirmwareDebugDumpInternal() {
850 legacy_hal::wifi_error legacy_status;
851 std::vector<uint8_t> firmware_dump;
852 std::tie(legacy_status, firmware_dump) =
853 legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName());
854 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
855 LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status);
856 return {std::vector<uint8_t>(), createWifiStatusFromLegacyError(legacy_status)};
857 }
858 return {firmware_dump, ndk::ScopedAStatus::ok()};
859}
860
861ndk::ScopedAStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
862 legacy_hal::wifi_error legacy_status;
863 legacy_status = legacy_hal_.lock()->createVirtualInterface(
864 apVirtIf, aidl_struct_util::convertAidlIfaceTypeToLegacy(IfaceType::AP));
865 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
866 LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
867 << legacyErrorToString(legacy_status);
868 return createWifiStatusFromLegacyError(legacy_status);
869 }
870 return ndk::ScopedAStatus::ok();
871}
872
873std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
874 std::vector<std::string> ap_instances;
875 for (auto const& it : br_ifaces_ap_instances_) {
876 if (it.first == ifname) {
877 ap_instances = it.second;
878 }
879 }
880 std::shared_ptr<WifiApIface> iface =
881 ndk::SharedRefBase::make<WifiApIface>(ifname, ap_instances, legacy_hal_, iface_util_);
882 ap_ifaces_.push_back(iface);
883 for (const auto& callback : event_cb_handler_.getCallbacks()) {
884 if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
885 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
886 }
887 }
888 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
889 return iface;
890}
891
892std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createApIfaceInternal() {
893 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP)) {
894 return {std::shared_ptr<WifiApIface>(),
895 createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
896 }
897 std::string ifname = allocateApIfaceName();
898 ndk::ScopedAStatus status = createVirtualApInterface(ifname);
899 if (!status.isOk()) {
900 return {std::shared_ptr<WifiApIface>(), std::move(status)};
901 }
902 std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname);
903 return {iface, ndk::ScopedAStatus::ok()};
904}
905
906std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
907WifiChip::createBridgedApIfaceInternal() {
908 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
909 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
910 }
911 std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
912 if (ap_instances.size() < 2) {
913 LOG(ERROR) << "Fail to allocate two instances";
914 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
915 }
916 std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
917 for (int i = 0; i < 2; i++) {
918 ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
919 if (!status.isOk()) {
920 if (i != 0) { // The failure happened when creating second virtual
921 // iface.
922 legacy_hal_.lock()->deleteVirtualInterface(
923 ap_instances.front()); // Remove the first virtual iface.
924 }
925 return {nullptr, std::move(status)};
926 }
927 }
928 br_ifaces_ap_instances_[br_ifname] = ap_instances;
929 if (!iface_util_->createBridge(br_ifname)) {
930 LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
931 invalidateAndClearBridgedAp(br_ifname);
932 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
933 }
934 for (auto const& instance : ap_instances) {
935 // Bind ap instance interface to AP bridge
936 if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
937 LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
938 invalidateAndClearBridgedAp(br_ifname);
939 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
940 }
941 }
942 std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname);
943 return {iface, ndk::ScopedAStatus::ok()};
944}
945
946std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getApIfaceNamesInternal() {
947 if (ap_ifaces_.empty()) {
948 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
949 }
950 return {getNames(ap_ifaces_), ndk::ScopedAStatus::ok()};
951}
952
953std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::getApIfaceInternal(
954 const std::string& ifname) {
955 const auto iface = findUsingName(ap_ifaces_, ifname);
956 if (!iface.get()) {
957 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
958 }
959 return {iface, ndk::ScopedAStatus::ok()};
960}
961
962ndk::ScopedAStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
963 const auto iface = findUsingName(ap_ifaces_, ifname);
964 if (!iface.get()) {
965 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
966 }
967 // Invalidate & remove any dependent objects first.
968 // Note: This is probably not required because we never create
969 // nan/rtt objects over AP iface. But, there is no harm to do it
970 // here and not make that assumption all over the place.
971 invalidateAndRemoveDependencies(ifname);
972 // Clear the bridge interface and the iface instance.
973 invalidateAndClearBridgedAp(ifname);
974 invalidateAndClear(ap_ifaces_, iface);
975 for (const auto& callback : event_cb_handler_.getCallbacks()) {
976 if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
977 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
978 }
979 }
980 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
981 return ndk::ScopedAStatus::ok();
982}
983
984ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
985 const std::string& ifname, const std::string& ifInstanceName) {
986 const auto iface = findUsingName(ap_ifaces_, ifname);
987 if (!iface.get() || ifInstanceName.empty()) {
988 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
989 }
990 // Requires to remove one of the instance in bridge mode
991 for (auto const& it : br_ifaces_ap_instances_) {
992 if (it.first == ifname) {
993 std::vector<std::string> ap_instances = it.second;
994 for (auto const& iface : ap_instances) {
995 if (iface == ifInstanceName) {
996 if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
997 LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
998 << ifname;
999 return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
1000 }
1001 legacy_hal::wifi_error legacy_status =
1002 legacy_hal_.lock()->deleteVirtualInterface(iface);
1003 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1004 LOG(ERROR) << "Failed to del interface: " << iface << " "
1005 << legacyErrorToString(legacy_status);
1006 return createWifiStatusFromLegacyError(legacy_status);
1007 }
1008 ap_instances.erase(
1009 std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
1010 ap_instances.end());
1011 br_ifaces_ap_instances_[ifname] = ap_instances;
1012 break;
1013 }
1014 }
1015 break;
1016 }
1017 }
1018 iface->removeInstance(ifInstanceName);
1019 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
1020
1021 return ndk::ScopedAStatus::ok();
1022}
1023
1024std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> WifiChip::createNanIfaceInternal() {
1025 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::NAN_IFACE)) {
1026 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1027 }
1028 bool is_dedicated_iface = true;
1029 std::string ifname = getPredefinedNanIfaceName();
1030 if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) {
1031 // Use the first shared STA iface (wlan0) if a dedicated aware iface is
1032 // not defined.
1033 ifname = getFirstActiveWlanIfaceName();
1034 is_dedicated_iface = false;
1035 }
1036 std::shared_ptr<WifiNanIface> iface =
1037 WifiNanIface::create(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
1038 nan_ifaces_.push_back(iface);
1039 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1040 if (!callback->onIfaceAdded(IfaceType::NAN_IFACE, ifname).isOk()) {
1041 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1042 }
1043 }
1044 return {iface, ndk::ScopedAStatus::ok()};
1045}
1046
1047std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getNanIfaceNamesInternal() {
1048 if (nan_ifaces_.empty()) {
1049 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
1050 }
1051 return {getNames(nan_ifaces_), ndk::ScopedAStatus::ok()};
1052}
1053
1054std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> WifiChip::getNanIfaceInternal(
1055 const std::string& ifname) {
1056 const auto iface = findUsingName(nan_ifaces_, ifname);
1057 if (!iface.get()) {
1058 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1059 }
1060 return {iface, ndk::ScopedAStatus::ok()};
1061}
1062
1063ndk::ScopedAStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
1064 const auto iface = findUsingName(nan_ifaces_, ifname);
1065 if (!iface.get()) {
1066 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1067 }
1068 invalidateAndClear(nan_ifaces_, iface);
1069 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1070 if (!callback->onIfaceRemoved(IfaceType::NAN_IFACE, ifname).isOk()) {
1071 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1072 }
1073 }
1074 return ndk::ScopedAStatus::ok();
1075}
1076
1077std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> WifiChip::createP2pIfaceInternal() {
1078 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::P2P)) {
1079 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1080 }
1081 std::string ifname = getPredefinedP2pIfaceName();
1082 std::shared_ptr<WifiP2pIface> iface =
1083 ndk::SharedRefBase::make<WifiP2pIface>(ifname, legacy_hal_);
1084 p2p_ifaces_.push_back(iface);
1085 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1086 if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
1087 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1088 }
1089 }
1090 return {iface, ndk::ScopedAStatus::ok()};
1091}
1092
1093std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getP2pIfaceNamesInternal() {
1094 if (p2p_ifaces_.empty()) {
1095 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
1096 }
1097 return {getNames(p2p_ifaces_), ndk::ScopedAStatus::ok()};
1098}
1099
1100std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> WifiChip::getP2pIfaceInternal(
1101 const std::string& ifname) {
1102 const auto iface = findUsingName(p2p_ifaces_, ifname);
1103 if (!iface.get()) {
1104 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1105 }
1106 return {iface, ndk::ScopedAStatus::ok()};
1107}
1108
1109ndk::ScopedAStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
1110 const auto iface = findUsingName(p2p_ifaces_, ifname);
1111 if (!iface.get()) {
1112 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1113 }
1114 invalidateAndClear(p2p_ifaces_, iface);
1115 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1116 if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
1117 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
1118 }
1119 }
1120 return ndk::ScopedAStatus::ok();
1121}
1122
1123std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> WifiChip::createStaIfaceInternal() {
1124 if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
1125 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1126 }
1127 std::string ifname = allocateStaIfaceName();
1128 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->createVirtualInterface(
1129 ifname, aidl_struct_util::convertAidlIfaceTypeToLegacy(IfaceType::STA));
1130 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1131 LOG(ERROR) << "Failed to add interface: " << ifname << " "
1132 << legacyErrorToString(legacy_status);
1133 return {nullptr, createWifiStatusFromLegacyError(legacy_status)};
1134 }
1135 std::shared_ptr<WifiStaIface> iface =
1136 ndk::SharedRefBase::make<WifiStaIface>(ifname, legacy_hal_, iface_util_);
1137 sta_ifaces_.push_back(iface);
1138 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1139 if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
1140 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
1141 }
1142 }
1143 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
1144 return {iface, ndk::ScopedAStatus::ok()};
1145}
1146
1147std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getStaIfaceNamesInternal() {
1148 if (sta_ifaces_.empty()) {
1149 return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
1150 }
1151 return {getNames(sta_ifaces_), ndk::ScopedAStatus::ok()};
1152}
1153
1154std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> WifiChip::getStaIfaceInternal(
1155 const std::string& ifname) {
1156 const auto iface = findUsingName(sta_ifaces_, ifname);
1157 if (!iface.get()) {
1158 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1159 }
1160 return {iface, ndk::ScopedAStatus::ok()};
1161}
1162
1163ndk::ScopedAStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
1164 const auto iface = findUsingName(sta_ifaces_, ifname);
1165 if (!iface.get()) {
1166 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1167 }
1168 // Invalidate & remove any dependent objects first.
1169 invalidateAndRemoveDependencies(ifname);
1170 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(ifname);
1171 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1172 LOG(ERROR) << "Failed to remove interface: " << ifname << " "
1173 << legacyErrorToString(legacy_status);
1174 }
1175 invalidateAndClear(sta_ifaces_, iface);
1176 for (const auto& callback : event_cb_handler_.getCallbacks()) {
1177 if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
1178 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
1179 }
1180 }
1181 setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
1182 return ndk::ScopedAStatus::ok();
1183}
1184
1185std::pair<std::shared_ptr<IWifiRttController>, ndk::ScopedAStatus>
1186WifiChip::createRttControllerInternal(const std::shared_ptr<IWifiStaIface>& bound_iface) {
1187 if (sta_ifaces_.size() == 0 &&
1188 !canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
1189 LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs "
1190 "(and RTT by extension)";
1191 return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
1192 }
1193 std::shared_ptr<WifiRttController> rtt =
1194 WifiRttController::create(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
1195 rtt_controllers_.emplace_back(rtt);
1196 return {rtt, ndk::ScopedAStatus::ok()};
1197}
1198
1199std::pair<std::vector<WifiDebugRingBufferStatus>, ndk::ScopedAStatus>
1200WifiChip::getDebugRingBuffersStatusInternal() {
1201 legacy_hal::wifi_error legacy_status;
1202 std::vector<legacy_hal::wifi_ring_buffer_status> legacy_ring_buffer_status_vec;
1203 std::tie(legacy_status, legacy_ring_buffer_status_vec) =
1204 legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
1205 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1206 return {std::vector<WifiDebugRingBufferStatus>(),
1207 createWifiStatusFromLegacyError(legacy_status)};
1208 }
1209 std::vector<WifiDebugRingBufferStatus> aidl_ring_buffer_status_vec;
1210 if (!aidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToAidl(
1211 legacy_ring_buffer_status_vec, &aidl_ring_buffer_status_vec)) {
1212 return {std::vector<WifiDebugRingBufferStatus>(),
1213 createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
1214 }
1215 return {aidl_ring_buffer_status_vec, ndk::ScopedAStatus::ok()};
1216}
1217
1218ndk::ScopedAStatus WifiChip::startLoggingToDebugRingBufferInternal(
1219 const std::string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
1220 uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
1221 ndk::ScopedAStatus status = registerDebugRingBufferCallback();
1222 if (!status.isOk()) {
1223 return status;
1224 }
1225 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging(
1226 getFirstActiveWlanIfaceName(), ring_name,
1227 static_cast<std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(verbose_level),
1228 max_interval_in_sec, min_data_size_in_bytes);
1229 ringbuffer_map_.insert(
1230 std::pair<std::string, Ringbuffer>(ring_name, Ringbuffer(kMaxBufferSizeBytes)));
1231 // if verbose logging enabled, turn up HAL daemon logging as well.
1232 if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) {
1233 ::android::base::SetMinimumLogSeverity(::android::base::DEBUG);
1234 } else {
1235 ::android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
1236 }
1237 return createWifiStatusFromLegacyError(legacy_status);
1238}
1239
1240ndk::ScopedAStatus WifiChip::forceDumpToDebugRingBufferInternal(const std::string& ring_name) {
1241 ndk::ScopedAStatus status = registerDebugRingBufferCallback();
1242 if (!status.isOk()) {
1243 return status;
1244 }
1245 legacy_hal::wifi_error legacy_status =
1246 legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), ring_name);
1247
1248 return createWifiStatusFromLegacyError(legacy_status);
1249}
1250
1251ndk::ScopedAStatus WifiChip::flushRingBufferToFileInternal() {
1252 if (!writeRingbufferFilesInternal()) {
1253 LOG(ERROR) << "Error writing files to flash";
1254 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
1255 }
1256 return ndk::ScopedAStatus::ok();
1257}
1258
1259ndk::ScopedAStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
1260 legacy_hal::wifi_error legacy_status =
1261 legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName());
1262 if (legacy_status == legacy_hal::WIFI_SUCCESS) {
1263 debug_ring_buffer_cb_registered_ = false;
1264 }
1265 return createWifiStatusFromLegacyError(legacy_status);
1266}
1267
1268std::pair<WifiDebugHostWakeReasonStats, ndk::ScopedAStatus>
1269WifiChip::getDebugHostWakeReasonStatsInternal() {
1270 legacy_hal::wifi_error legacy_status;
1271 legacy_hal::WakeReasonStats legacy_stats;
1272 std::tie(legacy_status, legacy_stats) =
1273 legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
1274 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1275 return {WifiDebugHostWakeReasonStats{}, createWifiStatusFromLegacyError(legacy_status)};
1276 }
1277 WifiDebugHostWakeReasonStats aidl_stats;
1278 if (!aidl_struct_util::convertLegacyWakeReasonStatsToAidl(legacy_stats, &aidl_stats)) {
1279 return {WifiDebugHostWakeReasonStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
1280 }
1281 return {aidl_stats, ndk::ScopedAStatus::ok()};
1282}
1283
1284ndk::ScopedAStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
1285 legacy_hal::wifi_error legacy_status;
1286 if (enable) {
1287 std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
1288 const auto& on_alert_callback = [weak_ptr_this](int32_t error_code,
1289 std::vector<uint8_t> debug_data) {
1290 const auto shared_ptr_this = weak_ptr_this.lock();
1291 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1292 LOG(ERROR) << "Callback invoked on an invalid object";
1293 return;
1294 }
1295 for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
1296 if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) {
1297 LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
1298 }
1299 }
1300 };
1301 legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
1302 getFirstActiveWlanIfaceName(), on_alert_callback);
1303 } else {
1304 legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
1305 getFirstActiveWlanIfaceName());
1306 }
1307 return createWifiStatusFromLegacyError(legacy_status);
1308}
1309
1310ndk::ScopedAStatus WifiChip::selectTxPowerScenarioInternal(IWifiChip::TxPowerScenario scenario) {
1311 auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
1312 getFirstActiveWlanIfaceName(),
1313 aidl_struct_util::convertAidlTxPowerScenarioToLegacy(scenario));
1314 return createWifiStatusFromLegacyError(legacy_status);
1315}
1316
1317ndk::ScopedAStatus WifiChip::resetTxPowerScenarioInternal() {
1318 auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
1319 return createWifiStatusFromLegacyError(legacy_status);
1320}
1321
1322ndk::ScopedAStatus WifiChip::setLatencyModeInternal(IWifiChip::LatencyMode mode) {
1323 auto legacy_status = legacy_hal_.lock()->setLatencyMode(
1324 getFirstActiveWlanIfaceName(), aidl_struct_util::convertAidlLatencyModeToLegacy(mode));
1325 return createWifiStatusFromLegacyError(legacy_status);
1326}
1327
1328ndk::ScopedAStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) {
1329 auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
1330 return createWifiStatusFromLegacyError(legacy_status);
1331}
1332
1333ndk::ScopedAStatus WifiChip::setMultiStaUseCaseInternal(IWifiChip::MultiStaUseCase use_case) {
1334 auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase(
1335 aidl_struct_util::convertAidlMultiStaUseCaseToLegacy(use_case));
1336 return createWifiStatusFromLegacyError(legacy_status);
1337}
1338
1339ndk::ScopedAStatus WifiChip::setCoexUnsafeChannelsInternal(
1340 std::vector<IWifiChip::CoexUnsafeChannel> unsafe_channels, CoexRestriction restrictions) {
1341 std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels;
1342 if (!aidl_struct_util::convertAidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels,
1343 &legacy_unsafe_channels)) {
1344 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
1345 }
1346 uint32_t aidl_restrictions = static_cast<uint32_t>(restrictions);
1347 uint32_t legacy_restrictions = 0;
1348 if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::WIFI_DIRECT)) {
1349 legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT;
1350 }
1351 if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::SOFTAP)) {
1352 legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP;
1353 }
1354 if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::WIFI_AWARE)) {
1355 legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE;
1356 }
1357 auto legacy_status =
1358 legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions);
1359 return createWifiStatusFromLegacyError(legacy_status);
1360}
1361
1362ndk::ScopedAStatus WifiChip::setCountryCodeInternal(const std::array<uint8_t, 2>& code) {
1363 auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
1364 return createWifiStatusFromLegacyError(legacy_status);
1365}
1366
1367std::pair<std::vector<WifiUsableChannel>, ndk::ScopedAStatus> WifiChip::getUsableChannelsInternal(
1368 WifiBand band, WifiIfaceMode ifaceModeMask, UsableChannelFilter filterMask) {
1369 legacy_hal::wifi_error legacy_status;
1370 std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels;
1371 std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels(
1372 aidl_struct_util::convertAidlWifiBandToLegacyMacBand(band),
1373 aidl_struct_util::convertAidlWifiIfaceModeToLegacy(
1374 static_cast<uint32_t>(ifaceModeMask)),
1375 aidl_struct_util::convertAidlUsableChannelFilterToLegacy(
1376 static_cast<uint32_t>(filterMask)));
1377
1378 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1379 return {std::vector<WifiUsableChannel>(), createWifiStatusFromLegacyError(legacy_status)};
1380 }
1381 std::vector<WifiUsableChannel> aidl_usable_channels;
1382 if (!aidl_struct_util::convertLegacyWifiUsableChannelsToAidl(legacy_usable_channels,
1383 &aidl_usable_channels)) {
1384 return {std::vector<WifiUsableChannel>(), createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
1385 }
1386 return {aidl_usable_channels, ndk::ScopedAStatus::ok()};
1387}
1388
1389std::pair<WifiRadioCombinationMatrix, ndk::ScopedAStatus>
1390WifiChip::getSupportedRadioCombinationsMatrixInternal() {
1391 legacy_hal::wifi_error legacy_status;
1392 legacy_hal::wifi_radio_combination_matrix* legacy_matrix;
1393
1394 std::tie(legacy_status, legacy_matrix) =
1395 legacy_hal_.lock()->getSupportedRadioCombinationsMatrix();
1396 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1397 LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: "
1398 << legacyErrorToString(legacy_status);
1399 return {WifiRadioCombinationMatrix{}, createWifiStatusFromLegacyError(legacy_status)};
1400 }
1401
1402 WifiRadioCombinationMatrix aidl_matrix;
1403 if (!aidl_struct_util::convertLegacyRadioCombinationsMatrixToAidl(legacy_matrix,
1404 &aidl_matrix)) {
1405 LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToAidl() ";
1406 return {WifiRadioCombinationMatrix(), createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1407 }
1408 return {aidl_matrix, ndk::ScopedAStatus::ok()};
1409}
1410
Mahesh KKVc84d3772022-12-02 16:53:28 -08001411std::pair<WifiChipCapabilities, ndk::ScopedAStatus> WifiChip::getWifiChipCapabilitiesInternal() {
1412 legacy_hal::wifi_error legacy_status;
1413 legacy_hal::wifi_chip_capabilities legacy_chip_capabilities;
1414 std::tie(legacy_status, legacy_chip_capabilities) =
1415 legacy_hal_.lock()->getWifiChipCapabilities();
1416 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1417 LOG(ERROR) << "Failed to get chip capabilities from legacy HAL: "
1418 << legacyErrorToString(legacy_status);
1419 return {WifiChipCapabilities(), createWifiStatusFromLegacyError(legacy_status)};
1420 }
1421 WifiChipCapabilities aidl_chip_capabilities;
1422 if (!aidl_struct_util::convertLegacyWifiChipCapabilitiesToAidl(legacy_chip_capabilities,
1423 aidl_chip_capabilities)) {
1424 LOG(ERROR) << "Failed convertLegacyWifiChipCapabilitiesToAidl() ";
1425 return {WifiChipCapabilities(), createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
1426 }
1427
1428 return {aidl_chip_capabilities, ndk::ScopedAStatus::ok()};
1429}
1430
Gabriel Birenf3262f92022-07-15 23:25:39 +00001431ndk::ScopedAStatus WifiChip::triggerSubsystemRestartInternal() {
1432 auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
1433 return createWifiStatusFromLegacyError(legacy_status);
1434}
1435
1436ndk::ScopedAStatus WifiChip::handleChipConfiguration(
1437 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, int32_t mode_id) {
1438 // If the chip is already configured in a different mode, stop
1439 // the legacy HAL and then start it after firmware mode change.
1440 if (isValidModeId(current_mode_id_)) {
1441 LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id;
1442 invalidateAndRemoveAllIfaces();
1443 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {});
1444 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1445 LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status);
1446 return createWifiStatusFromLegacyError(legacy_status);
1447 }
1448 }
1449 // Firmware mode change not needed for V2 devices.
1450 bool success = true;
1451 if (mode_id == feature_flags::chip_mode_ids::kV1Sta) {
1452 success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
1453 } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) {
1454 success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
1455 }
1456 if (!success) {
1457 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
1458 }
1459 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
1460 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1461 LOG(ERROR) << "Failed to start legacy HAL: " << legacyErrorToString(legacy_status);
1462 return createWifiStatusFromLegacyError(legacy_status);
1463 }
1464 // Every time the HAL is restarted, we need to register the
1465 // radio mode change callback.
1466 ndk::ScopedAStatus status = registerRadioModeChangeCallback();
1467 if (!status.isOk()) {
1468 // This is probably not a critical failure?
1469 LOG(ERROR) << "Failed to register radio mode change callback";
1470 }
1471 // Extract and save the version information into property.
1472 std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> version_info;
1473 version_info = WifiChip::requestChipDebugInfoInternal();
1474 if (version_info.second.isOk()) {
1475 property_set("vendor.wlan.firmware.version",
1476 version_info.first.firmwareDescription.c_str());
1477 property_set("vendor.wlan.driver.version", version_info.first.driverDescription.c_str());
1478 }
1479
1480 return ndk::ScopedAStatus::ok();
1481}
1482
1483ndk::ScopedAStatus WifiChip::registerDebugRingBufferCallback() {
1484 if (debug_ring_buffer_cb_registered_) {
1485 return ndk::ScopedAStatus::ok();
1486 }
1487
1488 std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
1489 const auto& on_ring_buffer_data_callback =
1490 [weak_ptr_this](const std::string& name, const std::vector<uint8_t>& data,
1491 const legacy_hal::wifi_ring_buffer_status& status) {
1492 const auto shared_ptr_this = weak_ptr_this.lock();
1493 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1494 LOG(ERROR) << "Callback invoked on an invalid object";
1495 return;
1496 }
1497 WifiDebugRingBufferStatus aidl_status;
1498 Ringbuffer::AppendStatus appendstatus;
1499 if (!aidl_struct_util::convertLegacyDebugRingBufferStatusToAidl(status,
1500 &aidl_status)) {
1501 LOG(ERROR) << "Error converting ring buffer status";
1502 return;
1503 }
1504 {
1505 std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
1506 const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
1507 if (target != shared_ptr_this->ringbuffer_map_.end()) {
1508 Ringbuffer& cur_buffer = target->second;
1509 appendstatus = cur_buffer.append(data);
1510 } else {
1511 LOG(ERROR) << "Ringname " << name << " not found";
1512 return;
1513 }
1514 // unique_lock unlocked here
1515 }
1516 if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) {
1517 LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer";
1518 shared_ptr_this->writeRingbufferFilesInternal();
1519 return;
1520 }
1521 };
1522 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler(
1523 getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
1524
1525 if (legacy_status == legacy_hal::WIFI_SUCCESS) {
1526 debug_ring_buffer_cb_registered_ = true;
1527 }
1528 return createWifiStatusFromLegacyError(legacy_status);
1529}
1530
1531ndk::ScopedAStatus WifiChip::registerRadioModeChangeCallback() {
1532 std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
1533 const auto& on_radio_mode_change_callback =
1534 [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
1535 const auto shared_ptr_this = weak_ptr_this.lock();
1536 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1537 LOG(ERROR) << "Callback invoked on an invalid object";
1538 return;
1539 }
1540 std::vector<IWifiChipEventCallback::RadioModeInfo> aidl_radio_mode_infos;
1541 if (!aidl_struct_util::convertLegacyWifiMacInfosToAidl(mac_infos,
1542 &aidl_radio_mode_infos)) {
1543 LOG(ERROR) << "Error converting wifi mac info";
1544 return;
1545 }
1546 for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
1547 if (!callback->onRadioModeChange(aidl_radio_mode_infos).isOk()) {
1548 LOG(ERROR) << "Failed to invoke onRadioModeChange callback";
1549 }
1550 }
1551 };
1552 legacy_hal::wifi_error legacy_status =
1553 legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
1554 getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
1555 return createWifiStatusFromLegacyError(legacy_status);
1556}
1557
1558std::vector<IWifiChip::ChipConcurrencyCombination>
1559WifiChip::getCurrentModeConcurrencyCombinations() {
1560 if (!isValidModeId(current_mode_id_)) {
1561 LOG(ERROR) << "Chip not configured in a mode yet";
1562 return std::vector<IWifiChip::ChipConcurrencyCombination>();
1563 }
1564 for (const auto& mode : modes_) {
1565 if (mode.id == current_mode_id_) {
1566 return mode.availableCombinations;
1567 }
1568 }
1569 CHECK(0) << "Expected to find concurrency combinations for current mode!";
1570 return std::vector<IWifiChip::ChipConcurrencyCombination>();
1571}
1572
1573// Returns a map indexed by IfaceConcurrencyType with the number of ifaces currently
1574// created of the corresponding concurrency type.
1575std::map<IfaceConcurrencyType, size_t> WifiChip::getCurrentConcurrencyCombination() {
1576 std::map<IfaceConcurrencyType, size_t> iface_counts;
1577 uint32_t num_ap = 0;
1578 uint32_t num_ap_bridged = 0;
1579 for (const auto& ap_iface : ap_ifaces_) {
1580 std::string ap_iface_name = ap_iface->getName();
1581 if (br_ifaces_ap_instances_.count(ap_iface_name) > 0 &&
1582 br_ifaces_ap_instances_[ap_iface_name].size() > 1) {
1583 num_ap_bridged++;
1584 } else {
1585 num_ap++;
1586 }
1587 }
1588 iface_counts[IfaceConcurrencyType::AP] = num_ap;
1589 iface_counts[IfaceConcurrencyType::AP_BRIDGED] = num_ap_bridged;
1590 iface_counts[IfaceConcurrencyType::NAN_IFACE] = nan_ifaces_.size();
1591 iface_counts[IfaceConcurrencyType::P2P] = p2p_ifaces_.size();
1592 iface_counts[IfaceConcurrencyType::STA] = sta_ifaces_.size();
1593 return iface_counts;
1594}
1595
1596// This expands the provided concurrency combinations to a more parseable
1597// form. Returns a vector of available combinations possible with the number
1598// of each concurrency type in the combination.
1599// This method is a port of HalDeviceManager.expandConcurrencyCombos() from framework.
1600std::vector<std::map<IfaceConcurrencyType, size_t>> WifiChip::expandConcurrencyCombinations(
1601 const IWifiChip::ChipConcurrencyCombination& combination) {
1602 int32_t num_expanded_combos = 1;
1603 for (const auto& limit : combination.limits) {
1604 for (int32_t i = 0; i < limit.maxIfaces; i++) {
1605 num_expanded_combos *= limit.types.size();
1606 }
1607 }
1608
1609 // Allocate the vector of expanded combos and reset all concurrency type counts to 0
1610 // in each combo.
1611 std::vector<std::map<IfaceConcurrencyType, size_t>> expanded_combos;
1612 expanded_combos.resize(num_expanded_combos);
1613 for (auto& expanded_combo : expanded_combos) {
1614 for (const auto type : {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
1615 IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P,
1616 IfaceConcurrencyType::STA}) {
1617 expanded_combo[type] = 0;
1618 }
1619 }
1620 int32_t span = num_expanded_combos;
1621 for (const auto& limit : combination.limits) {
1622 for (int32_t i = 0; i < limit.maxIfaces; i++) {
1623 span /= limit.types.size();
1624 for (int32_t k = 0; k < num_expanded_combos; ++k) {
1625 const auto iface_type = limit.types[(k / span) % limit.types.size()];
1626 expanded_combos[k][iface_type]++;
1627 }
1628 }
1629 }
1630 return expanded_combos;
1631}
1632
1633bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(
1634 const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
1635 IfaceConcurrencyType requested_type) {
1636 const auto current_combo = getCurrentConcurrencyCombination();
1637
1638 // Check if we have space for 1 more iface of |type| in this combo
1639 for (const auto type :
1640 {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
1641 IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
1642 size_t num_ifaces_needed = current_combo.at(type);
1643 if (type == requested_type) {
1644 num_ifaces_needed++;
1645 }
1646 size_t num_ifaces_allowed = expanded_combo.at(type);
1647 if (num_ifaces_needed > num_ifaces_allowed) {
1648 return false;
1649 }
1650 }
1651 return true;
1652}
1653
1654// This method does the following:
1655// a) Enumerate all possible concurrency combos by expanding the current
1656// ChipConcurrencyCombination.
1657// b) Check if the requested concurrency type can be added to the current mode
1658// with the concurrency combination that is already active.
1659bool WifiChip::canCurrentModeSupportConcurrencyTypeWithCurrentTypes(
1660 IfaceConcurrencyType requested_type) {
1661 if (!isValidModeId(current_mode_id_)) {
1662 LOG(ERROR) << "Chip not configured in a mode yet";
1663 return false;
1664 }
1665 const auto combinations = getCurrentModeConcurrencyCombinations();
1666 for (const auto& combination : combinations) {
1667 const auto expanded_combos = expandConcurrencyCombinations(combination);
1668 for (const auto& expanded_combo : expanded_combos) {
1669 if (canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(expanded_combo,
1670 requested_type)) {
1671 return true;
1672 }
1673 }
1674 }
1675 return false;
1676}
1677
1678// Note: This does not consider concurrency types already active. It only checks if the
1679// provided expanded concurrency combination can support the requested combo.
1680bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyCombo(
1681 const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
1682 const std::map<IfaceConcurrencyType, size_t>& req_combo) {
1683 // Check if we have space for 1 more |type| in this combo
1684 for (const auto type :
1685 {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
1686 IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
1687 if (req_combo.count(type) == 0) {
1688 // Concurrency type not in the req_combo.
1689 continue;
1690 }
1691 size_t num_ifaces_needed = req_combo.at(type);
1692 size_t num_ifaces_allowed = expanded_combo.at(type);
1693 if (num_ifaces_needed > num_ifaces_allowed) {
1694 return false;
1695 }
1696 }
1697 return true;
1698}
1699
1700// This method does the following:
1701// a) Enumerate all possible concurrency combos by expanding the current
1702// ChipConcurrencyCombination.
1703// b) Check if the requested concurrency combo can be added to the current mode.
1704// Note: This does not consider concurrency types already active. It only checks if the
1705// current mode can support the requested combo.
1706bool WifiChip::canCurrentModeSupportConcurrencyCombo(
1707 const std::map<IfaceConcurrencyType, size_t>& req_combo) {
1708 if (!isValidModeId(current_mode_id_)) {
1709 LOG(ERROR) << "Chip not configured in a mode yet";
1710 return false;
1711 }
1712 const auto combinations = getCurrentModeConcurrencyCombinations();
1713 for (const auto& combination : combinations) {
1714 const auto expanded_combos = expandConcurrencyCombinations(combination);
1715 for (const auto& expanded_combo : expanded_combos) {
1716 if (canExpandedConcurrencyComboSupportConcurrencyCombo(expanded_combo, req_combo)) {
1717 return true;
1718 }
1719 }
1720 }
1721 return false;
1722}
1723
1724// This method does the following:
1725// a) Enumerate all possible concurrency combos by expanding the current
1726// ChipConcurrencyCombination.
1727// b) Check if the requested concurrency type can be added to the current mode.
1728bool WifiChip::canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type) {
1729 // Check if we can support at least 1 of the requested concurrency type.
1730 std::map<IfaceConcurrencyType, size_t> req_iface_combo;
1731 req_iface_combo[requested_type] = 1;
1732 return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
1733}
1734
1735bool WifiChip::isValidModeId(int32_t mode_id) {
1736 for (const auto& mode : modes_) {
1737 if (mode.id == mode_id) {
1738 return true;
1739 }
1740 }
1741 return false;
1742}
1743
1744bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
1745 // Check if we can support at least 1 STA & 1 AP concurrently.
1746 std::map<IfaceConcurrencyType, size_t> req_iface_combo;
1747 req_iface_combo[IfaceConcurrencyType::STA] = 1;
1748 req_iface_combo[IfaceConcurrencyType::AP] = 1;
1749 return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
1750}
1751
1752bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() {
1753 // Check if we can support at least 2 STA concurrently.
1754 std::map<IfaceConcurrencyType, size_t> req_iface_combo;
1755 req_iface_combo[IfaceConcurrencyType::STA] = 2;
1756 return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
1757}
1758
1759std::string WifiChip::getFirstActiveWlanIfaceName() {
1760 if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
1761 if (ap_ifaces_.size() > 0) {
1762 // If the first active wlan iface is bridged iface.
1763 // Return first instance name.
1764 for (auto const& it : br_ifaces_ap_instances_) {
1765 if (it.first == ap_ifaces_[0]->getName()) {
1766 return it.second[0];
1767 }
1768 }
1769 return ap_ifaces_[0]->getName();
1770 }
1771 // This could happen if the chip call is made before any STA/AP
1772 // iface is created. Default to wlan0 for such cases.
1773 LOG(WARNING) << "No active wlan interfaces in use! Using default";
1774 return getWlanIfaceNameWithType(IfaceType::STA, 0);
1775}
1776
1777// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
1778// not already in use.
1779// Note: This doesn't check the actual presence of these interfaces.
1780std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) {
1781 for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
1782 const auto ifname = getWlanIfaceNameWithType(type, idx);
1783 if (findUsingNameFromBridgedApInstances(ifname)) continue;
1784 if (findUsingName(ap_ifaces_, ifname)) continue;
1785 if (findUsingName(sta_ifaces_, ifname)) continue;
1786 return ifname;
1787 }
1788 // This should never happen. We screwed up somewhere if it did.
1789 CHECK(false) << "All wlan interfaces in use already!";
1790 return {};
1791}
1792
1793uint32_t WifiChip::startIdxOfApIface() {
1794 if (isDualStaConcurrencyAllowedInCurrentMode()) {
1795 // When the HAL support dual STAs, AP should start with idx 2.
1796 return 2;
1797 } else if (isStaApConcurrencyAllowedInCurrentMode()) {
1798 // When the HAL support STA + AP but it doesn't support dual STAs.
1799 // AP should start with idx 1.
1800 return 1;
1801 }
1802 // No concurrency support.
1803 return 0;
1804}
1805
1806// AP iface names start with idx 1 for modes supporting
1807// concurrent STA and not dual AP, else start with idx 0.
1808std::string WifiChip::allocateApIfaceName() {
1809 // Check if we have a dedicated iface for AP.
1810 std::vector<std::string> ifnames = getPredefinedApIfaceNames(true);
1811 for (auto const& ifname : ifnames) {
1812 if (findUsingName(ap_ifaces_, ifname)) continue;
1813 return ifname;
1814 }
1815 return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
1816}
1817
1818std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
1819 // Check if we have a dedicated iface for AP.
1820 std::vector<std::string> instances = getPredefinedApIfaceNames(true);
1821 if (instances.size() == 2) {
1822 return instances;
1823 } else {
1824 int num_ifaces_need_to_allocate = 2 - instances.size();
1825 for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
1826 std::string instance_name =
1827 allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i);
1828 if (!instance_name.empty()) {
1829 instances.push_back(instance_name);
1830 }
1831 }
1832 }
1833 return instances;
1834}
1835
1836// STA iface names start with idx 0.
1837// Primary STA iface will always be 0.
1838std::string WifiChip::allocateStaIfaceName() {
1839 return allocateApOrStaIfaceName(IfaceType::STA, 0);
1840}
1841
1842bool WifiChip::writeRingbufferFilesInternal() {
1843 if (!removeOldFilesInternal()) {
1844 LOG(ERROR) << "Error occurred while deleting old tombstone files";
1845 return false;
1846 }
1847 // write ringbuffers to file
1848 {
1849 std::unique_lock<std::mutex> lk(lock_t);
1850 for (auto& item : ringbuffer_map_) {
1851 Ringbuffer& cur_buffer = item.second;
1852 if (cur_buffer.getData().empty()) {
1853 continue;
1854 }
1855 const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX";
1856 const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
1857 if (dump_fd == -1) {
1858 PLOG(ERROR) << "create file failed";
1859 return false;
1860 }
1861 unique_fd file_auto_closer(dump_fd);
1862 for (const auto& cur_block : cur_buffer.getData()) {
1863 if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) {
1864 PLOG(ERROR) << "Ring buffer: " << item.first
1865 << " is corrupted. Invalid block size: " << cur_block.size();
1866 break;
1867 }
1868 if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) ==
1869 -1) {
1870 PLOG(ERROR) << "Error writing to file";
1871 }
1872 }
1873 cur_buffer.clear();
1874 }
1875 // unique_lock unlocked here
1876 }
1877 return true;
1878}
1879
1880std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
1881 std::string ifname;
1882
1883 // let the legacy hal override the interface name
1884 legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
1885 if (err == legacy_hal::WIFI_SUCCESS) return ifname;
1886
1887 return getWlanIfaceName(idx);
1888}
1889
1890void WifiChip::invalidateAndClearBridgedApAll() {
1891 for (auto const& it : br_ifaces_ap_instances_) {
1892 for (auto const& iface : it.second) {
1893 iface_util_->removeIfaceFromBridge(it.first, iface);
1894 legacy_hal_.lock()->deleteVirtualInterface(iface);
1895 }
1896 iface_util_->deleteBridge(it.first);
1897 }
1898 br_ifaces_ap_instances_.clear();
1899}
1900
1901void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) {
1902 if (br_name.empty()) return;
1903 // delete managed interfaces
1904 for (auto const& it : br_ifaces_ap_instances_) {
1905 if (it.first == br_name) {
1906 for (auto const& iface : it.second) {
1907 iface_util_->removeIfaceFromBridge(br_name, iface);
1908 legacy_hal_.lock()->deleteVirtualInterface(iface);
1909 }
1910 iface_util_->deleteBridge(br_name);
1911 br_ifaces_ap_instances_.erase(br_name);
1912 break;
1913 }
1914 }
1915 return;
1916}
1917
1918bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
1919 for (auto const& it : br_ifaces_ap_instances_) {
1920 if (it.first == name) {
1921 return true;
1922 }
1923 for (auto const& iface : it.second) {
1924 if (iface == name) {
1925 return true;
1926 }
1927 }
1928 }
1929 return false;
1930}
1931
1932} // namespace wifi
1933} // namespace hardware
1934} // namespace android
1935} // namespace aidl