| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use crate::audio::policy::{self as audio, State}; |
| use crate::base::SettingType; |
| use crate::generate_inspect_with_info; |
| use crate::handler::device_storage::DeviceStorageFactory; |
| use crate::payload_convert; |
| use crate::policy::policy_handler::PolicyHandler; |
| use crate::policy::response::Response; |
| use crate::service; |
| use anyhow::Error; |
| use async_trait::async_trait; |
| use futures::future::BoxFuture; |
| use serde::{Deserialize, Serialize}; |
| use std::borrow::Cow; |
| use std::sync::Arc; |
| use thiserror::Error; |
| |
| /// Defines the policy handler trait, which describes a component that persists and applies the |
| /// policies specified by policy clients |
| pub mod policy_handler; |
| |
| /// Defines a proxy between the policy FIDL handler and policy handler that is responsible for |
| /// intercepting incoming setting requests and returning responses to the policy FIDL handler. |
| pub mod policy_proxy; |
| |
| /// Defines a factory for creating policy handlers on demand. |
| pub mod policy_handler_factory_impl; |
| |
| /// The policy types supported by the service. |
| #[derive(PartialEq, Debug, Eq, Hash, Clone, Copy, Serialize, Deserialize)] |
| pub enum PolicyType { |
| /// This type is reserved for testing purposes. |
| #[cfg(test)] |
| Unknown, |
| Audio, |
| } |
| |
| impl PolicyType { |
| /// Returns the corresponding setting type that this policy controls. |
| pub fn setting_type(&self) -> SettingType { |
| match self { |
| #[cfg(test)] |
| PolicyType::Unknown => SettingType::Unknown, |
| PolicyType::Audio => SettingType::Audio, |
| } |
| } |
| |
| /// Initialize the storage needed for this particular policy handler. |
| pub async fn initialize_storage<T>(&self, storage_factory: &Arc<T>) -> Result<(), Error> |
| where |
| T: DeviceStorageFactory, |
| { |
| match self { |
| #[cfg(test)] |
| Self::Unknown => Ok(()), |
| Self::Audio => { |
| storage_factory |
| .initialize::<audio::audio_policy_handler::AudioPolicyHandler>() |
| .await |
| } |
| } |
| } |
| } |
| |
| generate_inspect_with_info! { |
| /// Enumeration over the possible policy state information for all policies. |
| #[derive(PartialEq, Debug, Clone)] |
| pub enum PolicyInfo { |
| /// This value is reserved for testing purposes. |
| #[cfg(test)] |
| Unknown(UnknownInfo), |
| Audio(State), |
| } |
| } |
| |
| /// This struct is reserved for testing purposes. |
| #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] |
| #[cfg(test)] |
| pub struct UnknownInfo(pub bool); |
| |
| /// This trait implementation is reserved for testing purposes. |
| #[cfg(test)] |
| impl Into<PolicyInfo> for UnknownInfo { |
| fn into(self) -> PolicyInfo { |
| PolicyInfo::Unknown(self) |
| } |
| } |
| |
| #[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)] |
| pub enum Address { |
| // Policy(PolicyType), |
| } |
| |
| #[derive(PartialEq, Clone, Debug)] |
| pub enum Payload { |
| Request(Request), |
| Response(Response), |
| } |
| |
| payload_convert!(Policy, Payload); |
| |
| /// `Role` defines grouping for responsibilities on the policy message hub. |
| #[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)] |
| pub enum Role { |
| /// This role indicates that the messenger handles and enacts policy requests. |
| PolicyHandler, |
| } |
| |
| /// `Request` defines the request space for all policies handled by |
| /// the Setting Service. Note that the actions that can be taken upon each |
| /// policy should be defined within each policy's Request enum. |
| #[derive(PartialEq, Debug, Clone)] |
| pub enum Request { |
| /// Fetches the current policy state. |
| Get, |
| |
| /// Request targeted to the Audio policy. |
| Audio(audio::Request), |
| } |
| |
| pub mod response { |
| use super::*; |
| |
| pub type Response = Result<Payload, Error>; |
| |
| /// `Payload` defines the possible successful responses for a request. There |
| /// should be a corresponding policy response payload type for each request type. |
| #[derive(PartialEq, Debug, Clone)] |
| pub enum Payload { |
| PolicyInfo(PolicyInfo), |
| Audio(audio::Response), |
| } |
| |
| /// The possible errors that can be returned from a request. Note that |
| /// unlike the request and response space, errors are not type specific. |
| #[derive(Error, Debug, Clone, PartialEq)] |
| pub enum Error { |
| #[error("Unexpected error")] |
| Unexpected, |
| |
| #[error("Communication error")] |
| CommunicationError, |
| |
| #[error("Invalid input argument for policy: {0:?} argument:{1:?} value:{2:?}")] |
| InvalidArgument(PolicyType, Cow<'static, str>, Cow<'static, str>), |
| |
| #[error("Write failed for policy: {0:?}")] |
| WriteFailure(PolicyType), |
| } |
| } |
| |
| pub type BoxedHandler = Box<dyn PolicyHandler + Send + Sync>; |
| pub type GenerateHandlerResult = Result<BoxedHandler, Error>; |
| pub type GenerateHandler<T> = |
| Box<dyn Fn(Context<T>) -> BoxFuture<'static, GenerateHandlerResult> + Send + Sync>; |
| |
| /// Context captures all details necessary for a policy handler to execute in a given |
| /// settings service environment. |
| pub struct Context<T: DeviceStorageFactory> { |
| pub policy_type: PolicyType, |
| pub service_messenger: service::message::Messenger, |
| pub storage_factory: Arc<T>, |
| pub id: u64, |
| } |
| |
| /// A factory capable of creating a policy handler for a given setting on-demand. If no |
| /// viable handler can be created, None will be returned. |
| #[async_trait] |
| pub trait PolicyHandlerFactory { |
| async fn generate( |
| &mut self, |
| policy_type: PolicyType, |
| service_messenger: service::message::Messenger, |
| ) -> Result<BoxedHandler, PolicyHandlerFactoryError>; |
| } |
| |
| #[derive(thiserror::Error, Debug, Clone, PartialEq)] |
| pub enum PolicyHandlerFactoryError { |
| #[error("Policy type {0:?} not registered in environment")] |
| PolicyNotFound(PolicyType), |
| |
| #[error("Setting type {0:?} for policy {0:?} not registered in environment")] |
| SettingNotFound(SettingType, PolicyType), |
| |
| #[error("Cannot find policy handler generator for {0:?}")] |
| GeneratorNotFound(PolicyType), |
| |
| #[error("Policy handler {0:?} failed to startup")] |
| HandlerStartupError(PolicyType), |
| } |