blob: cbe4f5983e2fb53de0e4ea7e6bc15764996d4a7d [file] [log] [blame]
// 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::handler::base::{
Command, Context, Environment, GenerateHandler, SettingHandlerFactory,
SettingHandlerFactoryError, State,
};
use crate::handler::device_storage::DeviceStorageFactory;
use crate::internal::handler::{message, Payload};
use crate::message::base::{Audience, MessageEvent, MessengerType, Status};
use crate::service_context::ServiceContextHandle;
use crate::switchboard::base::SettingType;
use async_trait::async_trait;
use futures::lock::Mutex;
use futures::StreamExt;
use std::collections::HashMap;
use std::collections::HashSet;
use std::sync::Arc;
/// SettingHandlerFactoryImpl houses registered closures for generating setting
/// handlers.
pub struct SettingHandlerFactoryImpl<T: DeviceStorageFactory + Send + Sync> {
environment: Environment<T>,
generators: HashMap<SettingType, GenerateHandler<T>>,
/// Used to uniquely identify a context.
next_context_id: u64,
}
#[async_trait]
impl<T: DeviceStorageFactory + Send + Sync> SettingHandlerFactory for SettingHandlerFactoryImpl<T> {
async fn generate(
&mut self,
setting_type: SettingType,
messenger_factory: message::Factory,
notifier_signature: message::Signature,
) -> Result<message::Signature, SettingHandlerFactoryError> {
if !self.environment.settings.contains(&setting_type) {
return Err(SettingHandlerFactoryError::SettingNotFound(setting_type));
}
let (messenger, receptor) = messenger_factory
.create(MessengerType::Unbound)
.await
.map_err(|_| SettingHandlerFactoryError::HandlerMessengerError)?;
let signature = messenger.get_signature();
let generate_function = self
.generators
.get(&setting_type)
.ok_or(SettingHandlerFactoryError::GeneratorNotFound(setting_type))?;
(generate_function)(Context::new(
setting_type,
messenger,
receptor,
notifier_signature,
self.environment.clone(),
self.next_context_id,
))
.await
.map_err(|_| SettingHandlerFactoryError::HandlerStartupError(setting_type))?;
self.next_context_id += 1;
let (controller_messenger, _) = messenger_factory
.create(MessengerType::Unbound)
.await
.map_err(|_| SettingHandlerFactoryError::ControllerMessengerError)?;
// At this point, we know the controller was constructed successfully.
// Tell the controller to run the Startup phase to initialize its state.
let mut controller_receptor = controller_messenger
.message(
Payload::Command(Command::ChangeState(State::Startup)),
Audience::Messenger(signature),
)
.send();
// Wait for the startup phase to be over before continuing.
if let Some(MessageEvent::Status(Status::Received)) = controller_receptor.next().await {
// Startup phase is complete and had no errors. The proxy can assume it
// has an active controller with create() and startup() already run on it
// before handling its request.
return Ok(signature);
} else {
return Err(SettingHandlerFactoryError::HandlerStartupError(setting_type));
}
}
}
impl<T: DeviceStorageFactory + Send + Sync> SettingHandlerFactoryImpl<T> {
pub fn new(
settings: HashSet<SettingType>,
service_context_handle: ServiceContextHandle,
storage_factory_handle: Arc<Mutex<T>>,
) -> SettingHandlerFactoryImpl<T> {
SettingHandlerFactoryImpl {
environment: Environment::new(settings, service_context_handle, storage_factory_handle),
generators: HashMap::new(),
next_context_id: 1,
}
}
pub fn register(&mut self, setting_type: SettingType, generate_function: GenerateHandler<T>) {
self.generators.insert(setting_type, generate_function);
}
}