1use crate::accessibility::types::AccessibilityInfo;
6use crate::audio::types::SetAudioStream;
7use crate::base::{SettingInfo, SettingType};
8use crate::display::types::SetDisplayInfo;
9use crate::do_not_disturb::types::DoNotDisturbInfo;
10use crate::handler::setting_handler::ControllerError;
11use crate::input::types::InputDevice;
12use crate::intl::types::IntlInfo;
13use crate::keyboard::types::KeyboardInfo;
14use crate::night_mode::types::NightModeInfo;
15use crate::payload_convert;
16use crate::service::message::{Delegate, Messenger, Receptor, Signature};
17use crate::service_context::ServiceContext;
18use crate::setup::types::SetConfigurationInterfacesParams;
19use settings_light::types::LightState;
20use settings_media_buttons::MediaButtons;
21
22use async_trait::async_trait;
23use fuchsia_trace as ftrace;
24use futures::future::LocalBoxFuture;
25use std::borrow::Cow;
26use std::collections::HashSet;
27use std::rc::Rc;
28
29pub type ControllerGenerateResult = Result<(), anyhow::Error>;
30
31pub(crate) type GenerateHandler =
32 Box<dyn Fn(Context) -> LocalBoxFuture<'static, ControllerGenerateResult>>;
33
34pub type Response = Result<Option<SettingInfo>, Error>;
35
36#[macro_export]
40macro_rules! generate_inspect {
41 (@underscore $_type:ty) => { _ };
42 ($(#[$metas:meta])* pub enum $name:ident {
43 $(
44 $(#[$variant_meta:meta])*
45 $variant:ident
46 $( ($($data:ty),+ $(,)?) )?
47 ),* $(,)?
48 }
49 ) => {
50 $(#[$metas])*
51 pub enum $name {
52 $(
53 $(#[$variant_meta])*
54 $variant$(($($data,)+))?,
55 )*
56 }
57
58 impl $name {
59 pub(crate) fn for_inspect(&self) -> &'static str {
60 match self {
61 $(
62 $name::$variant $(
63 ( $(generate_inspect!(@underscore $data)),+ )
64 )? => stringify!($variant),
65 )*
66 }
67 }
68 }
69 };
70}
71
72generate_inspect! {
73 #[derive(PartialEq, Debug, Clone)]
77 pub enum Request {
78 Get,
80
81 Listen,
83
84 OnCameraSWState(bool),
86
87 OnButton(MediaButtons),
89
90 SetAccessibilityInfo(AccessibilityInfo),
92
93 SetVolume(Vec<SetAudioStream>, ftrace::Id),
95
96 SetDisplayInfo(SetDisplayInfo),
98
99 SetDnD(DoNotDisturbInfo),
101
102 SetLocalResetAllowed(bool),
104
105 SetInputStates(Vec<InputDevice>),
107
108 SetIntlInfo(IntlInfo),
110
111 SetKeyboardInfo(KeyboardInfo),
113
114 SetLightGroupValue(String, Vec<LightState>),
116
117 SetNightModeInfo(NightModeInfo),
119
120 Restore,
122
123 Rebroadcast,
125
126 SetUserDataSharingConsent(Option<bool>),
128
129 SetConfigurationInterfaces(SetConfigurationInterfacesParams),
131 }
132}
133
134impl From<MediaButtons> for Request {
135 fn from(event: MediaButtons) -> Self {
136 Request::OnButton(event)
137 }
138}
139
140#[derive(Clone, PartialEq, Debug)]
143pub enum Payload {
144 Request(Request),
151 Response(Response),
155}
156
157payload_convert!(Setting, Payload);
159
160#[derive(thiserror::Error, Debug, Clone, PartialEq)]
161pub enum Error {
164 #[error("Unimplemented Request:{0:?} for setting type: {1:?}")]
165 UnimplementedRequest(SettingType, Request),
166
167 #[error("Storage failure for setting type: {0:?}")]
168 StorageFailure(SettingType),
169
170 #[error("Initialization failure: cause {0:?}")]
171 InitFailure(Cow<'static, str>),
172
173 #[error("Restoration of setting on controller startup failed: cause {0:?}")]
174 RestoreFailure(Cow<'static, str>),
175
176 #[error("Invalid argument for setting type: {0:?} argument:{1:?} value:{2:?}")]
177 InvalidArgument(SettingType, Cow<'static, str>, Cow<'static, str>),
178
179 #[error(
180 "Incompatible argument values passed: {setting_type:?} argument:{main_arg:?} cannot be \
181 combined with arguments:[{other_args:?}] with respective values:[{values:?}]. {reason:?}"
182 )]
183 IncompatibleArguments {
184 setting_type: SettingType,
185 main_arg: Cow<'static, str>,
186 other_args: Cow<'static, str>,
187 values: Cow<'static, str>,
188 reason: Cow<'static, str>,
189 },
190
191 #[error("External failure for setting type:{0:?} dependency: {1:?} request:{2:?} error:{3}")]
192 ExternalFailure(SettingType, Cow<'static, str>, Cow<'static, str>, Cow<'static, str>),
193
194 #[error("Unhandled type: {0:?}")]
195 UnhandledType(SettingType),
196
197 #[error("Delivery error for type: {0:?} received by: {1:?}")]
198 DeliveryError(SettingType, SettingType),
199
200 #[error("Unexpected error: {0}")]
201 UnexpectedError(Cow<'static, str>),
202
203 #[error("Undeliverable Request:{1:?} for setting type: {0:?}")]
204 UndeliverableError(SettingType, Request),
205
206 #[error("Unsupported request for setting type: {0:?}")]
207 UnsupportedError(SettingType),
208
209 #[error("Communication error")]
210 CommunicationError,
211
212 #[error("Irrecoverable error")]
213 IrrecoverableError,
214
215 #[error("Timeout error")]
216 TimeoutError,
217}
218
219impl From<ControllerError> for Error {
220 fn from(error: ControllerError) -> Self {
221 match error {
222 ControllerError::UnimplementedRequest(setting_type, request) => {
223 Error::UnimplementedRequest(setting_type, request)
224 }
225 ControllerError::WriteFailure(setting_type) => Error::StorageFailure(setting_type),
226 ControllerError::InitFailure(description) => Error::InitFailure(description),
227 ControllerError::RestoreFailure(description) => Error::RestoreFailure(description),
228 ControllerError::ExternalFailure(setting_type, dependency, request, error) => {
229 Error::ExternalFailure(setting_type, dependency, request, error)
230 }
231 ControllerError::InvalidArgument(setting_type, argument, value) => {
232 Error::InvalidArgument(setting_type, argument, value)
233 }
234 ControllerError::IncompatibleArguments {
235 setting_type,
236 main_arg,
237 other_args,
238 values,
239 reason,
240 } => {
241 Error::IncompatibleArguments { setting_type, main_arg, other_args, values, reason }
242 }
243 ControllerError::UnhandledType(setting_type) => Error::UnhandledType(setting_type),
244 ControllerError::UnexpectedError(error) => Error::UnexpectedError(error),
245 ControllerError::UndeliverableError(setting_type, request) => {
246 Error::UndeliverableError(setting_type, request)
247 }
248 ControllerError::UnsupportedError(setting_type) => {
249 Error::UnsupportedError(setting_type)
250 }
251 ControllerError::DeliveryError(setting_type, setting_type_2) => {
252 Error::DeliveryError(setting_type, setting_type_2)
253 }
254 ControllerError::IrrecoverableError => Error::IrrecoverableError,
255 ControllerError::TimeoutError => Error::TimeoutError,
256 ControllerError::ExitError => Error::IrrecoverableError,
257 }
258 }
259}
260
261#[derive(thiserror::Error, Debug, Clone, PartialEq)]
262pub enum SettingHandlerFactoryError {
263 #[error("Setting type {0:?} not registered in environment")]
264 SettingNotFound(SettingType),
265
266 #[error("Cannot find setting handler generator for {0:?}")]
267 GeneratorNotFound(SettingType),
268
269 #[error("MessageHub Messenger for setting handler could not be created")]
270 HandlerMessengerError,
271
272 #[error("MessageHub Messenger for controller messenger could not be created")]
273 ControllerMessengerError,
274
275 #[error("MessageHub Messenger for lifecycle messenger could not be created")]
276 LifecycleMessengerError,
277
278 #[error("Setting handler for {0:?} failed to startup. cause: {1:?}")]
279 HandlerStartupError(SettingType, Cow<'static, str>),
280}
281
282#[async_trait(?Send)]
285pub(crate) trait SettingHandlerFactory {
286 async fn generate(
287 &mut self,
288 setting_type: SettingType,
289 delegate: Delegate,
290 notifier_signature: Signature,
291 ) -> Result<Signature, SettingHandlerFactoryError>;
292}
293
294pub struct Environment {
295 pub settings: HashSet<SettingType>,
296 pub service_context: Rc<ServiceContext>,
297}
298
299impl Clone for Environment {
300 fn clone(&self) -> Environment {
301 Environment::new(self.settings.clone(), self.service_context.clone())
302 }
303}
304
305impl Environment {
306 pub(crate) fn new(
307 settings: HashSet<SettingType>,
308 service_context: Rc<ServiceContext>,
309 ) -> Environment {
310 Environment { settings, service_context }
311 }
312}
313
314pub struct Context {
317 pub setting_type: SettingType,
318 pub messenger: Messenger,
319 pub receptor: Receptor,
320 pub notifier_signature: Signature,
321 pub environment: Environment,
322 pub id: u64,
323}
324
325impl Context {
326 pub(crate) fn new(
327 setting_type: SettingType,
328 messenger: Messenger,
329 receptor: Receptor,
330 notifier_signature: Signature,
331 environment: Environment,
332 id: u64,
333 ) -> Context {
334 Context { setting_type, messenger, receptor, notifier_signature, environment, id }
335 }
336}
337
338#[cfg(test)]
341pub(crate) struct ContextBuilder {
342 setting_type: SettingType,
343 settings: HashSet<SettingType>,
344 service_context: Option<Rc<ServiceContext>>,
345 messenger: Messenger,
346 receptor: Receptor,
347 notifier_signature: Signature,
348 id: u64,
349}
350
351#[cfg(test)]
352impl ContextBuilder {
353 pub(crate) fn new(
354 setting_type: SettingType,
355 messenger: Messenger,
356 receptor: Receptor,
357 notifier_signature: Signature,
358 id: u64,
359 ) -> Self {
360 Self {
361 setting_type,
362 settings: HashSet::new(),
363 service_context: None,
364 messenger,
365 receptor,
366 notifier_signature,
367 id,
368 }
369 }
370
371 pub(crate) fn build(self) -> Context {
373 let service_context =
374 self.service_context.unwrap_or_else(|| Rc::new(ServiceContext::new(None, None)));
375 let environment = Environment::new(self.settings, service_context);
376
377 Context::new(
382 self.setting_type,
383 self.messenger,
384 self.receptor,
385 self.notifier_signature,
386 environment,
387 self.id,
388 )
389 }
390}