wifi: Enhance tombstone folder dumping behavior
In current implementation, files in the tombstone folder are only archived when there is at least one active wifi interface. The examination is unnecessary and it causes problems for us to get wifi logs if reporter takes bugreport with STA/SAP off. In this change, tombstone files will be archived regardless of the state of the wifi interfaces. Bug: 303429585 Test: dumpsys android.hardware.wifi.IWifi/default Change-Id: I8a8b09f6473b2a1f93478b0393963e87b1fb9ad7
This commit is contained in:
parent
cfc6b2260a
commit
802828f461
2 changed files with 147 additions and 147 deletions
|
@ -18,14 +18,151 @@
|
|||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#include "aidl_return_util.h"
|
||||
#include "aidl_sync_util.h"
|
||||
#include "wifi_status_util.h"
|
||||
|
||||
namespace {
|
||||
using android::base::unique_fd;
|
||||
|
||||
// Starting Chip ID, will be assigned to primary chip
|
||||
static constexpr int32_t kPrimaryChipId = 0;
|
||||
constexpr char kCpioMagic[] = "070701";
|
||||
constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
|
||||
|
||||
// Helper function for |cpioArchiveFilesInDir|
|
||||
bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
|
||||
const int buf_size = 32 * 1024;
|
||||
std::array<char, buf_size> read_buf;
|
||||
ssize_t llen = snprintf(
|
||||
read_buf.data(), buf_size, "%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.data(), llen < buf_size ? llen : buf_size - 1) == -1) {
|
||||
PLOG(ERROR) << "Error writing cpio header to file " << file_name;
|
||||
return false;
|
||||
}
|
||||
if (write(out_fd, file_name, file_name_len) == -1) {
|
||||
PLOG(ERROR) << "Error writing filename to file " << file_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
PLOG(ERROR) << "Error padding 0s to file " << file_name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function for |cpioArchiveFilesInDir|
|
||||
size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
|
||||
// writing content of file
|
||||
std::array<char, 32 * 1024> read_buf;
|
||||
ssize_t llen = st.st_size;
|
||||
size_t n_error = 0;
|
||||
while (llen > 0) {
|
||||
ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
|
||||
if (bytes_read == -1) {
|
||||
PLOG(ERROR) << "Error reading file";
|
||||
return ++n_error;
|
||||
}
|
||||
llen -= bytes_read;
|
||||
if (write(out_fd, read_buf.data(), bytes_read) == -1) {
|
||||
PLOG(ERROR) << "Error writing data to file";
|
||||
return ++n_error;
|
||||
}
|
||||
if (bytes_read == 0) { // this should never happen, but just in case
|
||||
// to unstuck from while loop
|
||||
PLOG(ERROR) << "Unexpected read result";
|
||||
n_error++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
llen = st.st_size % 4;
|
||||
if (llen != 0) {
|
||||
const uint32_t zero = 0;
|
||||
if (write(out_fd, &zero, 4 - llen) == -1) {
|
||||
PLOG(ERROR) << "Error padding 0s to file";
|
||||
return ++n_error;
|
||||
}
|
||||
}
|
||||
return n_error;
|
||||
}
|
||||
|
||||
// Helper function for |cpioArchiveFilesInDir|
|
||||
bool cpioWriteFileTrailer(int out_fd) {
|
||||
const int buf_size = 4096;
|
||||
std::array<char, buf_size> read_buf;
|
||||
read_buf.fill(0);
|
||||
ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0);
|
||||
if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) {
|
||||
PLOG(ERROR) << "Error writing trailing bytes";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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 cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
|
||||
struct dirent* dp;
|
||||
size_t n_error = 0;
|
||||
std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
|
||||
if (!dir_dump) {
|
||||
PLOG(ERROR) << "Failed to open directory";
|
||||
return ++n_error;
|
||||
}
|
||||
while ((dp = readdir(dir_dump.get()))) {
|
||||
if (dp->d_type != DT_REG) {
|
||||
continue;
|
||||
}
|
||||
std::string cur_file_name(dp->d_name);
|
||||
struct stat st;
|
||||
const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
|
||||
if (stat(cur_file_path.c_str(), &st) == -1) {
|
||||
PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
|
||||
n_error++;
|
||||
continue;
|
||||
}
|
||||
const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
|
||||
if (fd_read == -1) {
|
||||
PLOG(ERROR) << "Failed to open file " << cur_file_path;
|
||||
n_error++;
|
||||
continue;
|
||||
}
|
||||
std::string file_name_with_last_modified_time =
|
||||
cur_file_name + "-" + std::to_string(st.st_mtime);
|
||||
// string.size() does not include the null terminator. The cpio FreeBSD
|
||||
// file header expects the null character to be included in the length.
|
||||
const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
|
||||
unique_fd file_auto_closer(fd_read);
|
||||
if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
|
||||
file_name_len)) {
|
||||
return ++n_error;
|
||||
}
|
||||
size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
|
||||
if (write_error) {
|
||||
return n_error + write_error;
|
||||
}
|
||||
}
|
||||
if (!cpioWriteFileTrailer(out_fd)) {
|
||||
return ++n_error;
|
||||
}
|
||||
return n_error;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace aidl {
|
||||
|
@ -83,16 +220,18 @@ ndk::ScopedAStatus Wifi::getChip(int32_t in_chipId, std::shared_ptr<IWifiChip>*
|
|||
binder_status_t Wifi::dump(int fd, const char** args, uint32_t numArgs) {
|
||||
const auto lock = acquireGlobalLock();
|
||||
LOG(INFO) << "-----------Debug was called----------------";
|
||||
if (chips_.size() == 0) {
|
||||
LOG(INFO) << "No chips to display.";
|
||||
return STATUS_OK;
|
||||
if (chips_.size() != 0) {
|
||||
for (std::shared_ptr<WifiChip> chip : chips_) {
|
||||
if (!chip.get()) continue;
|
||||
chip->dump(fd, args, numArgs);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::shared_ptr<WifiChip> chip : chips_) {
|
||||
if (!chip.get()) continue;
|
||||
chip->dump(fd, args, numArgs);
|
||||
uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
|
||||
if (n_error != 0) {
|
||||
LOG(ERROR) << n_error << " errors occurred in cpio function";
|
||||
}
|
||||
::android::base::WriteStringToFd("\n", fd);
|
||||
fsync(fd);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,13 +32,8 @@
|
|||
#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
|
||||
|
||||
namespace {
|
||||
using aidl::android::hardware::wifi::IfaceType;
|
||||
using aidl::android::hardware::wifi::IWifiChip;
|
||||
using CoexRestriction = aidl::android::hardware::wifi::IWifiChip::CoexRestriction;
|
||||
using ChannelCategoryMask = aidl::android::hardware::wifi::IWifiChip::ChannelCategoryMask;
|
||||
using android::base::unique_fd;
|
||||
|
||||
constexpr char kCpioMagic[] = "070701";
|
||||
constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3;
|
||||
constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
|
||||
constexpr uint32_t kMaxRingBufferFileNum = 20;
|
||||
|
@ -215,135 +210,6 @@ bool removeOldFilesInternal() {
|
|||
return success;
|
||||
}
|
||||
|
||||
// Helper function for |cpioArchiveFilesInDir|
|
||||
bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
|
||||
const int buf_size = 32 * 1024;
|
||||
std::array<char, buf_size> read_buf;
|
||||
ssize_t llen = snprintf(
|
||||
read_buf.data(), buf_size, "%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.data(), llen < buf_size ? llen : buf_size - 1) == -1) {
|
||||
PLOG(ERROR) << "Error writing cpio header to file " << file_name;
|
||||
return false;
|
||||
}
|
||||
if (write(out_fd, file_name, file_name_len) == -1) {
|
||||
PLOG(ERROR) << "Error writing filename to file " << file_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
PLOG(ERROR) << "Error padding 0s to file " << file_name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function for |cpioArchiveFilesInDir|
|
||||
size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
|
||||
// writing content of file
|
||||
std::array<char, 32 * 1024> read_buf;
|
||||
ssize_t llen = st.st_size;
|
||||
size_t n_error = 0;
|
||||
while (llen > 0) {
|
||||
ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
|
||||
if (bytes_read == -1) {
|
||||
PLOG(ERROR) << "Error reading file";
|
||||
return ++n_error;
|
||||
}
|
||||
llen -= bytes_read;
|
||||
if (write(out_fd, read_buf.data(), bytes_read) == -1) {
|
||||
PLOG(ERROR) << "Error writing data to file";
|
||||
return ++n_error;
|
||||
}
|
||||
if (bytes_read == 0) { // this should never happen, but just in case
|
||||
// to unstuck from while loop
|
||||
PLOG(ERROR) << "Unexpected read result";
|
||||
n_error++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
llen = st.st_size % 4;
|
||||
if (llen != 0) {
|
||||
const uint32_t zero = 0;
|
||||
if (write(out_fd, &zero, 4 - llen) == -1) {
|
||||
PLOG(ERROR) << "Error padding 0s to file";
|
||||
return ++n_error;
|
||||
}
|
||||
}
|
||||
return n_error;
|
||||
}
|
||||
|
||||
// Helper function for |cpioArchiveFilesInDir|
|
||||
bool cpioWriteFileTrailer(int out_fd) {
|
||||
const int buf_size = 4096;
|
||||
std::array<char, buf_size> read_buf;
|
||||
read_buf.fill(0);
|
||||
ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0);
|
||||
if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) {
|
||||
PLOG(ERROR) << "Error writing trailing bytes";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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 cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
|
||||
struct dirent* dp;
|
||||
size_t n_error = 0;
|
||||
std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
|
||||
if (!dir_dump) {
|
||||
PLOG(ERROR) << "Failed to open directory";
|
||||
return ++n_error;
|
||||
}
|
||||
while ((dp = readdir(dir_dump.get()))) {
|
||||
if (dp->d_type != DT_REG) {
|
||||
continue;
|
||||
}
|
||||
std::string cur_file_name(dp->d_name);
|
||||
struct stat st;
|
||||
const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
|
||||
if (stat(cur_file_path.c_str(), &st) == -1) {
|
||||
PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
|
||||
n_error++;
|
||||
continue;
|
||||
}
|
||||
const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
|
||||
if (fd_read == -1) {
|
||||
PLOG(ERROR) << "Failed to open file " << cur_file_path;
|
||||
n_error++;
|
||||
continue;
|
||||
}
|
||||
std::string file_name_with_last_modified_time =
|
||||
cur_file_name + "-" + std::to_string(st.st_mtime);
|
||||
// string.size() does not include the null terminator. The cpio FreeBSD
|
||||
// file header expects the null character to be included in the length.
|
||||
const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
|
||||
unique_fd file_auto_closer(fd_read);
|
||||
if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
|
||||
file_name_len)) {
|
||||
return ++n_error;
|
||||
}
|
||||
size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
|
||||
if (write_error) {
|
||||
return n_error + write_error;
|
||||
}
|
||||
}
|
||||
if (!cpioWriteFileTrailer(out_fd)) {
|
||||
return ++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);
|
||||
|
@ -651,7 +517,7 @@ ndk::ScopedAStatus WifiChip::setLatencyMode(IWifiChip::LatencyMode in_mode) {
|
|||
&WifiChip::setLatencyModeInternal, in_mode);
|
||||
}
|
||||
|
||||
binder_status_t WifiChip::dump(int fd, const char**, uint32_t) {
|
||||
binder_status_t WifiChip::dump(int fd __unused, const char**, uint32_t) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(lock_t);
|
||||
for (const auto& item : ringbuffer_map_) {
|
||||
|
@ -664,11 +530,6 @@ binder_status_t WifiChip::dump(int fd, const char**, uint32_t) {
|
|||
if (!writeRingbufferFilesInternal()) {
|
||||
LOG(ERROR) << "Error writing files to flash";
|
||||
}
|
||||
uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
|
||||
if (n_error != 0) {
|
||||
LOG(ERROR) << n_error << " errors occurred in cpio function";
|
||||
}
|
||||
fsync(fd);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue