1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <fcntl.h>
18
19#include <android-base/logging.h>
20#include <android-base/unique_fd.h>
21#include <cutils/properties.h>
22#include <sys/stat.h>
23#include <sys/sysmacros.h>
24
25#include "hidl_return_util.h"
26#include "hidl_struct_util.h"
27#include "wifi_chip.h"
28#include "wifi_status_util.h"
29
30namespace {
31using android::base::unique_fd;
32using android::hardware::hidl_string;
33using android::hardware::hidl_vec;
34using android::hardware::wifi::V1_0::ChipModeId;
35using android::hardware::wifi::V1_0::IfaceType;
36using android::hardware::wifi::V1_0::IWifiChip;
37using android::sp;
38
39constexpr ChipModeId kInvalidModeId = UINT32_MAX;
40// These mode ID's should be unique (even across combo versions). Refer to
41// handleChipConfiguration() for it's usage.
42// Mode ID's for V1
43constexpr ChipModeId kV1StaChipModeId = 0;
44constexpr ChipModeId kV1ApChipModeId = 1;
45// Mode ID for V2
46constexpr ChipModeId kV2ChipModeId = 2;
47
48constexpr char kCpioMagic[] = "070701";
49constexpr size_t kMaxBufferSizeBytes = 1024 * 1024;
50constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60;
51constexpr uint32_t kMaxRingBufferFileNum = 20;
52constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
53
54template <typename Iface>
55void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
56    iface->invalidate();
57    ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface),
58                 ifaces.end());
59}
60
61template <typename Iface>
62void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) {
63    for (const auto& iface : ifaces) {
64        iface->invalidate();
65    }
66    ifaces.clear();
67}
68
69template <typename Iface>
70std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) {
71    std::vector<hidl_string> names;
72    for (const auto& iface : ifaces) {
73        names.emplace_back(iface->getName());
74    }
75    return names;
76}
77
78template <typename Iface>
79sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces,
80                        const std::string& name) {
81    std::vector<hidl_string> names;
82    for (const auto& iface : ifaces) {
83        if (name == iface->getName()) {
84            return iface;
85        }
86    }
87    return nullptr;
88}
89
90std::string getWlan0IfaceName() {
91    std::array<char, PROPERTY_VALUE_MAX> buffer;
92    property_get("wifi.interface", buffer.data(), "wlan0");
93    return buffer.data();
94}
95
96std::string getWlan1IfaceName() {
97    std::array<char, PROPERTY_VALUE_MAX> buffer;
98    property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
99    return buffer.data();
100}
101
102std::string getP2pIfaceName() {
103    std::array<char, PROPERTY_VALUE_MAX> buffer;
104    property_get("wifi.direct.interface", buffer.data(), "p2p0");
105    return buffer.data();
106}
107
108// delete files that meet either conditions:
109// 1. older than a predefined time in the wifi tombstone dir.
110// 2. Files in excess to a predefined amount, starting from the oldest ones
111bool removeOldFilesInternal() {
112    time_t now = time(0);
113    const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
114    DIR* dir_dump = opendir(kTombstoneFolderPath);
115    if (!dir_dump) {
116        LOG(ERROR) << "Failed to open directory: " << strerror(errno);
117        return false;
118    }
119    unique_fd dir_auto_closer(dirfd(dir_dump));
120    struct dirent* dp;
121    bool success = true;
122    std::list<std::pair<const time_t, std::string>> valid_files;
123    while ((dp = readdir(dir_dump))) {
124        if (dp->d_type != DT_REG) {
125            continue;
126        }
127        std::string cur_file_name(dp->d_name);
128        struct stat cur_file_stat;
129        std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
130        if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
131            LOG(ERROR) << "Failed to get file stat for " << cur_file_path
132                       << ": " << strerror(errno);
133            success = false;
134            continue;
135        }
136        const time_t cur_file_time = cur_file_stat.st_mtime;
137        valid_files.push_back(
138            std::pair<const time_t, std::string>(cur_file_time, cur_file_path));
139    }
140    valid_files.sort();  // sort the list of files by last modified time from
141                         // small to big.
142    uint32_t cur_file_count = valid_files.size();
143    for (auto cur_file : valid_files) {
144        if (cur_file_count > kMaxRingBufferFileNum ||
145            cur_file.first < delete_files_before) {
146            if (unlink(cur_file.second.c_str()) != 0) {
147                LOG(ERROR) << "Error deleting file " << strerror(errno);
148                success = false;
149            }
150            cur_file_count--;
151        } else {
152            break;
153        }
154    }
155    return success;
156}
157
158// Helper function for |cpioArchiveFilesInDir|
159bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name,
160                     size_t file_name_len) {
161    std::array<char, 32 * 1024> read_buf;
162    ssize_t llen =
163        sprintf(read_buf.data(),
164                "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
165                kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
166                st.st_gid, static_cast<int>(st.st_nlink),
167                static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
168                major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
169                minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
170    if (write(out_fd, read_buf.data(), llen) == -1) {
171        LOG(ERROR) << "Error writing cpio header to file " << file_name << " "
172                   << strerror(errno);
173        return false;
174    }
175    if (write(out_fd, file_name, file_name_len) == -1) {
176        LOG(ERROR) << "Error writing filename to file " << file_name << " "
177                   << strerror(errno);
178        return false;
179    }
180
181    // NUL Pad header up to 4 multiple bytes.
182    llen = (llen + file_name_len) % 4;
183    if (llen != 0) {
184        const uint32_t zero = 0;
185        if (write(out_fd, &zero, 4 - llen) == -1) {
186            LOG(ERROR) << "Error padding 0s to file " << file_name << " "
187                       << strerror(errno);
188            return false;
189        }
190    }
191    return true;
192}
193
194// Helper function for |cpioArchiveFilesInDir|
195size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
196    // writing content of file
197    std::array<char, 32 * 1024> read_buf;
198    ssize_t llen = st.st_size;
199    size_t n_error = 0;
200    while (llen > 0) {
201        ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
202        if (bytes_read == -1) {
203            LOG(ERROR) << "Error reading file " << strerror(errno);
204            return ++n_error;
205        }
206        llen -= bytes_read;
207        if (write(out_fd, read_buf.data(), bytes_read) == -1) {
208            LOG(ERROR) << "Error writing data to file " << strerror(errno);
209            return ++n_error;
210        }
211        if (bytes_read == 0) {  // this should never happen, but just in case
212                                // to unstuck from while loop
213            LOG(ERROR) << "Unexpected read result for " << strerror(errno);
214            n_error++;
215            break;
216        }
217    }
218    llen = st.st_size % 4;
219    if (llen != 0) {
220        const uint32_t zero = 0;
221        if (write(out_fd, &zero, 4 - llen) == -1) {
222            LOG(ERROR) << "Error padding 0s to file " << strerror(errno);
223            return ++n_error;
224        }
225    }
226    return n_error;
227}
228
229// Helper function for |cpioArchiveFilesInDir|
230bool cpioWriteFileTrailer(int out_fd) {
231    std::array<char, 4096> read_buf;
232    read_buf.fill(0);
233    if (write(out_fd, read_buf.data(),
234              sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1,
235                      0x0b, 0) +
236                  4) == -1) {
237        LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
238        return false;
239    }
240    return true;
241}
242
243// Archives all files in |input_dir| and writes result into |out_fd|
244// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
245// portion
246size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
247    struct dirent* dp;
248    size_t n_error = 0;
249    DIR* dir_dump = opendir(input_dir);
250    if (!dir_dump) {
251        LOG(ERROR) << "Failed to open directory: " << strerror(errno);
252        return ++n_error;
253    }
254    unique_fd dir_auto_closer(dirfd(dir_dump));
255    while ((dp = readdir(dir_dump))) {
256        if (dp->d_type != DT_REG) {
257            continue;
258        }
259        std::string cur_file_name(dp->d_name);
260        // string.size() does not include the null terminator. The cpio FreeBSD
261        // file header expects the null character to be included in the length.
262        const size_t file_name_len = cur_file_name.size() + 1;
263        struct stat st;
264        const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
265        if (stat(cur_file_path.c_str(), &st) == -1) {
266            LOG(ERROR) << "Failed to get file stat for " << cur_file_path
267                       << ": " << strerror(errno);
268            n_error++;
269            continue;
270        }
271        const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
272        if (fd_read == -1) {
273            LOG(ERROR) << "Failed to open file " << cur_file_path << " "
274                       << strerror(errno);
275            n_error++;
276            continue;
277        }
278        unique_fd file_auto_closer(fd_read);
279        if (!cpioWriteHeader(out_fd, st, cur_file_name.c_str(),
280                             file_name_len)) {
281            return ++n_error;
282        }
283        size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
284        if (write_error) {
285            return n_error + write_error;
286        }
287    }
288    if (!cpioWriteFileTrailer(out_fd)) {
289        return ++n_error;
290    }
291    return n_error;
292}
293
294// Helper function to create a non-const char*.
295std::vector<char> makeCharVec(const std::string& str) {
296    std::vector<char> vec(str.size() + 1);
297    vec.assign(str.begin(), str.end());
298    vec.push_back('\0');
299    return vec;
300}
301
302}  // namespace
303
304namespace android {
305namespace hardware {
306namespace wifi {
307namespace V1_2 {
308namespace implementation {
309using hidl_return_util::validateAndCall;
310using hidl_return_util::validateAndCallWithLock;
311
312WifiChip::WifiChip(
313    ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
314    const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
315    const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
316    : chip_id_(chip_id),
317      legacy_hal_(legacy_hal),
318      mode_controller_(mode_controller),
319      feature_flags_(feature_flags),
320      is_valid_(true),
321      current_mode_id_(kInvalidModeId),
322      debug_ring_buffer_cb_registered_(false) {
323    populateModes();
324}
325
326void WifiChip::invalidate() {
327    if (!writeRingbufferFilesInternal()) {
328        LOG(ERROR) << "Error writing files to flash";
329    }
330    invalidateAndRemoveAllIfaces();
331    legacy_hal_.reset();
332    event_cb_handler_.invalidate();
333    is_valid_ = false;
334}
335
336bool WifiChip::isValid() { return is_valid_; }
337
338std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
339    return event_cb_handler_.getCallbacks();
340}
341
342Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
343    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
344                           &WifiChip::getIdInternal, hidl_status_cb);
345}
346
347Return<void> WifiChip::registerEventCallback(
348    const sp<V1_0::IWifiChipEventCallback>& event_callback,
349    registerEventCallback_cb hidl_status_cb) {
350    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
351                           &WifiChip::registerEventCallbackInternal,
352                           hidl_status_cb, event_callback);
353}
354
355Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) {
356    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
357                           &WifiChip::getCapabilitiesInternal, hidl_status_cb);
358}
359
360Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
361    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
362                           &WifiChip::getAvailableModesInternal,
363                           hidl_status_cb);
364}
365
366Return<void> WifiChip::configureChip(ChipModeId mode_id,
367                                     configureChip_cb hidl_status_cb) {
368    return validateAndCallWithLock(
369        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
370        &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
371}
372
373Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
374    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
375                           &WifiChip::getModeInternal, hidl_status_cb);
376}
377
378Return<void> WifiChip::requestChipDebugInfo(
379    requestChipDebugInfo_cb hidl_status_cb) {
380    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
381                           &WifiChip::requestChipDebugInfoInternal,
382                           hidl_status_cb);
383}
384
385Return<void> WifiChip::requestDriverDebugDump(
386    requestDriverDebugDump_cb hidl_status_cb) {
387    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
388                           &WifiChip::requestDriverDebugDumpInternal,
389                           hidl_status_cb);
390}
391
392Return<void> WifiChip::requestFirmwareDebugDump(
393    requestFirmwareDebugDump_cb hidl_status_cb) {
394    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
395                           &WifiChip::requestFirmwareDebugDumpInternal,
396                           hidl_status_cb);
397}
398
399Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
400    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
401                           &WifiChip::createApIfaceInternal, hidl_status_cb);
402}
403
404Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
405    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
406                           &WifiChip::getApIfaceNamesInternal, hidl_status_cb);
407}
408
409Return<void> WifiChip::getApIface(const hidl_string& ifname,
410                                  getApIface_cb hidl_status_cb) {
411    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
412                           &WifiChip::getApIfaceInternal, hidl_status_cb,
413                           ifname);
414}
415
416Return<void> WifiChip::removeApIface(const hidl_string& ifname,
417                                     removeApIface_cb hidl_status_cb) {
418    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
419                           &WifiChip::removeApIfaceInternal, hidl_status_cb,
420                           ifname);
421}
422
423Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
424    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
425                           &WifiChip::createNanIfaceInternal, hidl_status_cb);
426}
427
428Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) {
429    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
430                           &WifiChip::getNanIfaceNamesInternal, hidl_status_cb);
431}
432
433Return<void> WifiChip::getNanIface(const hidl_string& ifname,
434                                   getNanIface_cb hidl_status_cb) {
435    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
436                           &WifiChip::getNanIfaceInternal, hidl_status_cb,
437                           ifname);
438}
439
440Return<void> WifiChip::removeNanIface(const hidl_string& ifname,
441                                      removeNanIface_cb hidl_status_cb) {
442    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
443                           &WifiChip::removeNanIfaceInternal, hidl_status_cb,
444                           ifname);
445}
446
447Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) {
448    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
449                           &WifiChip::createP2pIfaceInternal, hidl_status_cb);
450}
451
452Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) {
453    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
454                           &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb);
455}
456
457Return<void> WifiChip::getP2pIface(const hidl_string& ifname,
458                                   getP2pIface_cb hidl_status_cb) {
459    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
460                           &WifiChip::getP2pIfaceInternal, hidl_status_cb,
461                           ifname);
462}
463
464Return<void> WifiChip::removeP2pIface(const hidl_string& ifname,
465                                      removeP2pIface_cb hidl_status_cb) {
466    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
467                           &WifiChip::removeP2pIfaceInternal, hidl_status_cb,
468                           ifname);
469}
470
471Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
472    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
473                           &WifiChip::createStaIfaceInternal, hidl_status_cb);
474}
475
476Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
477    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
478                           &WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
479}
480
481Return<void> WifiChip::getStaIface(const hidl_string& ifname,
482                                   getStaIface_cb hidl_status_cb) {
483    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
484                           &WifiChip::getStaIfaceInternal, hidl_status_cb,
485                           ifname);
486}
487
488Return<void> WifiChip::removeStaIface(const hidl_string& ifname,
489                                      removeStaIface_cb hidl_status_cb) {
490    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
491                           &WifiChip::removeStaIfaceInternal, hidl_status_cb,
492                           ifname);
493}
494
495Return<void> WifiChip::createRttController(
496    const sp<IWifiIface>& bound_iface, createRttController_cb hidl_status_cb) {
497    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
498                           &WifiChip::createRttControllerInternal,
499                           hidl_status_cb, bound_iface);
500}
501
502Return<void> WifiChip::getDebugRingBuffersStatus(
503    getDebugRingBuffersStatus_cb hidl_status_cb) {
504    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
505                           &WifiChip::getDebugRingBuffersStatusInternal,
506                           hidl_status_cb);
507}
508
509Return<void> WifiChip::startLoggingToDebugRingBuffer(
510    const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
511    uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
512    startLoggingToDebugRingBuffer_cb hidl_status_cb) {
513    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
514                           &WifiChip::startLoggingToDebugRingBufferInternal,
515                           hidl_status_cb, ring_name, verbose_level,
516                           max_interval_in_sec, min_data_size_in_bytes);
517}
518
519Return<void> WifiChip::forceDumpToDebugRingBuffer(
520    const hidl_string& ring_name,
521    forceDumpToDebugRingBuffer_cb hidl_status_cb) {
522    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
523                           &WifiChip::forceDumpToDebugRingBufferInternal,
524                           hidl_status_cb, ring_name);
525}
526
527Return<void> WifiChip::stopLoggingToDebugRingBuffer(
528    stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
529    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
530                           &WifiChip::stopLoggingToDebugRingBufferInternal,
531                           hidl_status_cb);
532}
533
534Return<void> WifiChip::getDebugHostWakeReasonStats(
535    getDebugHostWakeReasonStats_cb hidl_status_cb) {
536    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
537                           &WifiChip::getDebugHostWakeReasonStatsInternal,
538                           hidl_status_cb);
539}
540
541Return<void> WifiChip::enableDebugErrorAlerts(
542    bool enable, enableDebugErrorAlerts_cb hidl_status_cb) {
543    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
544                           &WifiChip::enableDebugErrorAlertsInternal,
545                           hidl_status_cb, enable);
546}
547
548Return<void> WifiChip::selectTxPowerScenario(
549    V1_1::IWifiChip::TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
550    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
551                           &WifiChip::selectTxPowerScenarioInternal,
552                           hidl_status_cb, scenario);
553}
554
555Return<void> WifiChip::resetTxPowerScenario(
556    resetTxPowerScenario_cb hidl_status_cb) {
557    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
558                           &WifiChip::resetTxPowerScenarioInternal,
559                           hidl_status_cb);
560}
561
562Return<void> WifiChip::registerEventCallback_1_2(
563    const sp<IWifiChipEventCallback>& event_callback,
564    registerEventCallback_cb hidl_status_cb) {
565    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
566                           &WifiChip::registerEventCallbackInternal_1_2,
567                           hidl_status_cb, event_callback);
568}
569
570Return<void> WifiChip::selectTxPowerScenario_1_2(
571        TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
572    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
573            &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario);
574}
575
576Return<void> WifiChip::debug(const hidl_handle& handle,
577                             const hidl_vec<hidl_string>&) {
578    if (handle != nullptr && handle->numFds >= 1) {
579        int fd = handle->data[0];
580        if (!writeRingbufferFilesInternal()) {
581            LOG(ERROR) << "Error writing files to flash";
582        }
583        uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
584        if (n_error != 0) {
585            LOG(ERROR) << n_error << " errors occured in cpio function";
586        }
587        fsync(fd);
588    } else {
589        LOG(ERROR) << "File handle error";
590    }
591    return Void();
592}
593
594void WifiChip::invalidateAndRemoveAllIfaces() {
595    invalidateAndClearAll(ap_ifaces_);
596    invalidateAndClearAll(nan_ifaces_);
597    invalidateAndClearAll(p2p_ifaces_);
598    invalidateAndClearAll(sta_ifaces_);
599    // Since all the ifaces are invalid now, all RTT controller objects
600    // using those ifaces also need to be invalidated.
601    for (const auto& rtt : rtt_controllers_) {
602        rtt->invalidate();
603    }
604    rtt_controllers_.clear();
605}
606
607std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
608    return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
609}
610
611WifiStatus WifiChip::registerEventCallbackInternal(
612    const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) {
613    // Deprecated support for this callback.
614    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
615}
616
617std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
618    legacy_hal::wifi_error legacy_status;
619    uint32_t legacy_feature_set;
620    uint32_t legacy_logger_feature_set;
621    std::tie(legacy_status, legacy_feature_set) =
622        legacy_hal_.lock()->getSupportedFeatureSet(getWlan0IfaceName());
623    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
624        return {createWifiStatusFromLegacyError(legacy_status), 0};
625    }
626    std::tie(legacy_status, legacy_logger_feature_set) =
627        legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
628    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
629        // some devices don't support querying logger feature set
630        legacy_logger_feature_set = 0;
631    }
632    uint32_t hidl_caps;
633    if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
634            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
635        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
636    }
637    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
638}
639
640std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
641WifiChip::getAvailableModesInternal() {
642    return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
643}
644
645WifiStatus WifiChip::configureChipInternal(
646    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
647    ChipModeId mode_id) {
648    if (!isValidModeId(mode_id)) {
649        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
650    }
651    if (mode_id == current_mode_id_) {
652        LOG(DEBUG) << "Already in the specified mode " << mode_id;
653        return createWifiStatus(WifiStatusCode::SUCCESS);
654    }
655    WifiStatus status = handleChipConfiguration(lock, mode_id);
656    if (status.code != WifiStatusCode::SUCCESS) {
657        for (const auto& callback : event_cb_handler_.getCallbacks()) {
658            if (!callback->onChipReconfigureFailure(status).isOk()) {
659                LOG(ERROR)
660                    << "Failed to invoke onChipReconfigureFailure callback";
661            }
662        }
663        return status;
664    }
665    for (const auto& callback : event_cb_handler_.getCallbacks()) {
666        if (!callback->onChipReconfigured(mode_id).isOk()) {
667            LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
668        }
669    }
670    current_mode_id_ = mode_id;
671    LOG(INFO) << "Configured chip in mode " << mode_id;
672    return status;
673}
674
675std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
676    if (!isValidModeId(current_mode_id_)) {
677        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
678                current_mode_id_};
679    }
680    return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
681}
682
683std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
684WifiChip::requestChipDebugInfoInternal() {
685    IWifiChip::ChipDebugInfo result;
686    legacy_hal::wifi_error legacy_status;
687    std::string driver_desc;
688    std::tie(legacy_status, driver_desc) =
689        legacy_hal_.lock()->getDriverVersion(getWlan0IfaceName());
690    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
691        LOG(ERROR) << "Failed to get driver version: "
692                   << legacyErrorToString(legacy_status);
693        WifiStatus status = createWifiStatusFromLegacyError(
694            legacy_status, "failed to get driver version");
695        return {status, result};
696    }
697    result.driverDescription = driver_desc.c_str();
698
699    std::string firmware_desc;
700    std::tie(legacy_status, firmware_desc) =
701        legacy_hal_.lock()->getFirmwareVersion(getWlan0IfaceName());
702    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
703        LOG(ERROR) << "Failed to get firmware version: "
704                   << legacyErrorToString(legacy_status);
705        WifiStatus status = createWifiStatusFromLegacyError(
706            legacy_status, "failed to get firmware version");
707        return {status, result};
708    }
709    result.firmwareDescription = firmware_desc.c_str();
710
711    return {createWifiStatus(WifiStatusCode::SUCCESS), result};
712}
713
714std::pair<WifiStatus, std::vector<uint8_t>>
715WifiChip::requestDriverDebugDumpInternal() {
716    legacy_hal::wifi_error legacy_status;
717    std::vector<uint8_t> driver_dump;
718    std::tie(legacy_status, driver_dump) =
719        legacy_hal_.lock()->requestDriverMemoryDump(getWlan0IfaceName());
720    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
721        LOG(ERROR) << "Failed to get driver debug dump: "
722                   << legacyErrorToString(legacy_status);
723        return {createWifiStatusFromLegacyError(legacy_status),
724                std::vector<uint8_t>()};
725    }
726    return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump};
727}
728
729std::pair<WifiStatus, std::vector<uint8_t>>
730WifiChip::requestFirmwareDebugDumpInternal() {
731    legacy_hal::wifi_error legacy_status;
732    std::vector<uint8_t> firmware_dump;
733    std::tie(legacy_status, firmware_dump) =
734        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlan0IfaceName());
735    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
736        LOG(ERROR) << "Failed to get firmware debug dump: "
737                   << legacyErrorToString(legacy_status);
738        return {createWifiStatusFromLegacyError(legacy_status), {}};
739    }
740    return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
741}
742
743std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
744    if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) {
745        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
746    }
747    std::string ifname = allocateApOrStaIfaceName();
748    sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_);
749    ap_ifaces_.push_back(iface);
750    for (const auto& callback : event_cb_handler_.getCallbacks()) {
751        if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
752            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
753        }
754    }
755    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
756}
757
758std::pair<WifiStatus, std::vector<hidl_string>>
759WifiChip::getApIfaceNamesInternal() {
760    if (ap_ifaces_.empty()) {
761        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
762    }
763    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)};
764}
765
766std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal(
767    const std::string& ifname) {
768    const auto iface = findUsingName(ap_ifaces_, ifname);
769    if (!iface.get()) {
770        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
771    }
772    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
773}
774
775WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
776    const auto iface = findUsingName(ap_ifaces_, ifname);
777    if (!iface.get()) {
778        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
779    }
780    invalidateAndClear(ap_ifaces_, iface);
781    for (const auto& callback : event_cb_handler_.getCallbacks()) {
782        if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
783            LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
784        }
785    }
786    return createWifiStatus(WifiStatusCode::SUCCESS);
787}
788
789std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
790    if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) {
791        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
792    }
793    // These are still assumed to be based on wlan0.
794    std::string ifname = getWlan0IfaceName();
795    sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
796    nan_ifaces_.push_back(iface);
797    for (const auto& callback : event_cb_handler_.getCallbacks()) {
798        if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
799            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
800        }
801    }
802    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
803}
804
805std::pair<WifiStatus, std::vector<hidl_string>>
806WifiChip::getNanIfaceNamesInternal() {
807    if (nan_ifaces_.empty()) {
808        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
809    }
810    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)};
811}
812
813std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal(
814    const std::string& ifname) {
815    const auto iface = findUsingName(nan_ifaces_, ifname);
816    if (!iface.get()) {
817        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
818    }
819    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
820}
821
822WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
823    const auto iface = findUsingName(nan_ifaces_, ifname);
824    if (!iface.get()) {
825        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
826    }
827    invalidateAndClear(nan_ifaces_, iface);
828    for (const auto& callback : event_cb_handler_.getCallbacks()) {
829        if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
830            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
831        }
832    }
833    return createWifiStatus(WifiStatusCode::SUCCESS);
834}
835
836std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
837    if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) {
838        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
839    }
840    std::string ifname = getP2pIfaceName();
841    sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
842    p2p_ifaces_.push_back(iface);
843    for (const auto& callback : event_cb_handler_.getCallbacks()) {
844        if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
845            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
846        }
847    }
848    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
849}
850
851std::pair<WifiStatus, std::vector<hidl_string>>
852WifiChip::getP2pIfaceNamesInternal() {
853    if (p2p_ifaces_.empty()) {
854        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
855    }
856    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)};
857}
858
859std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(
860    const std::string& ifname) {
861    const auto iface = findUsingName(p2p_ifaces_, ifname);
862    if (!iface.get()) {
863        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
864    }
865    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
866}
867
868WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
869    const auto iface = findUsingName(p2p_ifaces_, ifname);
870    if (!iface.get()) {
871        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
872    }
873    invalidateAndClear(p2p_ifaces_, iface);
874    for (const auto& callback : event_cb_handler_.getCallbacks()) {
875        if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
876            LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
877        }
878    }
879    return createWifiStatus(WifiStatusCode::SUCCESS);
880}
881
882std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
883    if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
884        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
885    }
886    std::string ifname = allocateApOrStaIfaceName();
887    sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);
888    sta_ifaces_.push_back(iface);
889    for (const auto& callback : event_cb_handler_.getCallbacks()) {
890        if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
891            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
892        }
893    }
894    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
895}
896
897std::pair<WifiStatus, std::vector<hidl_string>>
898WifiChip::getStaIfaceNamesInternal() {
899    if (sta_ifaces_.empty()) {
900        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
901    }
902    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
903}
904
905std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
906    const std::string& ifname) {
907    const auto iface = findUsingName(sta_ifaces_, ifname);
908    if (!iface.get()) {
909        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
910    }
911    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
912}
913
914WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
915    const auto iface = findUsingName(sta_ifaces_, ifname);
916    if (!iface.get()) {
917        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
918    }
919    invalidateAndClear(sta_ifaces_, iface);
920    for (const auto& callback : event_cb_handler_.getCallbacks()) {
921        if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
922            LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
923        }
924    }
925    return createWifiStatus(WifiStatusCode::SUCCESS);
926}
927
928std::pair<WifiStatus, sp<IWifiRttController>>
929WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
930    sp<WifiRttController> rtt =
931        new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
932    rtt_controllers_.emplace_back(rtt);
933    return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
934}
935
936std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
937WifiChip::getDebugRingBuffersStatusInternal() {
938    legacy_hal::wifi_error legacy_status;
939    std::vector<legacy_hal::wifi_ring_buffer_status>
940        legacy_ring_buffer_status_vec;
941    std::tie(legacy_status, legacy_ring_buffer_status_vec) =
942        legacy_hal_.lock()->getRingBuffersStatus(getWlan0IfaceName());
943    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
944        return {createWifiStatusFromLegacyError(legacy_status), {}};
945    }
946    std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
947    if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
948            legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
949        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
950    }
951    return {createWifiStatus(WifiStatusCode::SUCCESS),
952            hidl_ring_buffer_status_vec};
953}
954
955WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
956    const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
957    uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
958    WifiStatus status = registerDebugRingBufferCallback();
959    if (status.code != WifiStatusCode::SUCCESS) {
960        return status;
961    }
962    legacy_hal::wifi_error legacy_status =
963        legacy_hal_.lock()->startRingBufferLogging(
964            getWlan0IfaceName(), ring_name,
965            static_cast<
966                std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
967                verbose_level),
968            max_interval_in_sec, min_data_size_in_bytes);
969    ringbuffer_map_.insert(std::pair<std::string, Ringbuffer>(
970        ring_name, Ringbuffer(kMaxBufferSizeBytes)));
971    return createWifiStatusFromLegacyError(legacy_status);
972}
973
974WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
975    const hidl_string& ring_name) {
976    WifiStatus status = registerDebugRingBufferCallback();
977    if (status.code != WifiStatusCode::SUCCESS) {
978        return status;
979    }
980    legacy_hal::wifi_error legacy_status =
981        legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
982
983    return createWifiStatusFromLegacyError(legacy_status);
984}
985
986WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
987    legacy_hal::wifi_error legacy_status =
988        legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
989            getWlan0IfaceName());
990    return createWifiStatusFromLegacyError(legacy_status);
991}
992
993std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
994WifiChip::getDebugHostWakeReasonStatsInternal() {
995    legacy_hal::wifi_error legacy_status;
996    legacy_hal::WakeReasonStats legacy_stats;
997    std::tie(legacy_status, legacy_stats) =
998        legacy_hal_.lock()->getWakeReasonStats(getWlan0IfaceName());
999    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1000        return {createWifiStatusFromLegacyError(legacy_status), {}};
1001    }
1002    WifiDebugHostWakeReasonStats hidl_stats;
1003    if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats,
1004                                                              &hidl_stats)) {
1005        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
1006    }
1007    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
1008}
1009
1010WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
1011    legacy_hal::wifi_error legacy_status;
1012    if (enable) {
1013        android::wp<WifiChip> weak_ptr_this(this);
1014        const auto& on_alert_callback = [weak_ptr_this](
1015                                            int32_t error_code,
1016                                            std::vector<uint8_t> debug_data) {
1017            const auto shared_ptr_this = weak_ptr_this.promote();
1018            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1019                LOG(ERROR) << "Callback invoked on an invalid object";
1020                return;
1021            }
1022            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
1023                if (!callback->onDebugErrorAlert(error_code, debug_data)
1024                         .isOk()) {
1025                    LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
1026                }
1027            }
1028        };
1029        legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
1030            getWlan0IfaceName(), on_alert_callback);
1031    } else {
1032        legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
1033            getWlan0IfaceName());
1034    }
1035    return createWifiStatusFromLegacyError(legacy_status);
1036}
1037
1038WifiStatus WifiChip::selectTxPowerScenarioInternal(
1039        V1_1::IWifiChip::TxPowerScenario scenario) {
1040    auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
1041        getWlan0IfaceName(),
1042        hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
1043    return createWifiStatusFromLegacyError(legacy_status);
1044}
1045
1046WifiStatus WifiChip::resetTxPowerScenarioInternal() {
1047    auto legacy_status =
1048        legacy_hal_.lock()->resetTxPowerScenario(getWlan0IfaceName());
1049    return createWifiStatusFromLegacyError(legacy_status);
1050}
1051
1052WifiStatus WifiChip::registerEventCallbackInternal_1_2(
1053    const sp<IWifiChipEventCallback>& event_callback) {
1054    if (!event_cb_handler_.addCallback(event_callback)) {
1055        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
1056    }
1057    return createWifiStatus(WifiStatusCode::SUCCESS);
1058}
1059
1060WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) {
1061    auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
1062        getWlan0IfaceName(),
1063        hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
1064    return createWifiStatusFromLegacyError(legacy_status);
1065}
1066
1067WifiStatus WifiChip::handleChipConfiguration(
1068    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
1069    ChipModeId mode_id) {
1070    // If the chip is already configured in a different mode, stop
1071    // the legacy HAL and then start it after firmware mode change.
1072    if (isValidModeId(current_mode_id_)) {
1073        LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
1074                  << " to mode " << mode_id;
1075        invalidateAndRemoveAllIfaces();
1076        legacy_hal::wifi_error legacy_status =
1077            legacy_hal_.lock()->stop(lock, []() {});
1078        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1079            LOG(ERROR) << "Failed to stop legacy HAL: "
1080                       << legacyErrorToString(legacy_status);
1081            return createWifiStatusFromLegacyError(legacy_status);
1082        }
1083    }
1084    // Firmware mode change not needed for V2 devices.
1085    bool success = true;
1086    if (mode_id == kV1StaChipModeId) {
1087        success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
1088    } else if (mode_id == kV1ApChipModeId) {
1089        success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
1090    }
1091    if (!success) {
1092        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
1093    }
1094    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
1095    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
1096        LOG(ERROR) << "Failed to start legacy HAL: "
1097                   << legacyErrorToString(legacy_status);
1098        return createWifiStatusFromLegacyError(legacy_status);
1099    }
1100    // Every time the HAL is restarted, we need to register the
1101    // radio mode change callback.
1102    WifiStatus status = registerRadioModeChangeCallback();
1103    if (status.code != WifiStatusCode::SUCCESS) {
1104        // This probably is not a critical failure?
1105        LOG(ERROR) << "Failed to register radio mode change callback";
1106    }
1107    return createWifiStatus(WifiStatusCode::SUCCESS);
1108}
1109
1110WifiStatus WifiChip::registerDebugRingBufferCallback() {
1111    if (debug_ring_buffer_cb_registered_) {
1112        return createWifiStatus(WifiStatusCode::SUCCESS);
1113    }
1114
1115    android::wp<WifiChip> weak_ptr_this(this);
1116    const auto& on_ring_buffer_data_callback =
1117        [weak_ptr_this](const std::string& name,
1118                        const std::vector<uint8_t>& data,
1119                        const legacy_hal::wifi_ring_buffer_status& status) {
1120            const auto shared_ptr_this = weak_ptr_this.promote();
1121            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1122                LOG(ERROR) << "Callback invoked on an invalid object";
1123                return;
1124            }
1125            WifiDebugRingBufferStatus hidl_status;
1126            if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(
1127                    status, &hidl_status)) {
1128                LOG(ERROR) << "Error converting ring buffer status";
1129                return;
1130            }
1131            const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
1132            if (target != shared_ptr_this->ringbuffer_map_.end()) {
1133                Ringbuffer& cur_buffer = target->second;
1134                cur_buffer.append(data);
1135            } else {
1136                LOG(ERROR) << "Ringname " << name << " not found";
1137                return;
1138            }
1139        };
1140    legacy_hal::wifi_error legacy_status =
1141        legacy_hal_.lock()->registerRingBufferCallbackHandler(
1142            getWlan0IfaceName(), on_ring_buffer_data_callback);
1143
1144    if (legacy_status == legacy_hal::WIFI_SUCCESS) {
1145        debug_ring_buffer_cb_registered_ = true;
1146    }
1147    return createWifiStatusFromLegacyError(legacy_status);
1148}
1149
1150WifiStatus WifiChip::registerRadioModeChangeCallback() {
1151    android::wp<WifiChip> weak_ptr_this(this);
1152    const auto& on_radio_mode_change_callback =
1153        [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
1154            const auto shared_ptr_this = weak_ptr_this.promote();
1155            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
1156                LOG(ERROR) << "Callback invoked on an invalid object";
1157                return;
1158            }
1159            std::vector<IWifiChipEventCallback::RadioModeInfo>
1160                hidl_radio_mode_infos;
1161            if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(
1162                    mac_infos, &hidl_radio_mode_infos)) {
1163                LOG(ERROR) << "Error converting wifi mac info";
1164                return;
1165            }
1166            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
1167                if (!callback->onRadioModeChange(hidl_radio_mode_infos)
1168                         .isOk()) {
1169                    LOG(ERROR) << "Failed to invoke onRadioModeChange"
1170                               << " callback on: " << toString(callback);
1171                }
1172            }
1173        };
1174    legacy_hal::wifi_error legacy_status =
1175        legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
1176            getWlan0IfaceName(), on_radio_mode_change_callback);
1177    return createWifiStatusFromLegacyError(legacy_status);
1178}
1179
1180void WifiChip::populateModes() {
1181    // The chip combination supported for current devices is fixed.
1182    // They can be one of the following based on device features:
1183    // a) 2 separate modes of operation with 1 interface combination each:
1184    //    Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN(optional)
1185    //                       concurrent iface operations.
1186    //    Mode 2 (AP mode): Will support 1 AP iface operation.
1187    //
1188    // b) 1 mode of operation with 2 interface combinations
1189    // (conditional on isDualInterfaceSupported()):
1190    //    Interface Combination 1: Will support 1 STA and 1 P2P or NAN(optional)
1191    //                             concurrent iface operations.
1192    //    Interface Combination 2: Will support 1 STA and 1 AP concurrent
1193    //                             iface operations.
1194    // If Aware is enabled (conditional on isAwareSupported()), the iface
1195    // combination will be modified to support either P2P or NAN in place of
1196    // just P2P.
1197    if (feature_flags_.lock()->isDualInterfaceSupported()) {
1198        // V2 Iface combinations for Mode Id = 2.
1199        const IWifiChip::ChipIfaceCombinationLimit
1200            chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
1201        const IWifiChip::ChipIfaceCombinationLimit
1202            chip_iface_combination_limit_2 = {{IfaceType::AP}, 1};
1203        IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;
1204        if (feature_flags_.lock()->isAwareSupported()) {
1205            chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},
1206                                              1};
1207        } else {
1208            chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};
1209        }
1210        const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
1211            {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
1212        const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
1213            {chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
1214        if (feature_flags_.lock()->isApDisabled()) {
1215          const IWifiChip::ChipMode chip_mode = {
1216              kV2ChipModeId,
1217              {chip_iface_combination_2}};
1218          modes_ = {chip_mode};
1219        } else {
1220          const IWifiChip::ChipMode chip_mode = {
1221            kV2ChipModeId,
1222            {chip_iface_combination_1, chip_iface_combination_2}};
1223          modes_ = {chip_mode};
1224        }
1225    } else {
1226        // V1 Iface combinations for Mode Id = 0. (STA Mode)
1227        const IWifiChip::ChipIfaceCombinationLimit
1228            sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
1229        IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
1230        if (feature_flags_.lock()->isAwareSupported()) {
1231            sta_chip_iface_combination_limit_2 = {
1232                {IfaceType::P2P, IfaceType::NAN}, 1};
1233        } else {
1234            sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
1235        }
1236        const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
1237            {sta_chip_iface_combination_limit_1,
1238             sta_chip_iface_combination_limit_2}};
1239        const IWifiChip::ChipMode sta_chip_mode = {
1240            kV1StaChipModeId, {sta_chip_iface_combination}};
1241        // Iface combinations for Mode Id = 1. (AP Mode)
1242        const IWifiChip::ChipIfaceCombinationLimit
1243            ap_chip_iface_combination_limit = {{IfaceType::AP}, 1};
1244        const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
1245            {ap_chip_iface_combination_limit}};
1246        const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
1247                                                  {ap_chip_iface_combination}};
1248        if (feature_flags_.lock()->isApDisabled()) {
1249          modes_ = {sta_chip_mode};
1250        } else {
1251          modes_ = {sta_chip_mode, ap_chip_mode};
1252        }
1253    }
1254}
1255
1256std::vector<IWifiChip::ChipIfaceCombination>
1257WifiChip::getCurrentModeIfaceCombinations() {
1258    if (!isValidModeId(current_mode_id_)) {
1259        LOG(ERROR) << "Chip not configured in a mode yet";
1260        return {};
1261    }
1262    for (const auto& mode : modes_) {
1263        if (mode.id == current_mode_id_) {
1264            return mode.availableCombinations;
1265        }
1266    }
1267    CHECK(0) << "Expected to find iface combinations for current mode!";
1268    return {};
1269}
1270
1271// Returns a map indexed by IfaceType with the number of ifaces currently
1272// created of the corresponding type.
1273std::map<IfaceType, size_t> WifiChip::getCurrentIfaceCombination() {
1274    std::map<IfaceType, size_t> iface_counts;
1275    iface_counts[IfaceType::AP] = ap_ifaces_.size();
1276    iface_counts[IfaceType::NAN] = nan_ifaces_.size();
1277    iface_counts[IfaceType::P2P] = p2p_ifaces_.size();
1278    iface_counts[IfaceType::STA] = sta_ifaces_.size();
1279    return iface_counts;
1280}
1281
1282// This expands the provided iface combinations to a more parseable
1283// form. Returns a vector of available combinations possible with the number
1284// of ifaces of each type in the combination.
1285// This method is a port of HalDeviceManager.expandIfaceCombos() from framework.
1286std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations(
1287    const IWifiChip::ChipIfaceCombination& combination) {
1288    uint32_t num_expanded_combos = 1;
1289    for (const auto& limit : combination.limits) {
1290        for (uint32_t i = 0; i < limit.maxIfaces; i++) {
1291            num_expanded_combos *= limit.types.size();
1292        }
1293    }
1294
1295    // Allocate the vector of expanded combos and reset all iface counts to 0
1296    // in each combo.
1297    std::vector<std::map<IfaceType, size_t>> expanded_combos;
1298    expanded_combos.resize(num_expanded_combos);
1299    for (auto& expanded_combo : expanded_combos) {
1300        for (const auto type :
1301             {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
1302            expanded_combo[type] = 0;
1303        }
1304    }
1305    uint32_t span = num_expanded_combos;
1306    for (const auto& limit : combination.limits) {
1307        for (uint32_t i = 0; i < limit.maxIfaces; i++) {
1308            span /= limit.types.size();
1309            for (uint32_t k = 0; k < num_expanded_combos; ++k) {
1310                const auto iface_type =
1311                    limit.types[(k / span) % limit.types.size()];
1312                expanded_combos[k][iface_type]++;
1313            }
1314        }
1315    }
1316    return expanded_combos;
1317}
1318
1319bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType(
1320    const std::map<IfaceType, size_t>& combo, IfaceType requested_type) {
1321    const auto current_combo = getCurrentIfaceCombination();
1322
1323    // Check if we have space for 1 more iface of |type| in this combo
1324    for (const auto type :
1325         {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
1326        size_t num_ifaces_needed = current_combo.at(type);
1327        if (type == requested_type) {
1328            num_ifaces_needed++;
1329        }
1330        size_t num_ifaces_allowed = combo.at(type);
1331        if (num_ifaces_needed > num_ifaces_allowed) {
1332            return false;
1333        }
1334    }
1335    return true;
1336}
1337
1338// This method does the following:
1339// a) Enumerate all possible iface combos by expanding the current
1340//    ChipIfaceCombination.
1341// b) Check if the requested iface type can be added to the current mode.
1342bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) {
1343    if (!isValidModeId(current_mode_id_)) {
1344        LOG(ERROR) << "Chip not configured in a mode yet";
1345        return false;
1346    }
1347    const auto combinations = getCurrentModeIfaceCombinations();
1348    for (const auto& combination : combinations) {
1349        const auto expanded_combos = expandIfaceCombinations(combination);
1350        for (const auto& expanded_combo : expanded_combos) {
1351            if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo,
1352                                                              type)) {
1353                return true;
1354            }
1355        }
1356    }
1357    return false;
1358}
1359
1360bool WifiChip::isValidModeId(ChipModeId mode_id) {
1361    for (const auto& mode : modes_) {
1362        if (mode.id == mode_id) {
1363            return true;
1364        }
1365    }
1366    return false;
1367}
1368
1369// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
1370// This is based on the assumption that we'll have a max of 2 concurrent
1371// AP/STA ifaces.
1372std::string WifiChip::allocateApOrStaIfaceName() {
1373    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
1374    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
1375    if (!ap_iface.get() && !sta_iface.get()) {
1376        return getWlan0IfaceName();
1377    }
1378    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
1379    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
1380    if (!ap_iface.get() && !sta_iface.get()) {
1381        return getWlan1IfaceName();
1382    }
1383    // This should never happen. We screwed up somewhere if it did.
1384    CHECK(0) << "wlan0 and wlan1 in use already!";
1385    return {};
1386}
1387
1388bool WifiChip::writeRingbufferFilesInternal() {
1389    if (!removeOldFilesInternal()) {
1390        LOG(ERROR) << "Error occurred while deleting old tombstone files";
1391        return false;
1392    }
1393    // write ringbuffers to file
1394    for (const auto& item : ringbuffer_map_) {
1395        const Ringbuffer& cur_buffer = item.second;
1396        if (cur_buffer.getData().empty()) {
1397            continue;
1398        }
1399        const std::string file_path_raw =
1400            kTombstoneFolderPath + item.first + "XXXXXXXXXX";
1401        const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
1402        if (dump_fd == -1) {
1403            LOG(ERROR) << "create file failed: " << strerror(errno);
1404            return false;
1405        }
1406        unique_fd file_auto_closer(dump_fd);
1407        for (const auto& cur_block : cur_buffer.getData()) {
1408            if (write(dump_fd, cur_block.data(),
1409                      sizeof(cur_block[0]) * cur_block.size()) == -1) {
1410                LOG(ERROR) << "Error writing to file " << strerror(errno);
1411            }
1412        }
1413    }
1414    return true;
1415}
1416
1417}  // namespace implementation
1418}  // namespace V1_2
1419}  // namespace wifi
1420}  // namespace hardware
1421}  // namespace android
1422