blob: f370154654308e0cf1dc53279fd8db3c496ae679 [file] [log] [blame] [edit]
// 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/reboot_log/annotations.h"
#include "fuchsia/feedback/cpp/fidl.h"
#include "src/developer/forensics/utils/time.h"
namespace forensics::feedback {
namespace {
std::string GetSpontaneousRebootReason(const SpontaneousRebootReason spontaneous_reboot_reason) {
switch (spontaneous_reboot_reason) {
case SpontaneousRebootReason::kSpontaneous:
return "spontaneous";
case SpontaneousRebootReason::kBriefPowerLoss:
return "brief loss of power";
case SpontaneousRebootReason::kHardReset:
return "hard reset";
}
}
} // namespace
std::string LastRebootReasonAnnotation(const FinalShutdownInfo& final_shutdown_info,
const SpontaneousRebootReason spontaneous_reboot_reason) {
using FuchsiaRebootReason = fuchsia::feedback::RebootReason;
// Define a generic value to use in case conversion fails or the converted value fails to match a
// good value.
std::string generic_value = "unknown";
if (const std::optional<bool> graceful_opt = final_shutdown_info.OptionallyGraceful();
graceful_opt.has_value()) {
generic_value = (graceful_opt.value()) ? "graceful" : "ungraceful";
}
const auto reboot_reason = final_shutdown_info.ToFidlRebootReason();
if (!reboot_reason) {
return generic_value;
}
switch (reboot_reason.value()) {
case FuchsiaRebootReason::COLD:
return "cold";
case FuchsiaRebootReason::BRIEF_POWER_LOSS:
return GetSpontaneousRebootReason(spontaneous_reboot_reason);
case FuchsiaRebootReason::BROWNOUT:
return "brownout";
case FuchsiaRebootReason::KERNEL_PANIC:
return "kernel panic";
case FuchsiaRebootReason::SYSTEM_OUT_OF_MEMORY:
return "system out of memory";
case FuchsiaRebootReason::HARDWARE_WATCHDOG_TIMEOUT:
return "hardware watchdog timeout";
case FuchsiaRebootReason::SOFTWARE_WATCHDOG_TIMEOUT:
return "software watchdog timeout";
case FuchsiaRebootReason::USER_REQUEST:
return "user request";
case FuchsiaRebootReason::SYSTEM_UPDATE:
return "system update";
case FuchsiaRebootReason::RETRY_SYSTEM_UPDATE:
return "retry system update";
case FuchsiaRebootReason::ZBI_SWAP:
return "ZBI swap";
case FuchsiaRebootReason::HIGH_TEMPERATURE:
return "device too hot";
case FuchsiaRebootReason::SESSION_FAILURE:
return "fatal session failure";
case FuchsiaRebootReason::SYSMGR_FAILURE:
return "fatal sysmgr failure";
case FuchsiaRebootReason::CRITICAL_COMPONENT_FAILURE:
return "fatal critical component failure";
case FuchsiaRebootReason::FACTORY_DATA_RESET:
return "factory data reset";
case FuchsiaRebootReason::ROOT_JOB_TERMINATION:
return "root job termination";
case FuchsiaRebootReason::NETSTACK_MIGRATION:
return "netstack migration";
case FuchsiaRebootReason::ANDROID_UNEXPECTED_REASON:
return "android unexpected reason";
case FuchsiaRebootReason::ANDROID_NO_REASON:
return "android no reason";
case FuchsiaRebootReason::ANDROID_RESCUE_PARTY:
return "android rescue party";
case FuchsiaRebootReason::ANDROID_CRITICAL_PROCESS_FAILURE:
return "android critical process failure";
case FuchsiaRebootReason::DEVELOPER_REQUEST:
return "developer request";
default:
return generic_value;
}
}
ErrorOrString LastRebootUptimeAnnotation(const RebootLog& reboot_log) {
if (reboot_log.Uptime().has_value()) {
const auto uptime = FormatDuration(*reboot_log.Uptime());
if (uptime.has_value()) {
return ErrorOrString(*uptime);
}
}
return ErrorOrString(Error::kMissingValue);
}
ErrorOrString LastRebootRuntimeAnnotation(const RebootLog& reboot_log) {
if (reboot_log.Runtime().has_value()) {
const auto runtime = FormatDuration(*reboot_log.Runtime());
if (runtime.has_value()) {
return ErrorOrString(*runtime);
}
}
return ErrorOrString(Error::kMissingValue);
}
ErrorOrString LastRebootTotalSuspendedTimeAnnotation(const RebootLog& reboot_log) {
if (reboot_log.Uptime().has_value() && reboot_log.Runtime().has_value()) {
const std::optional<std::string> suspended_time =
FormatDuration(*reboot_log.Uptime() - *reboot_log.Runtime());
if (suspended_time.has_value()) {
return ErrorOrString(*suspended_time);
}
}
return ErrorOrString(Error::kMissingValue);
}
ErrorOrString LastShutdownGracefulActionAnnotation(const FinalShutdownInfo& final_shutdown_info) {
const std::optional<GracefulShutdownAction> action =
final_shutdown_info.ToGracefulShutdownAction();
if (!action.has_value()) {
return ErrorOrString(Error::kMissingValue);
}
switch (*action) {
case GracefulShutdownAction::kPoweroff:
return ErrorOrString("poweroff");
case GracefulShutdownAction::kReboot:
return ErrorOrString("reboot");
case GracefulShutdownAction::kRebootToRecovery:
return ErrorOrString("reboot to recovery");
case GracefulShutdownAction::kRebootToBootloader:
return ErrorOrString("reboot to bootloader");
case GracefulShutdownAction::kNotSupported:
case GracefulShutdownAction::kNotParseable:
return ErrorOrString(Error::kBadValue);
}
}
} // namespace forensics::feedback