1use crate::agent::{
6 AgentError, Context as AgentContext, Invocation, InvocationResult, Lifespan, Payload,
7};
8use crate::base::SettingType;
9use crate::event::{media_buttons, Event, Publisher};
10use crate::handler::base::{Payload as HandlerPayload, Request};
11use crate::input::{monitor_media_buttons, MediaButtons};
12use crate::message::base::Audience;
13use crate::service_context::ServiceContext;
14use crate::{service, trace_guard};
15use fidl_fuchsia_ui_input::MediaButtonsEvent;
16use futures::StreamExt;
17use std::collections::HashSet;
18use std::rc::Rc;
19use {fuchsia_async as fasync, fuchsia_trace as ftrace};
20
21fn get_event_setting_types() -> HashSet<SettingType> {
24 vec![SettingType::Audio, SettingType::Light, SettingType::Input].into_iter().collect()
25}
26
27pub(crate) struct MediaButtonsAgent {
28 publisher: Publisher,
29 messenger: service::message::Messenger,
30
31 recipient_settings: HashSet<SettingType>,
33}
34
35impl MediaButtonsAgent {
36 pub(crate) async fn create(context: AgentContext) {
37 let mut agent = MediaButtonsAgent {
38 publisher: context.get_publisher(),
39 messenger: context.create_messenger().await.expect("media button messenger created"),
40 recipient_settings: context
41 .available_components
42 .intersection(&get_event_setting_types())
43 .cloned()
44 .collect::<HashSet<SettingType>>(),
45 };
46
47 let mut receptor = context.receptor;
48 fasync::Task::local(async move {
49 while let Ok((Payload::Invocation(invocation), client)) =
50 receptor.next_of::<Payload>().await
51 {
52 let _ = client.reply(Payload::Complete(agent.handle(invocation).await).into());
53 }
54
55 log::info!("Media buttons agent done processing requests");
56 })
57 .detach()
58 }
59
60 async fn handle(&mut self, invocation: Invocation) -> InvocationResult {
61 match invocation.lifespan {
62 Lifespan::Initialization => Err(AgentError::UnhandledLifespan),
63 Lifespan::Service => self.handle_service_lifespan(invocation.service_context).await,
64 }
65 }
66
67 async fn handle_service_lifespan(
68 &mut self,
69 service_context: Rc<ServiceContext>,
70 ) -> InvocationResult {
71 let (input_tx, mut input_rx) = futures::channel::mpsc::unbounded::<MediaButtonsEvent>();
72 if let Err(e) = monitor_media_buttons(service_context, input_tx).await {
73 log::error!("Unable to monitor media buttons: {:?}", e);
74 return Err(AgentError::UnexpectedError);
75 }
76
77 let event_handler = EventHandler {
78 publisher: self.publisher.clone(),
79 messenger: self.messenger.clone(),
80 recipient_settings: self.recipient_settings.clone(),
81 };
82 fasync::Task::local(async move {
83 while let Some(event) = input_rx.next().await {
84 let id = ftrace::Id::new();
85 event_handler.handle_event(event, id);
86 }
87 })
88 .detach();
89
90 Ok(())
91 }
92}
93
94struct EventHandler {
95 publisher: Publisher,
96 messenger: service::message::Messenger,
97 recipient_settings: HashSet<SettingType>,
98}
99
100impl EventHandler {
101 fn handle_event(&self, event: MediaButtonsEvent, id: ftrace::Id) {
102 if event.mic_mute.is_some() || event.camera_disable.is_some() {
103 let media_buttons: MediaButtons = event.into();
104 self.send_event(media_buttons, id);
105 }
106 }
107
108 fn send_event<E>(&self, event: E, id: ftrace::Id)
109 where
110 E: Copy + Into<media_buttons::Event> + Into<Request> + std::fmt::Debug,
111 {
112 self.publisher.send_event(Event::MediaButtons(event.into()));
113 let setting_request: Request = event.into();
114
115 for setting_type in self.recipient_settings.iter() {
117 let guard = trace_guard!(
118 id,
119
120 c"media buttons send event",
121 "setting_type" => format!("{setting_type:?}").as_str()
122 );
123 let mut receptor = self.messenger.message(
124 HandlerPayload::Request(setting_request.clone()).into(),
125 Audience::Address(service::Address::Handler(*setting_type)),
126 );
127 fasync::Task::local(async move {
128 let _ = receptor.next_payload().await;
129 drop(guard);
130 })
131 .detach();
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use crate::event;
140 use crate::input::common::MediaButtonsEventBuilder;
141 use crate::message::base::MessageEvent;
142 use crate::message::receptor::Receptor;
143 use crate::tests::fakes::service_registry::ServiceRegistry;
144 use crate::tests::helpers::{
145 create_messenger_and_publisher, create_messenger_and_publisher_from_hub,
146 create_receptor_for_setting_type,
147 };
148
149 #[fuchsia::test(allow_stalls = false)]
151 async fn initialization_lifespan_is_unhandled() {
152 let (messenger, publisher) = create_messenger_and_publisher().await;
154
155 let mut agent =
157 MediaButtonsAgent { publisher, messenger, recipient_settings: HashSet::new() };
158
159 let result = agent
161 .handle(Invocation {
162 lifespan: Lifespan::Initialization,
163 service_context: Rc::new(ServiceContext::new(None, None)),
164 })
165 .await;
166
167 assert!(matches!(result, Err(AgentError::UnhandledLifespan)));
168 }
169
170 #[fuchsia::test(allow_stalls = false)]
172 async fn when_media_buttons_inaccessible_returns_err() {
173 let (messenger, publisher) = create_messenger_and_publisher().await;
175
176 let mut agent =
178 MediaButtonsAgent { publisher, messenger, recipient_settings: HashSet::new() };
179
180 let service_context = Rc::new(ServiceContext::new(
181 Some(ServiceRegistry::serve(ServiceRegistry::create())),
183 None,
184 ));
185
186 let result =
188 agent.handle(Invocation { lifespan: Lifespan::Service, service_context }).await;
189 assert!(matches!(result, Err(AgentError::UnexpectedError)));
190 }
191
192 #[fuchsia::test(allow_stalls = false)]
194 async fn event_handler_proxies_event() {
195 let service_message_hub = service::MessageHub::create_hub();
196
197 let (messenger, publisher) =
198 create_messenger_and_publisher_from_hub(&service_message_hub).await;
199 let target_setting_type = SettingType::Unknown;
200
201 let event_receptor = service::build_event_listener(&service_message_hub).await;
206
207 let handler_receptor: Receptor =
209 create_receptor_for_setting_type(&service_message_hub, target_setting_type).await;
210
211 let event_handler = EventHandler {
213 publisher,
214 messenger,
215 recipient_settings: vec![target_setting_type].into_iter().collect(),
216 };
217
218 event_handler.handle_event(
220 MediaButtonsEventBuilder::new().set_mic_mute(true).set_camera_disable(true).build(),
221 0.into(),
222 );
223
224 service_message_hub.delete(handler_receptor.get_signature());
227 service_message_hub.delete(event_receptor.get_signature());
228
229 let mut agent_received_media_buttons = false;
230
231 let mut received_events: usize = 0;
232
233 let fused_event = event_receptor.fuse();
234 let fused_handler = handler_receptor.fuse();
235 futures::pin_mut!(fused_event, fused_handler);
236
237 loop {
241 futures::select! {
242 message = fused_event.select_next_some() => {
243 if let MessageEvent::Message(
244 service::Payload::Event(event::Payload::Event(
245 event::Event::MediaButtons(event))), _) = message
246 {
247 match event {
248 event::media_buttons::Event::OnButton(
249 MediaButtons{..}
250 ) => {
251 agent_received_media_buttons = true;
252 }
253 }
254 }
255 },
256 message = fused_handler.select_next_some() => {
257 if let MessageEvent::Message(
258 service::Payload::Setting(HandlerPayload::Request(
259 Request::OnButton(_button),
260 )),
261 _,
262 ) = message
263 {
264 received_events += 1;
265 }
266 }
267 complete => break,
268 }
269 }
270
271 assert!(agent_received_media_buttons);
272
273 assert_eq!(received_events, 1);
275 }
276
277 #[fuchsia::test(allow_stalls = false)]
279 async fn event_handler_sends_no_events_if_no_settings_available() {
280 let service_message_hub = service::MessageHub::create_hub();
281 let (messenger, publisher) =
282 create_messenger_and_publisher_from_hub(&service_message_hub).await;
283
284 let mut handler_receptor: Receptor =
286 create_receptor_for_setting_type(&service_message_hub, SettingType::Unknown).await;
287
288 let event_handler =
290 EventHandler { publisher, messenger, recipient_settings: HashSet::new() };
291
292 event_handler.handle_event(
294 MediaButtonsEventBuilder::new().set_mic_mute(true).set_camera_disable(true).build(),
295 0.into(),
296 );
297
298 let mut received_events: usize = 0;
299
300 service_message_hub.delete(handler_receptor.get_signature());
303
304 while let Ok((HandlerPayload::Request(_), _)) =
305 handler_receptor.next_of::<HandlerPayload>().await
306 {
307 received_events += 1;
308 }
309
310 assert_eq!(received_events, 0);
312 }
313}