blob: 26dd92577f0774de50113244309f8da700bafaa9 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/forensics/feedback/annotations/startup_annotations.h"
#include <fuchsia/sysinfo/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/string.h>
#include <lib/fidl/cpp/synchronous_interface_ptr.h>
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/syscalls.h>
#include "src/developer/forensics/feedback/annotations/constants.h"
#include "src/developer/forensics/feedback/constants.h"
#include "src/developer/forensics/feedback/reboot_log/annotations.h"
#include "src/developer/forensics/utils/time.h"
#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/trim.h"
namespace forensics::feedback {
namespace {
using FormatFn = fit::function<std::optional<std::string>(std::string_view)>;
std::optional<std::string> IdentityFn(const std::string_view s) { return std::string(s); }
ErrorOrString ReadAnnotation(const std::string& filepath, FormatFn format = IdentityFn) {
std::string content;
if (!files::ReadFileToString(filepath, &content)) {
FX_LOGS(WARNING) << "Failed to read content from " << filepath;
return ErrorOrString(Error::kFileReadFailure);
}
const std::optional<std::string> formatted = format(content);
if (!formatted.has_value()) {
FX_LOGS(WARNING) << "Failed to formatted content from " << filepath;
return ErrorOrString(Error::kBadValue);
}
return ErrorOrString(std::string(fxl::TrimString(*formatted, "\r\n")));
}
ErrorOrString ReadAnnotationWithFallback(const std::string& filepath,
const std::string& fallback_filepath) {
std::string content;
if (!files::ReadFileToString(filepath, &content)) {
FX_LOGS(WARNING) << "Failed to read content from " << filepath;
return ReadAnnotation(fallback_filepath);
}
return ErrorOrString(std::string(fxl::TrimString(content, "\r\n")));
}
ErrorOrString BoardName() {
fuchsia::sysinfo::SysInfoSyncPtr sysinfo;
if (const zx_status_t status = fdio_service_connect("/svc/fuchsia.sysinfo.SysInfo",
sysinfo.NewRequest().TakeChannel().release());
status != ZX_OK) {
FX_PLOGS(ERROR, status) << "Error connecting to sysinfo";
return ErrorOrString(Error::kConnectionError);
}
::fidl::StringPtr out_board_name;
zx_status_t out_status;
if (const zx_status_t status = sysinfo->GetBoardName(&out_status, &out_board_name);
status != ZX_OK) {
FX_PLOGS(ERROR, status) << "Failed to get device board name";
return ErrorOrString(Error::kConnectionError);
}
if (out_status != ZX_OK) {
FX_PLOGS(ERROR, out_status) << "Failed to get device board name";
return ErrorOrString(Error::kBadValue);
}
if (!out_board_name) {
FX_PLOGS(ERROR, out_status) << "Failed to get device board name";
return ErrorOrString(Error::kMissingValue);
}
return ErrorOrString(out_board_name.value());
}
std::string IsDebug() {
#ifndef NDEBUG
return "true";
#else
return "false";
#endif
}
std::string NumCPUs() { return std::to_string(zx_system_get_num_cpus()); }
} // namespace
Annotations GetStartupAnnotations(const RebootLog& reboot_log,
const SpontaneousRebootReason spontaneous_reboot_reason) {
return {
{kBuildBoardKey, ReadAnnotation(kBuildBoardPath)},
{kBuildProductKey, ReadAnnotation(kBuildProductPath)},
{kBuildLatestCommitDateKey, ReadAnnotation(kBuildCommitDatePath)},
{kBuildPlatformBackstopKey, ReadAnnotation(kBuildMinUtcStampPath, FormatSecondsSinceEpoch)},
{kBuildVersionKey, ReadAnnotation(kCurrentBuildVersionPath)},
{kBuildVersionPreviousBootKey, ReadAnnotation(kPreviousBuildVersionPath)},
{kBuildPlatformVersionKey, ReadAnnotation(kCurrentBuildPlatformVersionPath)},
{kBuildPlatformVersionPreviousBootKey, ReadAnnotation(kPreviousBuildPlatformVersionPath)},
{kBuildProductVersionKey, ReadAnnotation(kCurrentBuildProductVersionPath)},
{kBuildProductVersionPreviousBootKey,
ReadAnnotationWithFallback(kPreviousBuildProductVersionPath, kPreviousBuildVersionPath)},
{kBuildIsDebugKey, ErrorOrString(IsDebug())},
{kDeviceBoardNameKey, BoardName()},
{kDeviceNumCPUsKey, ErrorOrString(NumCPUs())},
{kSystemBootIdCurrentKey, ReadAnnotation(kCurrentBootIdPath)},
{kSystemBootIdPreviousKey, ReadAnnotation(kPreviousBootIdPath)},
{kSystemLastRebootReasonKey,
ErrorOrString(LastRebootReasonAnnotation(reboot_log.GetFinalShutdownInfo(),
spontaneous_reboot_reason))},
{kSystemLastRebootRuntimeKey, LastRebootRuntimeAnnotation(reboot_log)},
{kSystemLastRebootTotalSuspendedTimeKey, LastRebootTotalSuspendedTimeAnnotation(reboot_log)},
{kSystemLastRebootUptimeKey, LastRebootUptimeAnnotation(reboot_log)},
{kSystemLastShutdownGracefulActionKey,
LastShutdownGracefulActionAnnotation(reboot_log.GetFinalShutdownInfo())},
};
}
} // namespace forensics::feedback