settings/factory_reset/
factory_reset_controller.rs1use crate::base::{SettingInfo, SettingType};
6use crate::call;
7use crate::factory_reset::types::FactoryResetInfo;
8use crate::handler::base::Request;
9use crate::handler::setting_handler::controller::Handle;
10use crate::handler::setting_handler::persist::{controller, ClientProxy};
11use crate::handler::setting_handler::{
12 ControllerError, ControllerStateResult, SettingHandlerResult, State,
13};
14use crate::service_context::ExternalServiceProxy;
15use async_trait::async_trait;
16use fidl_fuchsia_recovery_policy::{DeviceMarker, DeviceProxy};
17use futures::lock::Mutex;
18use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
19use settings_storage::storage_factory::{NoneT, StorageAccess};
20use std::rc::Rc;
21
22impl DeviceStorageCompatible for FactoryResetInfo {
23 type Loader = NoneT;
24 const KEY: &'static str = "factory_reset_info";
25}
26
27impl Default for FactoryResetInfo {
28 fn default() -> Self {
29 FactoryResetInfo::new(true)
30 }
31}
32
33impl From<FactoryResetInfo> for SettingInfo {
34 fn from(info: FactoryResetInfo) -> SettingInfo {
35 SettingInfo::FactoryReset(info)
36 }
37}
38
39type FactoryResetHandle = Rc<Mutex<FactoryResetManager>>;
40
41pub struct FactoryResetController {
48 handle: FactoryResetHandle,
49}
50
51impl StorageAccess for FactoryResetController {
52 type Storage = DeviceStorage;
53 type Data = FactoryResetInfo;
54 const STORAGE_KEY: &'static str = FactoryResetInfo::KEY;
55}
56
57pub struct FactoryResetManager {
60 client: ClientProxy,
61 is_local_reset_allowed: bool,
62 factory_reset_policy_service: ExternalServiceProxy<DeviceProxy>,
63}
64
65impl FactoryResetManager {
66 async fn from_client(client: ClientProxy) -> Result<FactoryResetHandle, ControllerError> {
67 client
68 .get_service_context()
69 .connect::<DeviceMarker>()
70 .await
71 .map(|factory_reset_policy_service| {
72 Rc::new(Mutex::new(Self {
73 client,
74 is_local_reset_allowed: true,
75 factory_reset_policy_service,
76 }))
77 })
78 .map_err(|_| {
79 ControllerError::InitFailure("could not connect to factory reset service".into())
80 })
81 }
82
83 async fn restore(&mut self) -> SettingHandlerResult {
84 self.restore_reset_state(true).await.map(|_| None)
85 }
86
87 async fn restore_reset_state(&mut self, send_event: bool) -> ControllerStateResult {
88 let info = self.client.read_setting::<FactoryResetInfo>(fuchsia_trace::Id::new()).await;
89 self.is_local_reset_allowed = info.is_local_reset_allowed;
90 if send_event {
91 call!(self.factory_reset_policy_service =>
92 set_is_local_reset_allowed(info.is_local_reset_allowed)
93 )
94 .map_err(|e| {
95 ControllerError::ExternalFailure(
96 SettingType::FactoryReset,
97 "factory_reset_policy".into(),
98 "restore_reset_state".into(),
99 format!("{e:?}").into(),
100 )
101 })?;
102 }
103
104 Ok(())
105 }
106
107 #[allow(clippy::result_large_err)] fn get(&self) -> SettingHandlerResult {
109 Ok(Some(FactoryResetInfo::new(self.is_local_reset_allowed).into()))
110 }
111
112 async fn set_local_reset_allowed(
113 &mut self,
114 is_local_reset_allowed: bool,
115 ) -> SettingHandlerResult {
116 let id = fuchsia_trace::Id::new();
117 let mut info = self.client.read_setting::<FactoryResetInfo>(id).await;
118 self.is_local_reset_allowed = is_local_reset_allowed;
119 info.is_local_reset_allowed = is_local_reset_allowed;
120 call!(self.factory_reset_policy_service =>
121 set_is_local_reset_allowed(info.is_local_reset_allowed)
122 )
123 .map_err(|e| {
124 ControllerError::ExternalFailure(
125 SettingType::FactoryReset,
126 "factory_reset_policy".into(),
127 "set_local_reset_allowed".into(),
128 format!("{e:?}").into(),
129 )
130 })?;
131 self.client.write_setting(info.into(), id).await.map(|_| None)
132 }
133}
134
135#[async_trait(?Send)]
136impl controller::Create for FactoryResetController {
137 async fn create(client: ClientProxy) -> Result<Self, ControllerError> {
138 Ok(Self { handle: FactoryResetManager::from_client(client).await? })
139 }
140}
141
142#[async_trait(?Send)]
143impl Handle for FactoryResetController {
144 async fn handle(&self, request: Request) -> Option<SettingHandlerResult> {
145 match request {
146 Request::Restore => Some(self.handle.lock().await.restore().await),
147 Request::Get => Some(self.handle.lock().await.get()),
148 Request::SetLocalResetAllowed(is_local_reset_allowed) => {
149 Some(self.handle.lock().await.set_local_reset_allowed(is_local_reset_allowed).await)
150 }
151 _ => None,
152 }
153 }
154
155 async fn change_state(&mut self, state: State) -> Option<ControllerStateResult> {
156 match state {
157 State::Startup => {
158 Some(self.handle.lock().await.restore_reset_state(false).await)
161 }
162 _ => None,
163 }
164 }
165}