blob: 8f79392a128f4c040349e78964d23b5773a5f043 [file] [log] [blame] [edit]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "debugd/src/bluetooth_utils.h"
#include <stdio.h>
#include <string>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/functional/bind.h>
#include <base/functional/callback_helpers.h>
#include <base/logging.h>
#include <brillo/files/file_util.h>
#include <brillo/process/process.h>
#include "debugd/src/sandboxed_process.h"
namespace debugd {
namespace {
constexpr char kBunzip2Command[] = "/bin/bunzip2";
constexpr char kBtmonCommand[] = "/usr/bin/btmon";
constexpr char kBtclientCommand[] = "/usr/bin/btclient";
constexpr char btsnoop_infile[] = "/var/log/bluetooth/log.bz2";
constexpr char btsnoop_outfile[] = "/var/log/bluetooth/log";
// The bluetooth_quality_report file is a standalone file and is not part of
// the system_logs. This report file is only generated if a user logs in
// with a Google account. The file would not be attached by the chrome unless
// the Googler opts in to "Attach Bluetooth Logs" in the feedback UI.
constexpr char report_file[] = "/var/log/bluetooth/bluetooth_quality_report";
constexpr char BQR_UNAVAILABLE[] = "; Bluetooth quality report unavailable";
} // namespace
void GetBluetoothBqr() {
int ret;
if (!base::PathExists(base::FilePath(btsnoop_infile))) {
PLOG(WARNING) << "The btsnoop file does not exist: " << btsnoop_infile
<< BQR_UNAVAILABLE;
return;
}
// Remove btsnoop_outfile at exit.
base::ScopedClosureRunner delete_outfile(
base::BindOnce(base::IgnoreResult(&brillo::DeleteFile),
base::FilePath(btsnoop_outfile)));
// The process is used to decompress the Bluetooth log.
// - input: btsnoop_infile
// - output: btsnoop_outfile
// Note: kBunzip2Command has been sandboxed so ProcessImpl is employed.
brillo::ProcessImpl p;
p.AddArg(kBunzip2Command);
p.AddArg("--keep");
p.AddArg("--force");
p.AddArg(btsnoop_infile);
ret = p.Run();
if (ret) {
PLOG(WARNING) << "Failed to decompress " << btsnoop_infile
<< BQR_UNAVAILABLE;
return;
}
// The process is used to create the summary report.
// - input: btsnoop_outfile
// - output: report_file
// Note: this process should be sandboxed.
SandboxedProcess sp;
sp.SandboxAs("bluetooth", "bluetooth");
sp.AddArg(kBtmonCommand);
sp.AddArg("--analyze");
sp.AddArg(btsnoop_outfile);
sp.RedirectUsingFile(STDOUT_FILENO, base::FilePath(report_file));
ret = sp.Run();
if (ret) {
PLOG(WARNING) << "Failed to btmon analyze " << btsnoop_outfile
<< BQR_UNAVAILABLE;
return;
}
// The process is used to create the Bluetooth media log.
// - input: the "media log" command argument
// - output: memory
// Note: this process should be sandboxed.
SandboxedProcess sp2;
sp2.SandboxAs("bluetooth", "bluetooth");
sp2.AddArg(kBtclientCommand);
sp2.AddArg("--command");
sp2.AddArg("media log");
// Set timeout to 1 second.
sp2.AddArg("--timeout");
sp2.AddArg("1");
sp2.RedirectUsingMemory(STDOUT_FILENO);
ret = sp2.Run();
if (ret) {
PLOG(WARNING) << "Failed to get the btclient media log";
return;
}
// Append the media log to bluetooth quality report.
std::string media_log = sp2.GetOutputString(STDOUT_FILENO);
if (!base::AppendToFile(base::FilePath(report_file), media_log)) {
PLOG(WARNING) << "Failed to append media log to bluetooth quality report";
}
}
} // namespace debugd