1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45use crate::agent::{
6 AgentError, Context as AgentContext, Invocation, InvocationResult, Lifespan, Payload,
7};
8use crate::base::SettingType;
9use crate::event::{camera_watcher, Event, Publisher};
10use crate::handler::base::{Payload as HandlerPayload, Request};
11use crate::input::common::connect_to_camera;
12use crate::message::base::Audience;
13use crate::service_context::ServiceContext;
14use crate::{service, trace, trace_guard};
15use fuchsia_async as fasync;
16use std::collections::HashSet;
17use std::rc::Rc;
1819/// Setting types that the camera watcher agent will send updates to, if they're
20/// available on the device.
21fn get_event_setting_types() -> HashSet<SettingType> {
22vec![SettingType::Input].into_iter().collect()
23}
2425// TODO(https://fxbug.dev/42149412): Extract common template from agents.
26pub(crate) struct CameraWatcherAgent {
27 publisher: Publisher,
28 messenger: service::message::Messenger,
2930/// Settings to send camera watcher events to.
31recipient_settings: HashSet<SettingType>,
32}
3334impl CameraWatcherAgent {
35pub(crate) async fn create(context: AgentContext) {
36let mut agent = CameraWatcherAgent {
37 publisher: context.get_publisher(),
38 messenger: context
39 .create_messenger()
40 .await
41.expect("messenger should be created for CameraWatchAgent"),
42 recipient_settings: context
43 .available_components
44 .intersection(&get_event_setting_types())
45 .cloned()
46 .collect::<HashSet<SettingType>>(),
47 };
4849let mut receptor = context.receptor;
50 fasync::Task::local(async move {
51let id = fuchsia_trace::Id::new();
52let guard = trace_guard!(id, c"camera watcher agent");
53while let Ok((payload, client)) = receptor.next_of::<Payload>().await {
54trace!(id, c"payload");
55if let Payload::Invocation(invocation) = payload {
56let _ = client.reply(Payload::Complete(agent.handle(invocation).await).into());
57 }
58 }
59 drop(guard);
6061log::info!("Camera watcher agent done processing requests");
62 })
63 .detach()
64 }
6566async fn handle(&mut self, invocation: Invocation) -> InvocationResult {
67match invocation.lifespan {
68 Lifespan::Initialization => Err(AgentError::UnhandledLifespan),
69 Lifespan::Service => self.handle_service_lifespan(invocation.service_context).await,
70 }
71 }
7273async fn handle_service_lifespan(
74&mut self,
75 service_context: Rc<ServiceContext>,
76 ) -> InvocationResult {
77match connect_to_camera(service_context).await {
78Ok(camera_device_client) => {
79let mut event_handler = EventHandler {
80 publisher: self.publisher.clone(),
81 messenger: self.messenger.clone(),
82 recipient_settings: self.recipient_settings.clone(),
83 sw_muted: false,
84 };
85 fasync::Task::local(async move {
86let id = fuchsia_trace::Id::new();
87// Here we don't care about hw_muted state because the input service would pick
88 // up mute changes directly from the switch. We care about sw changes because
89 // other clients of the camera3 service could change the sw mute state but not
90 // notify the settings service.
91trace!(id, c"camera_watcher_agent_handler");
92while let Ok((sw_muted, _hw_muted)) =
93 camera_device_client.watch_mute_state().await
94{
95trace!(id, c"event");
96 event_handler.handle_event(sw_muted);
97 }
98 })
99 .detach();
100101Ok(())
102 }
103Err(e) => {
104log::error!("Unable to watch camera device: {:?}", e);
105Err(AgentError::UnexpectedError)
106 }
107 }
108 }
109}
110111struct EventHandler {
112 publisher: Publisher,
113 messenger: service::message::Messenger,
114 recipient_settings: HashSet<SettingType>,
115 sw_muted: bool,
116}
117118impl EventHandler {
119fn handle_event(&mut self, sw_muted: bool) {
120if self.sw_muted != sw_muted {
121self.sw_muted = sw_muted;
122self.send_event(sw_muted);
123 }
124 }
125126fn send_event(&self, muted: bool) {
127self.publisher.send_event(Event::CameraUpdate(camera_watcher::Event::OnSWMuteState(muted)));
128let setting_request: Request = Request::OnCameraSWState(muted);
129130// Send the event to all the interested setting types that are also available.
131for setting_type in self.recipient_settings.iter() {
132// Ignore the receptor result.
133let _ = self.messenger.message(
134 HandlerPayload::Request(setting_request.clone()).into(),
135 Audience::Address(service::Address::Handler(*setting_type)),
136 );
137 }
138 }
139}
140141#[cfg(test)]
142mod tests {
143use super::*;
144use crate::event;
145use crate::message::base::{MessageEvent, MessengerType};
146use crate::message::receptor::Receptor;
147use crate::tests::fakes::service_registry::ServiceRegistry;
148use crate::tests::helpers::{
149 create_messenger_and_publisher, create_messenger_and_publisher_from_hub,
150 create_receptor_for_setting_type,
151 };
152use assert_matches::assert_matches;
153use futures::StreamExt;
154155// Tests that the initialization lifespan is not handled.
156#[fuchsia::test(allow_stalls = false)]
157async fn initialization_lifespan_is_unhandled() {
158// Setup messengers needed to construct the agent.
159let (messenger, publisher) = create_messenger_and_publisher().await;
160161// Construct the agent.
162let mut agent =
163 CameraWatcherAgent { publisher, messenger, recipient_settings: HashSet::new() };
164165// Try to initiatate the initialization lifespan.
166let result = agent
167 .handle(Invocation {
168 lifespan: Lifespan::Initialization,
169 service_context: Rc::new(ServiceContext::new(None, None)),
170 })
171 .await;
172173assert!(matches!(result, Err(AgentError::UnhandledLifespan)));
174 }
175176// Tests that the agent cannot start without a camera3 service.
177#[fuchsia::test(allow_stalls = false)]
178async fn when_camera3_inaccessible_returns_err() {
179// Setup messengers needed to construct the agent.
180let (messenger, publisher) = create_messenger_and_publisher().await;
181182// Construct the agent.
183let mut agent =
184 CameraWatcherAgent { publisher, messenger, recipient_settings: HashSet::new() };
185186let service_context = Rc::new(ServiceContext::new(
187// Create a service registry without a camera3 service interface.
188Some(ServiceRegistry::serve(ServiceRegistry::create())),
189None,
190 ));
191192// Try to initiate the Service lifespan without providing the camera3 fidl interface.
193let result =
194 agent.handle(Invocation { lifespan: Lifespan::Service, service_context }).await;
195assert!(matches!(result, Err(AgentError::UnexpectedError)));
196 }
197198// Tests that events can be sent to the intended recipients.
199#[fuchsia::test(allow_stalls = false)]
200async fn event_handler_proxies_event() {
201let service_message_hub = service::MessageHub::create_hub();
202let (messenger, publisher) =
203 create_messenger_and_publisher_from_hub(&service_message_hub).await;
204205// Get the messenger's signature and the receptor for agents. We need
206 // a different messenger below because a broadcast would not send a message
207 // to itself. The signature is used to delete the original messenger for this
208 // receptor.
209let event_receptor = service::build_event_listener(&service_message_hub).await;
210211// Get the messenger's signature and the receptor for agents. We need
212 // a different messenger below because a broadcast would not send a message
213 // to itself. The signature is used to delete the original messenger for this
214 // receptor.
215let handler_receptor: Receptor =
216 create_receptor_for_setting_type(&service_message_hub, SettingType::Unknown).await;
217218let mut event_handler = EventHandler {
219 publisher,
220 messenger,
221 recipient_settings: vec![SettingType::Unknown].into_iter().collect(),
222 sw_muted: false,
223 };
224225// Send the events.
226event_handler.handle_event(true);
227228// Delete the messengers for the receptors we're selecting below. This
229 // will allow the `select!` to eventually hit the `complete` case.
230service_message_hub.delete(handler_receptor.get_signature());
231 service_message_hub.delete(event_receptor.get_signature());
232233let mut agent_received_sw_mute = false;
234let mut handler_received_event = false;
235236let fused_event = event_receptor.fuse();
237let fused_setting_handler = handler_receptor.fuse();
238futures::pin_mut!(fused_event, fused_setting_handler);
239240// Loop over the select so we can handle the messages as they come in. When all messages
241 // have been handled, due to the messengers being deleted above, the complete branch should
242 // be hit to break out of the loop.
243loop {
244futures::select! {
245 message = fused_event.select_next_some() => {
246if let MessageEvent::Message(service::Payload::Event(event::Payload::Event(
247 event::Event::CameraUpdate(event)
248 )), _) = message
249 {
250match event {
251 event::camera_watcher::Event::OnSWMuteState(muted) => {
252assert!(muted);
253 agent_received_sw_mute = true;
254 }
255 }
256 }
257 },
258 message = fused_setting_handler.select_next_some() => {
259if let MessageEvent::Message(
260 service::Payload::Setting(HandlerPayload::Request(
261 Request::OnCameraSWState(_muted))),
262_,
263 ) = message
264 {
265 handler_received_event = true;
266 }
267 }
268 complete => break,
269 }
270 }
271272assert!(agent_received_sw_mute);
273assert!(handler_received_event);
274 }
275276// Tests that events are not sent to unavailable settings.
277#[fuchsia::test(allow_stalls = false)]
278async fn event_handler_sends_no_events_if_no_settings_available() {
279let service_message_hub = service::MessageHub::create_hub();
280let (messenger, publisher) =
281 create_messenger_and_publisher_from_hub(&service_message_hub).await;
282let handler_address = service::Address::Handler(SettingType::Unknown);
283let verification_request = Request::Get;
284285// Get the messenger's signature and the receptor for agents. We need
286 // a different messenger below because a broadcast would not send a message
287 // to itself. The signature is used to delete the original messenger for this
288 // receptor.
289let mut handler_receptor: Receptor = service_message_hub
290 .create(MessengerType::Addressable(handler_address))
291 .await
292.expect("Unable to create handler receptor")
293 .1;
294295// Declare all settings as unavailable so that no events are sent.
296let mut event_handler = EventHandler {
297 publisher,
298 messenger,
299 recipient_settings: HashSet::new(),
300 sw_muted: false,
301 };
302303// Send the events
304event_handler.handle_event(true);
305306// Send an arbitrary request that should be the next payload received.
307let _ = service_message_hub
308 .create(MessengerType::Unbound)
309 .await
310.expect("Unable to create messenger")
311 .0
312.message(
313 HandlerPayload::Request(verification_request.clone()).into(),
314 Audience::Address(handler_address),
315 );
316317// Delete the messengers for the receptors we're selecting below. This will allow the while
318 // loop below to eventually finish.
319service_message_hub.delete(handler_receptor.get_signature());
320321assert_matches!(
322 handler_receptor.next_of::<HandlerPayload>().await,
323Ok((HandlerPayload::Request(request), _))
324if request == verification_request
325 )
326 }
327}