mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 10:44:41 +00:00
Merge "move ringbuffer interactions to wifi hal"
This commit is contained in:
committed by
Android (Google) Code Review
commit
84a51275b5
@@ -30,6 +30,7 @@ endif
|
||||
LOCAL_SRC_FILES := \
|
||||
hidl_struct_util.cpp \
|
||||
hidl_sync_util.cpp \
|
||||
ringbuffer.cpp \
|
||||
wifi.cpp \
|
||||
wifi_ap_iface.cpp \
|
||||
wifi_chip.cpp \
|
||||
@@ -97,6 +98,7 @@ LOCAL_SRC_FILES := \
|
||||
tests/mock_wifi_feature_flags.cpp \
|
||||
tests/mock_wifi_legacy_hal.cpp \
|
||||
tests/mock_wifi_mode_controller.cpp \
|
||||
tests/ringbuffer_unit_tests.cpp \
|
||||
tests/wifi_chip_unit_tests.cpp
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libgmock \
|
||||
|
||||
47
wifi/1.2/default/ringbuffer.cpp
Normal file
47
wifi/1.2/default/ringbuffer.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ringbuffer.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
|
||||
Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
|
||||
|
||||
void Ringbuffer::append(const std::vector<uint8_t>& input) {
|
||||
if (input.size() == 0) {
|
||||
return;
|
||||
}
|
||||
data_.push_back(input);
|
||||
size_ += input.size() * sizeof(input[0]);
|
||||
while (size_ > maxSize_) {
|
||||
size_ -= data_.front().size() * sizeof(data_.front()[0]);
|
||||
data_.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const {
|
||||
return data_;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
53
wifi/1.2/default/ringbuffer.h
Normal file
53
wifi/1.2/default/ringbuffer.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef RINGBUFFER_H_
|
||||
#define RINGBUFFER_H_
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
|
||||
/**
|
||||
* Ringbuffer object used to store debug data.
|
||||
*/
|
||||
class Ringbuffer {
|
||||
public:
|
||||
explicit Ringbuffer(size_t maxSize);
|
||||
|
||||
// Appends the data buffer and deletes from the front until buffer is
|
||||
// within |maxSize_|.
|
||||
void append(const std::vector<uint8_t>& input);
|
||||
const std::list<std::vector<uint8_t>>& getData() const;
|
||||
|
||||
private:
|
||||
std::list<std::vector<uint8_t>> data_;
|
||||
size_t size_;
|
||||
size_t maxSize_;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // RINGBUFFER_H_
|
||||
88
wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
Normal file
88
wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2018, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "ringbuffer.h"
|
||||
|
||||
using testing::Return;
|
||||
using testing::Test;
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
|
||||
class RingbufferTest : public Test {
|
||||
public:
|
||||
const uint32_t maxBufferSize_ = 10;
|
||||
Ringbuffer buffer_{maxBufferSize_};
|
||||
};
|
||||
|
||||
TEST_F(RingbufferTest, CreateEmptyBuffer) {
|
||||
ASSERT_TRUE(buffer_.getData().empty());
|
||||
}
|
||||
|
||||
TEST_F(RingbufferTest, CanUseFullBufferCapacity) {
|
||||
const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
|
||||
const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
|
||||
buffer_.append(input);
|
||||
buffer_.append(input2);
|
||||
ASSERT_EQ(2u, buffer_.getData().size());
|
||||
EXPECT_EQ(input, buffer_.getData().front());
|
||||
EXPECT_EQ(input2, buffer_.getData().back());
|
||||
}
|
||||
|
||||
TEST_F(RingbufferTest, OldDataIsRemovedOnOverflow) {
|
||||
const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
|
||||
const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
|
||||
const std::vector<uint8_t> input3 = {'G'};
|
||||
buffer_.append(input);
|
||||
buffer_.append(input2);
|
||||
buffer_.append(input3);
|
||||
ASSERT_EQ(2u, buffer_.getData().size());
|
||||
EXPECT_EQ(input2, buffer_.getData().front());
|
||||
EXPECT_EQ(input3, buffer_.getData().back());
|
||||
}
|
||||
|
||||
TEST_F(RingbufferTest, MultipleOldDataIsRemovedOnOverflow) {
|
||||
const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
|
||||
const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
|
||||
const std::vector<uint8_t> input3(maxBufferSize_, '2');
|
||||
buffer_.append(input);
|
||||
buffer_.append(input2);
|
||||
buffer_.append(input3);
|
||||
ASSERT_EQ(1u, buffer_.getData().size());
|
||||
EXPECT_EQ(input3, buffer_.getData().front());
|
||||
}
|
||||
|
||||
TEST_F(RingbufferTest, AppendingEmptyBufferDoesNotAddGarbage) {
|
||||
const std::vector<uint8_t> input = {};
|
||||
buffer_.append(input);
|
||||
ASSERT_TRUE(buffer_.getData().empty());
|
||||
}
|
||||
|
||||
TEST_F(RingbufferTest, OversizedAppendIsDropped) {
|
||||
const std::vector<uint8_t> input(maxBufferSize_ + 1, '0');
|
||||
buffer_.append(input);
|
||||
ASSERT_TRUE(buffer_.getData().empty());
|
||||
}
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -77,6 +77,12 @@ Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
|
||||
&Wifi::getChipInternal, hidl_status_cb, chip_id);
|
||||
}
|
||||
|
||||
Return<void> Wifi::debug(const hidl_handle& handle,
|
||||
const hidl_vec<hidl_string>&) {
|
||||
LOG(INFO) << "-----------Debug is called----------------";
|
||||
return chip_->debug(handle, {});
|
||||
}
|
||||
|
||||
WifiStatus Wifi::registerEventCallbackInternal(
|
||||
const sp<IWifiEventCallback>& event_callback) {
|
||||
if (!event_cb_handler_.addCallback(event_callback)) {
|
||||
|
||||
@@ -56,6 +56,8 @@ class Wifi : public V1_2::IWifi {
|
||||
Return<void> stop(stop_cb hidl_status_cb) override;
|
||||
Return<void> getChipIds(getChipIds_cb hidl_status_cb) override;
|
||||
Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override;
|
||||
Return<void> debug(const hidl_handle& handle,
|
||||
const hidl_vec<hidl_string>& options) override;
|
||||
|
||||
private:
|
||||
enum class RunState { STOPPED, STARTED, STOPPING };
|
||||
|
||||
@@ -14,8 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#include "hidl_return_util.h"
|
||||
#include "hidl_struct_util.h"
|
||||
@@ -23,6 +28,7 @@
|
||||
#include "wifi_status_util.h"
|
||||
|
||||
namespace {
|
||||
using android::base::unique_fd;
|
||||
using android::hardware::hidl_string;
|
||||
using android::hardware::hidl_vec;
|
||||
using android::hardware::wifi::V1_0::ChipModeId;
|
||||
@@ -39,6 +45,11 @@ constexpr ChipModeId kV1ApChipModeId = 1;
|
||||
// Mode ID for V2
|
||||
constexpr ChipModeId kV2ChipModeId = 2;
|
||||
|
||||
constexpr char kCpioMagic[] = "070701";
|
||||
constexpr size_t kMaxBufferSizeBytes = 1024 * 1024;
|
||||
constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60;
|
||||
constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
|
||||
|
||||
template <typename Iface>
|
||||
void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
|
||||
iface->invalidate();
|
||||
@@ -93,6 +104,165 @@ std::string getP2pIfaceName() {
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
// delete files older than a predefined time in the wifi tombstone dir
|
||||
bool removeOldFilesInternal() {
|
||||
time_t now = time(0);
|
||||
const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
|
||||
DIR* dir_dump = opendir(kTombstoneFolderPath);
|
||||
if (!dir_dump) {
|
||||
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
|
||||
return false;
|
||||
}
|
||||
unique_fd dir_auto_closer(dirfd(dir_dump));
|
||||
struct dirent* dp;
|
||||
bool success = true;
|
||||
while ((dp = readdir(dir_dump))) {
|
||||
if (dp->d_type != DT_REG) {
|
||||
continue;
|
||||
}
|
||||
std::string cur_file_name(dp->d_name);
|
||||
struct stat cur_file_stat;
|
||||
std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
|
||||
if (stat(cur_file_path.c_str(), &cur_file_stat) != -1) {
|
||||
if (cur_file_stat.st_mtime < delete_files_before) {
|
||||
if (unlink(cur_file_path.c_str()) != 0) {
|
||||
LOG(ERROR) << "Error deleting file " << strerror(errno);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to get file stat for " << cur_file_path
|
||||
<< ": " << strerror(errno);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// Archives all files in |input_dir| and writes result into |out_fd|
|
||||
// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
|
||||
// portion
|
||||
size_t cpioFilesInDir(int out_fd, const char* input_dir) {
|
||||
struct dirent* dp;
|
||||
size_t n_error = 0;
|
||||
char read_buf[32 * 1024];
|
||||
DIR* dir_dump = opendir(input_dir);
|
||||
if (!dir_dump) {
|
||||
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
|
||||
n_error++;
|
||||
return n_error;
|
||||
}
|
||||
unique_fd dir_auto_closer(dirfd(dir_dump));
|
||||
while ((dp = readdir(dir_dump))) {
|
||||
if (dp->d_type != DT_REG) {
|
||||
continue;
|
||||
}
|
||||
std::string cur_file_name(dp->d_name);
|
||||
const size_t file_name_len =
|
||||
cur_file_name.size() + 1; // string.size() does not include the
|
||||
// null terminator. The cpio FreeBSD file
|
||||
// header expects the null character to
|
||||
// be included in the length.
|
||||
struct stat st;
|
||||
ssize_t llen;
|
||||
const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
|
||||
if (stat(cur_file_path.c_str(), &st) != -1) {
|
||||
const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
|
||||
unique_fd file_auto_closer(fd_read);
|
||||
if (fd_read == -1) {
|
||||
LOG(ERROR) << "Failed to read file " << cur_file_path << " "
|
||||
<< strerror(errno);
|
||||
n_error++;
|
||||
continue;
|
||||
}
|
||||
llen = sprintf(
|
||||
read_buf,
|
||||
"%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
|
||||
kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
|
||||
st.st_gid, static_cast<int>(st.st_nlink),
|
||||
static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
|
||||
major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
|
||||
minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
|
||||
if (write(out_fd, read_buf, llen) == -1) {
|
||||
LOG(ERROR) << "Error writing cpio header to file "
|
||||
<< cur_file_path << " " << strerror(errno);
|
||||
n_error++;
|
||||
return n_error;
|
||||
}
|
||||
if (write(out_fd, cur_file_name.c_str(), file_name_len) == -1) {
|
||||
LOG(ERROR) << "Error writing filename to file " << cur_file_path
|
||||
<< " " << strerror(errno);
|
||||
n_error++;
|
||||
return n_error;
|
||||
}
|
||||
|
||||
// NUL Pad header up to 4 multiple bytes.
|
||||
llen = (llen + file_name_len) % 4;
|
||||
if (llen != 0) {
|
||||
const uint32_t zero = 0;
|
||||
if (write(out_fd, &zero, 4 - llen) == -1) {
|
||||
LOG(ERROR) << "Error padding 0s to file " << cur_file_path
|
||||
<< " " << strerror(errno);
|
||||
n_error++;
|
||||
return n_error;
|
||||
}
|
||||
}
|
||||
|
||||
// writing content of file
|
||||
llen = st.st_size;
|
||||
while (llen > 0) {
|
||||
ssize_t bytes_read = read(fd_read, read_buf, sizeof(read_buf));
|
||||
if (bytes_read == -1) {
|
||||
LOG(ERROR) << "Error reading file " << cur_file_path << " "
|
||||
<< strerror(errno);
|
||||
n_error++;
|
||||
return n_error;
|
||||
}
|
||||
llen -= bytes_read;
|
||||
if (write(out_fd, read_buf, bytes_read) == -1) {
|
||||
LOG(ERROR) << "Error writing data to file " << cur_file_path
|
||||
<< " " << strerror(errno);
|
||||
n_error++;
|
||||
return n_error;
|
||||
}
|
||||
if (bytes_read ==
|
||||
0) { // this should never happen, but just in case
|
||||
// to unstuck from while loop
|
||||
LOG(ERROR) << "Unexpected file size for " << cur_file_path
|
||||
<< " " << strerror(errno);
|
||||
n_error++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
llen = st.st_size % 4;
|
||||
if (llen != 0) {
|
||||
const uint32_t zero = 0;
|
||||
write(out_fd, &zero, 4 - llen);
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to get file stat for " << cur_file_path
|
||||
<< ": " << strerror(errno);
|
||||
n_error++;
|
||||
}
|
||||
}
|
||||
memset(read_buf, 0, sizeof(read_buf));
|
||||
if (write(out_fd, read_buf,
|
||||
sprintf(read_buf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0) +
|
||||
4) == -1) {
|
||||
LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
|
||||
n_error++;
|
||||
}
|
||||
return n_error;
|
||||
}
|
||||
|
||||
// Helper function to create a non-const char*.
|
||||
std::vector<char> makeCharVec(const std::string& str) {
|
||||
std::vector<char> vec(str.size() + 1);
|
||||
vec.assign(str.begin(), str.end());
|
||||
vec.push_back('\0');
|
||||
return vec;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace android {
|
||||
@@ -350,6 +520,24 @@ Return<void> WifiChip::resetTxPowerScenario(
|
||||
hidl_status_cb);
|
||||
}
|
||||
|
||||
Return<void> WifiChip::debug(const hidl_handle& handle,
|
||||
const hidl_vec<hidl_string>&) {
|
||||
if (handle != nullptr && handle->numFds >= 1) {
|
||||
int fd = handle->data[0];
|
||||
if (!writeRingbufferFilesInternal()) {
|
||||
LOG(ERROR) << "Error writing files to flash";
|
||||
}
|
||||
uint32_t n_error = cpioFilesInDir(fd, kTombstoneFolderPath);
|
||||
if (n_error != 0) {
|
||||
LOG(ERROR) << n_error << " errors occured in cpio function";
|
||||
}
|
||||
fsync(fd);
|
||||
} else {
|
||||
LOG(ERROR) << "File handle error";
|
||||
}
|
||||
return Void();
|
||||
}
|
||||
|
||||
void WifiChip::invalidateAndRemoveAllIfaces() {
|
||||
invalidateAndClearAll(ap_ifaces_);
|
||||
invalidateAndClearAll(nan_ifaces_);
|
||||
@@ -727,6 +915,8 @@ WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
|
||||
std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
|
||||
verbose_level),
|
||||
max_interval_in_sec, min_data_size_in_bytes);
|
||||
ringbuffer_map_.insert(std::pair<std::string, Ringbuffer>(
|
||||
ring_name, Ringbuffer(kMaxBufferSizeBytes)));
|
||||
return createWifiStatusFromLegacyError(legacy_status);
|
||||
}
|
||||
|
||||
@@ -738,6 +928,7 @@ WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
|
||||
}
|
||||
legacy_hal::wifi_error legacy_status =
|
||||
legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
|
||||
|
||||
return createWifiStatusFromLegacyError(legacy_status);
|
||||
}
|
||||
|
||||
@@ -849,7 +1040,7 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() {
|
||||
|
||||
android::wp<WifiChip> weak_ptr_this(this);
|
||||
const auto& on_ring_buffer_data_callback =
|
||||
[weak_ptr_this](const std::string& /* name */,
|
||||
[weak_ptr_this](const std::string& name,
|
||||
const std::vector<uint8_t>& data,
|
||||
const legacy_hal::wifi_ring_buffer_status& status) {
|
||||
const auto shared_ptr_this = weak_ptr_this.promote();
|
||||
@@ -863,13 +1054,13 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() {
|
||||
LOG(ERROR) << "Error converting ring buffer status";
|
||||
return;
|
||||
}
|
||||
for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
|
||||
if (!callback->onDebugRingBufferDataAvailable(hidl_status, data)
|
||||
.isOk()) {
|
||||
LOG(ERROR)
|
||||
<< "Failed to invoke onDebugRingBufferDataAvailable"
|
||||
<< " callback on: " << toString(callback);
|
||||
}
|
||||
const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
|
||||
if (target != shared_ptr_this->ringbuffer_map_.end()) {
|
||||
Ringbuffer& cur_buffer = target->second;
|
||||
cur_buffer.append(data);
|
||||
} else {
|
||||
LOG(ERROR) << "Ringname " << name << " not found";
|
||||
return;
|
||||
}
|
||||
};
|
||||
legacy_hal::wifi_error legacy_status =
|
||||
@@ -1080,6 +1271,35 @@ std::string WifiChip::allocateApOrStaIfaceName() {
|
||||
return {};
|
||||
}
|
||||
|
||||
bool WifiChip::writeRingbufferFilesInternal() {
|
||||
if (!removeOldFilesInternal()) {
|
||||
LOG(ERROR) << "Error occurred while deleting old tombstone files";
|
||||
return false;
|
||||
}
|
||||
// write ringbuffers to file
|
||||
for (const auto& item : ringbuffer_map_) {
|
||||
const Ringbuffer& cur_buffer = item.second;
|
||||
if (cur_buffer.getData().empty()) {
|
||||
continue;
|
||||
}
|
||||
const std::string file_path_raw =
|
||||
kTombstoneFolderPath + item.first + "XXXXXXXXXX";
|
||||
const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
|
||||
if (dump_fd == -1) {
|
||||
LOG(ERROR) << "create file failed: " << strerror(errno);
|
||||
return false;
|
||||
}
|
||||
unique_fd file_auto_closer(dump_fd);
|
||||
for (const auto& cur_block : cur_buffer.getData()) {
|
||||
if (write(dump_fd, cur_block.data(),
|
||||
sizeof(cur_block[0]) * cur_block.size()) == -1) {
|
||||
LOG(ERROR) << "Error writing to file " << strerror(errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
#ifndef WIFI_CHIP_H_
|
||||
#define WIFI_CHIP_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
#include <android/hardware/wifi/1.2/IWifiChip.h>
|
||||
|
||||
#include "hidl_callback_util.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "wifi_ap_iface.h"
|
||||
#include "wifi_feature_flags.h"
|
||||
#include "wifi_legacy_hal.h"
|
||||
@@ -134,6 +136,8 @@ class WifiChip : public V1_2::IWifiChip {
|
||||
selectTxPowerScenario_cb hidl_status_cb) override;
|
||||
Return<void> resetTxPowerScenario(
|
||||
resetTxPowerScenario_cb hidl_status_cb) override;
|
||||
Return<void> debug(const hidl_handle& handle,
|
||||
const hidl_vec<hidl_string>& options) override;
|
||||
|
||||
private:
|
||||
void invalidateAndRemoveAllIfaces();
|
||||
@@ -204,6 +208,7 @@ class WifiChip : public V1_2::IWifiChip {
|
||||
bool canCurrentModeSupportIfaceOfType(IfaceType type);
|
||||
bool isValidModeId(ChipModeId mode_id);
|
||||
std::string allocateApOrStaIfaceName();
|
||||
bool writeRingbufferFilesInternal();
|
||||
|
||||
ChipId chip_id_;
|
||||
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
|
||||
@@ -214,6 +219,7 @@ class WifiChip : public V1_2::IWifiChip {
|
||||
std::vector<sp<WifiP2pIface>> p2p_ifaces_;
|
||||
std::vector<sp<WifiStaIface>> sta_ifaces_;
|
||||
std::vector<sp<WifiRttController>> rtt_controllers_;
|
||||
std::map<std::string, Ringbuffer> ringbuffer_map_;
|
||||
bool is_valid_;
|
||||
// Members pertaining to chip configuration.
|
||||
uint32_t current_mode_id_;
|
||||
|
||||
Reference in New Issue
Block a user