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::DeveloperRequest => RebootReason2::DeveloperRequest,
73 ShutdownReason::SystemUpdate => RebootReason2::SystemUpdate,
74 ShutdownReason::RetrySystemUpdate => RebootReason2::RetrySystemUpdate,
75 ShutdownReason::HighTemperature => RebootReason2::HighTemperature,
76 ShutdownReason::FactoryDataReset => RebootReason2::FactoryDataReset,
77 ShutdownReason::SessionFailure => RebootReason2::SessionFailure,
78 ShutdownReason::CriticalComponentFailure => RebootReason2::CriticalComponentFailure,
79 ShutdownReason::ZbiSwap => RebootReason2::ZbiSwap,
80 ShutdownReason::OutOfMemory => RebootReason2::OutOfMemory,
81 ShutdownReason::NetstackMigration => RebootReason2::NetstackMigration,
82 ShutdownReason::AndroidUnexpectedReason => RebootReason2::AndroidUnexpectedReason,
83 ShutdownReason::StarnixContainerNoReason => RebootReason2::UserRequest,
84 ShutdownReason::AndroidRescueParty => RebootReason2::AndroidRescueParty,
85 ShutdownReason::AndroidCriticalProcessFailure => {
86 RebootReason2::AndroidCriticalProcessFailure
87 }
88 ShutdownReason::__SourceBreaking { unknown_ordinal } => {
89 println!("[shutdown-shim]: error, unrecognized ShutdownReason ordinal: {unknown_ordinal}");
90 RebootReason2::unknown()
91 }
92 })
93 .collect()
94 }
95}
96
97impl From<ShutdownOptionsWrapper> for fpower::RebootOptions {
98 fn from(options: ShutdownOptionsWrapper) -> Self {
99 fpower::RebootOptions {
100 reasons: Some(options.to_reboot_reason2_deprecated()),
101 __source_breaking: SourceBreaking,
102 }
103 }
104}
105
106impl From<ShutdownOptionsWrapper> for ShutdownOptions {
107 fn from(options: ShutdownOptionsWrapper) -> Self {
108 ShutdownOptions {
109 action: Some(options.action),
110 reasons: Some(options.reasons),
111 __source_breaking: SourceBreaking,
112 }
113 }
114}
115
116#[derive(Debug, PartialEq)]
118pub enum InvalidRebootOptions {
119 NoReasons,
121}
122
123impl TryFrom<fpower::RebootOptions> for ShutdownOptionsWrapper {
124 type Error = InvalidRebootOptions;
125 fn try_from(options: fpower::RebootOptions) -> Result<Self, Self::Error> {
126 let fpower::RebootOptions { reasons, __source_breaking } = options;
127 if let Some(reasons) = reasons {
128 if !reasons.is_empty() {
129 return Ok(ShutdownOptionsWrapper::from_reboot_reason2_deprecated(&reasons));
130 }
131 }
132
133 Err(InvalidRebootOptions::NoReasons)
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use test_case::test_case;
141
142 #[test_case(None => Err(InvalidRebootOptions::NoReasons); "no_reasons")]
143 #[test_case(Some(vec![]) => Err(InvalidRebootOptions::NoReasons); "empty_reasons")]
144 #[test_case(Some(vec![fpower::RebootReason2::UserRequest]) => Ok(()); "success")]
145 fn reboot_reasons(
146 reasons: Option<Vec<fpower::RebootReason2>>,
147 ) -> Result<(), InvalidRebootOptions> {
148 let options = fpower::RebootOptions { reasons, __source_breaking: SourceBreaking };
149 ShutdownOptionsWrapper::try_from(options).map(|_reasons| {})
150 }
151}