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::BatteryDrained => RebootReason2::UserRequest,
90 ShutdownReason::SuspensionFailure => RebootReason2::unknown(),
91 ShutdownReason::__SourceBreaking { unknown_ordinal } => {
92 println!("[shutdown-shim]: error, unrecognized ShutdownReason ordinal: {unknown_ordinal}");
93 RebootReason2::unknown()
94 }
95 })
96 .collect()
97 }
98}
99
100impl From<ShutdownOptionsWrapper> for fpower::RebootOptions {
101 fn from(options: ShutdownOptionsWrapper) -> Self {
102 fpower::RebootOptions {
103 reasons: Some(options.to_reboot_reason2_deprecated()),
104 __source_breaking: SourceBreaking,
105 }
106 }
107}
108
109impl From<ShutdownOptionsWrapper> for ShutdownOptions {
110 fn from(options: ShutdownOptionsWrapper) -> Self {
111 ShutdownOptions {
112 action: Some(options.action),
113 reasons: Some(options.reasons),
114 __source_breaking: SourceBreaking,
115 }
116 }
117}
118
119#[derive(Debug, PartialEq)]
121pub enum InvalidRebootOptions {
122 NoReasons,
124}
125
126impl TryFrom<fpower::RebootOptions> for ShutdownOptionsWrapper {
127 type Error = InvalidRebootOptions;
128 fn try_from(options: fpower::RebootOptions) -> Result<Self, Self::Error> {
129 let fpower::RebootOptions { reasons, __source_breaking } = options;
130 if let Some(reasons) = reasons {
131 if !reasons.is_empty() {
132 return Ok(ShutdownOptionsWrapper::from_reboot_reason2_deprecated(&reasons));
133 }
134 }
135
136 Err(InvalidRebootOptions::NoReasons)
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use test_case::test_case;
144
145 #[test_case(None => Err(InvalidRebootOptions::NoReasons); "no_reasons")]
146 #[test_case(Some(vec![]) => Err(InvalidRebootOptions::NoReasons); "empty_reasons")]
147 #[test_case(Some(vec![fpower::RebootReason2::UserRequest]) => Ok(()); "success")]
148 fn reboot_reasons(
149 reasons: Option<Vec<fpower::RebootReason2>>,
150 ) -> Result<(), InvalidRebootOptions> {
151 let options = fpower::RebootOptions { reasons, __source_breaking: SourceBreaking };
152 ShutdownOptionsWrapper::try_from(options).map(|_reasons| {})
153 }
154}