1use anyhow::Error;
6use fidl_fuchsia_feedback::{LastRebootInfoProviderMarker, RebootReason};
7use fuchsia_component::client::connect_to_protocol_sync;
8use log::{debug, info};
9
10const LRIP_FIDL_TIMEOUT: zx::MonotonicDuration = zx::MonotonicDuration::INFINITE;
12
13pub fn get_android_bootreason() -> Result<&'static str, Error> {
15 info!("Converting LastRebootInfo to an android-friendly bootreason.");
16 let reboot_info_proxy = connect_to_protocol_sync::<LastRebootInfoProviderMarker>()?;
17 let deadline = zx::MonotonicInstant::after(LRIP_FIDL_TIMEOUT);
18 let reboot_info = reboot_info_proxy.get(deadline)?;
19
20 match reboot_info.reason {
21 Some(RebootReason::Unknown) => return Ok("reboot,unknown"),
22 Some(RebootReason::Cold) => return Ok("reboot,cold"),
23 Some(RebootReason::BriefPowerLoss) => return Ok("reboot,hard_reset"),
24 Some(RebootReason::Brownout) => return Ok("reboot,undervoltage"),
25 Some(RebootReason::KernelPanic) => return Ok("kernel_panic"),
26 Some(RebootReason::SystemOutOfMemory) => return Ok("kernel_panic,oom"),
27 Some(RebootReason::HardwareWatchdogTimeout) => return Ok("watchdog"),
28 Some(RebootReason::SoftwareWatchdogTimeout) => return Ok("watchdog,sw"),
29 Some(RebootReason::RootJobTermination) => return Ok("kernel_panic"),
30 Some(RebootReason::UserRequest) => return Ok("reboot,userrequested"),
31 Some(RebootReason::DeveloperRequest) => return Ok("reboot,shell"),
32 Some(RebootReason::RetrySystemUpdate) => return Ok("reboot,ota"),
33 Some(RebootReason::HighTemperature) => return Ok("shutdown,thermal"),
34 Some(RebootReason::SessionFailure) => return Ok("kernel_panic"),
35 Some(RebootReason::SysmgrFailure) => return Ok("kernel_panic"),
36 Some(RebootReason::FactoryDataReset) => return Ok("reboot,factory_reset"),
37 Some(RebootReason::CriticalComponentFailure) => return Ok("kernel_panic"),
38 Some(RebootReason::ZbiSwap) => return Ok("reboot,normal"),
39 Some(RebootReason::SystemUpdate) => return Ok("reboot,ota"),
40 Some(RebootReason::NetstackMigration) => return Ok("reboot,normal"),
41 Some(RebootReason::AndroidUnexpectedReason) => return Ok("reboot,normal"),
42 Some(RebootReason::AndroidRescueParty) => return Ok("reboot,rescueparty"),
43 Some(RebootReason::AndroidCriticalProcessFailure) => return Ok("reboot,userspace_failed"),
44 Some(RebootReason::__SourceBreaking { .. }) => return Ok("reboot,normal"),
45 None => return Ok("reboot,unknown"),
46 }
47}
48
49fn get_reboot_reason() -> Option<u16> {
51 let reboot_info_proxy = connect_to_protocol_sync::<LastRebootInfoProviderMarker>().ok();
52 let deadline = zx::MonotonicInstant::after(LRIP_FIDL_TIMEOUT);
53 let reboot_info = reboot_info_proxy?.get(deadline);
54 match reboot_info {
55 Ok(info) => match info.reason {
56 Some(r) => Some(r.into_primitive()),
57 None => {
58 info!("Failed to get the reboot reason.");
59 Some(RebootReason::unknown().into_primitive())
60 }
61 },
62 Err(e) => {
63 info!("Failed to get the reboot info: {:?}", e);
64 Some(RebootReason::unknown().into_primitive())
65 }
66 }
67}
68
69pub fn get_console_ramoops() -> Option<Vec<u8>> {
74 debug!("Getting console-ramoops contents");
75 match get_android_bootreason() {
76 Ok(reason) => match reason {
77 "kernel_panic" | "watchdog" | "watchdog,sw" => {
78 Some(format!("Last Reboot Reason: {}\n", get_reboot_reason()?).as_bytes().to_vec())
79 }
81 _ => None,
82 },
83 Err(e) => {
84 info!("Failed to get android bootreason for console_ramoops: {:?}", e);
85 None
86 }
87 }
88}