shutdown_shim/
reboot_reasons.rs1use fidl::marker::SourceBreaking;
6use fidl_fuchsia_hardware_power_statecontrol::{
7 self as fpower, RebootReason2, ShutdownAction, ShutdownOptions, ShutdownReason,
8};
9
10#[derive(Debug, PartialEq, PartialOrd, Clone)]
16pub struct ShutdownOptionsWrapper {
17 pub action: ShutdownAction,
18 pub reasons: Vec<ShutdownReason>,
19}
20
21impl ShutdownOptionsWrapper {
22 pub fn new(action: fpower::ShutdownAction, reason: ShutdownReason) -> Self {
24 Self { action, reasons: vec![reason] }
25 }
26
27 pub(crate) fn from_reboot_reason2_deprecated(reasons: &Vec<RebootReason2>) -> Self {
29 let reasons = reasons
30 .iter()
31 .map(|reason| match reason {
32 RebootReason2::UserRequest => ShutdownReason::UserRequest,
33 RebootReason2::DeveloperRequest => ShutdownReason::DeveloperRequest,
34 RebootReason2::SystemUpdate => ShutdownReason::SystemUpdate,
35 RebootReason2::RetrySystemUpdate => ShutdownReason::RetrySystemUpdate,
36 RebootReason2::HighTemperature => ShutdownReason::HighTemperature,
37 RebootReason2::FactoryDataReset => ShutdownReason::FactoryDataReset,
38 RebootReason2::SessionFailure => ShutdownReason::SessionFailure,
39 RebootReason2::SysmgrFailure => {
40 println!(
42 "[shutdown-shim]: error, unexpectedly received RebootReason2::SysmgrFailure"
43 );
44 fpower::ShutdownReason::unknown()
45 }
46 RebootReason2::CriticalComponentFailure => ShutdownReason::CriticalComponentFailure,
47 RebootReason2::ZbiSwap => ShutdownReason::ZbiSwap,
48 RebootReason2::OutOfMemory => ShutdownReason::OutOfMemory,
49 RebootReason2::NetstackMigration => ShutdownReason::NetstackMigration,
50 RebootReason2::AndroidUnexpectedReason => ShutdownReason::AndroidUnexpectedReason,
51 RebootReason2::AndroidRescueParty => ShutdownReason::AndroidRescueParty,
52 RebootReason2::AndroidCriticalProcessFailure => {
53 ShutdownReason::AndroidCriticalProcessFailure
54 }
55 RebootReason2::__SourceBreaking { unknown_ordinal } => {
56 println!("[shutdown-shim]: error, unrecognized RebootReason2 ordinal: {unknown_ordinal}");
57 ShutdownReason::unknown()
58 }
59 })
60 .collect();
61 Self { action: ShutdownAction::Reboot, reasons }
62 }
63
64 pub(crate) fn to_reboot_reason2_deprecated(&self) -> Vec<RebootReason2> {
68 self.reasons
69 .iter()
70 .map(|item| match item {
71 ShutdownReason::UserRequest => RebootReason2::UserRequest,
72 ShutdownReason::UserRequestDeviceStuck => RebootReason2::UserRequest,
73 ShutdownReason::DeveloperRequest => RebootReason2::DeveloperRequest,
74 ShutdownReason::SystemUpdate => RebootReason2::SystemUpdate,
75 ShutdownReason::RetrySystemUpdate => RebootReason2::RetrySystemUpdate,
76 ShutdownReason::HighTemperature => RebootReason2::HighTemperature,
77 ShutdownReason::FactoryDataReset => RebootReason2::FactoryDataReset,
78 ShutdownReason::SessionFailure => RebootReason2::SessionFailure,
79 ShutdownReason::CriticalComponentFailure => RebootReason2::CriticalComponentFailure,
80 ShutdownReason::ZbiSwap => RebootReason2::ZbiSwap,
81 ShutdownReason::OutOfMemory => RebootReason2::OutOfMemory,
82 ShutdownReason::NetstackMigration => RebootReason2::NetstackMigration,
83 ShutdownReason::AndroidUnexpectedReason => RebootReason2::AndroidUnexpectedReason,
84 ShutdownReason::StarnixContainerNoReason => RebootReason2::UserRequest,
85 ShutdownReason::AndroidRescueParty => RebootReason2::AndroidRescueParty,
86 ShutdownReason::AndroidCriticalProcessFailure => {
87 RebootReason2::AndroidCriticalProcessFailure
88 }
89 ShutdownReason::__SourceBreaking { unknown_ordinal } => {
90 println!("[shutdown-shim]: error, unrecognized ShutdownReason ordinal: {unknown_ordinal}");
91 RebootReason2::unknown()
92 }
93 })
94 .collect()
95 }
96}
97
98impl From<ShutdownOptionsWrapper> for fpower::RebootOptions {
99 fn from(options: ShutdownOptionsWrapper) -> Self {
100 fpower::RebootOptions {
101 reasons: Some(options.to_reboot_reason2_deprecated()),
102 __source_breaking: SourceBreaking,
103 }
104 }
105}
106
107impl From<ShutdownOptionsWrapper> for ShutdownOptions {
108 fn from(options: ShutdownOptionsWrapper) -> Self {
109 ShutdownOptions {
110 action: Some(options.action),
111 reasons: Some(options.reasons),
112 __source_breaking: SourceBreaking,
113 }
114 }
115}
116
117#[derive(Debug, PartialEq)]
119pub enum InvalidRebootOptions {
120 NoReasons,
122}
123
124impl TryFrom<fpower::RebootOptions> for ShutdownOptionsWrapper {
125 type Error = InvalidRebootOptions;
126 fn try_from(options: fpower::RebootOptions) -> Result<Self, Self::Error> {
127 let fpower::RebootOptions { reasons, __source_breaking } = options;
128 if let Some(reasons) = reasons {
129 if !reasons.is_empty() {
130 return Ok(ShutdownOptionsWrapper::from_reboot_reason2_deprecated(&reasons));
131 }
132 }
133
134 Err(InvalidRebootOptions::NoReasons)
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use test_case::test_case;
142
143 #[test_case(None => Err(InvalidRebootOptions::NoReasons); "no_reasons")]
144 #[test_case(Some(vec![]) => Err(InvalidRebootOptions::NoReasons); "empty_reasons")]
145 #[test_case(Some(vec![fpower::RebootReason2::UserRequest]) => Ok(()); "success")]
146 fn reboot_reasons(
147 reasons: Option<Vec<fpower::RebootReason2>>,
148 ) -> Result<(), InvalidRebootOptions> {
149 let options = fpower::RebootOptions { reasons, __source_breaking: SourceBreaking };
150 ShutdownOptionsWrapper::try_from(options).map(|_reasons| {})
151 }
152}