1use anyhow::Error;
6use async_trait::async_trait;
7use fidl_fuchsia_settings::*;
8use fidl_fuchsia_ui_brightness::{ControlRequest, ControlRequestStream};
9use fuchsia_async as fasync;
10use fuchsia_component::server::{ServiceFs, ServiceFsDir};
11use fuchsia_component_test::{
12 Capability, ChildOptions, LocalComponentHandles, RealmBuilder, RealmInstance, Ref, Route,
13};
14use futures::channel::mpsc::Sender;
15use futures::lock::Mutex;
16use futures::{SinkExt, StreamExt, TryStreamExt};
17use std::sync::atomic::{AtomicU32, Ordering};
18use std::sync::Arc;
19
20const COMPONENT_URL: &str = "#meta/setui_service.cm";
21
22#[derive(PartialEq, Debug)]
23pub enum Request {
24 SetAutoBrightness,
25 SetManualBrightness,
26}
27
28#[async_trait]
29pub trait Mocks {
30 async fn brightness_service_impl(
31 handles: LocalComponentHandles,
32 manual_brightness: Arc<Mutex<Option<f32>>>,
33 auto_brightness: Arc<Mutex<Option<bool>>>,
34 num_changes: Arc<AtomicU32>,
35 requests_sender: Sender<Request>,
36 ) -> Result<(), Error>;
37}
38
39#[async_trait]
40impl Mocks for DisplayTest {
41 async fn brightness_service_impl(
44 handles: LocalComponentHandles,
45 manual_brightness: Arc<Mutex<Option<f32>>>,
46 auto_brightness: Arc<Mutex<Option<bool>>>,
47 num_changes: Arc<AtomicU32>,
48 requests_sender: Sender<Request>,
49 ) -> Result<(), Error> {
50 let mut fs = ServiceFs::new();
51 let _: &mut ServiceFsDir<'_, _> =
52 fs.dir("svc").add_fidl_service(move |mut stream: ControlRequestStream| {
53 let auto_brightness_handle = auto_brightness.clone();
54 let brightness_handle = manual_brightness.clone();
55 let num_changes_handle = num_changes.clone();
56 let mut requests_sender = requests_sender.clone();
57 fasync::Task::spawn(async move {
58 while let Ok(Some(req)) = stream.try_next().await {
59 #[allow(unreachable_patterns)]
61 match req {
62 ControlRequest::WatchCurrentBrightness { responder } => {
63 responder
64 .send(
65 brightness_handle
66 .lock()
67 .await
68 .expect("brightness not yet set"),
69 )
70 .unwrap();
71 }
72 ControlRequest::SetAutoBrightness { control_handle: _ } => {
73 *auto_brightness_handle.lock().await = Some(true);
74 let current_num = num_changes_handle.load(Ordering::Relaxed);
75 (*num_changes_handle).store(current_num + 1, Ordering::Relaxed);
76 requests_sender
77 .send(Request::SetAutoBrightness)
78 .await
79 .expect("Finished processing SetAutoBrightness call");
80 }
81 ControlRequest::SetManualBrightness { value, control_handle: _ } => {
82 *brightness_handle.lock().await = Some(value);
83 *auto_brightness_handle.lock().await = Some(false);
84 let current_num = num_changes_handle.load(Ordering::Relaxed);
85 (*num_changes_handle).store(current_num + 1, Ordering::Relaxed);
86 requests_sender
87 .send(Request::SetManualBrightness)
88 .await
89 .expect("Finished processing SetManualBrightness call");
90 }
91 ControlRequest::WatchAutoBrightness { responder } => {
92 responder
93 .send(auto_brightness_handle.lock().await.unwrap_or(false))
94 .unwrap();
95 }
96 _ => {}
97 }
98 }
99 })
100 .detach();
101 });
102 let _: &mut ServiceFs<_> = fs.serve_connection(handles.outgoing_dir).unwrap();
103 fs.collect::<()>().await;
104 Ok(())
105 }
106}
107
108pub struct DisplayTest {}
109
110impl DisplayTest {
111 pub async fn create_realm() -> Result<RealmInstance, Error> {
114 let builder = RealmBuilder::new().await?;
115 let setui_service =
117 builder.add_child("setui_service", COMPONENT_URL, ChildOptions::new()).await?;
118 let info = utils::SettingsRealmInfo {
119 builder,
120 settings: &setui_service,
121 has_config_data: true,
122 capabilities: vec!["fuchsia.settings.Display"],
123 };
124 utils::create_realm_basic(&info).await?;
126 let instance = info.builder.build().await?;
127 Ok(instance)
128 }
129
130 pub async fn create_realm_with_brightness_controller(
133 manual_brightness: Arc<Mutex<Option<f32>>>,
134 auto_brightness: Arc<Mutex<Option<bool>>>,
135 num_changes: Arc<AtomicU32>,
136 requests_sender: Sender<Request>,
137 ) -> Result<RealmInstance, Error> {
138 let builder = RealmBuilder::new().await?;
139 let setui_service =
141 builder.add_child("setui_service", COMPONENT_URL, ChildOptions::new()).await?;
142 let info = utils::SettingsRealmInfo {
143 builder,
144 settings: &setui_service,
145 has_config_data: true,
146 capabilities: vec!["fuchsia.settings.Display"],
147 };
148 utils::create_realm_basic(&info).await?;
150 let brightness_service = info
152 .builder
153 .add_local_child(
154 "brightness_service",
155 move |handles: LocalComponentHandles| {
156 Box::pin(DisplayTest::brightness_service_impl(
157 handles,
158 Arc::clone(&manual_brightness),
159 Arc::clone(&auto_brightness),
160 Arc::clone(&num_changes),
161 requests_sender.clone(),
162 ))
163 },
164 ChildOptions::new().eager(),
165 )
166 .await?;
167 info.builder
168 .add_route(
169 Route::new()
170 .capability(Capability::protocol_by_name("fuchsia.ui.brightness.Control"))
171 .from(&brightness_service)
172 .to(Ref::parent())
173 .to(&setui_service),
174 )
175 .await?;
176 info.builder
178 .add_route(
179 Route::new()
180 .capability(Capability::protocol_by_name("fuchsia.logger.LogSink"))
181 .from(Ref::parent())
182 .to(&brightness_service),
183 )
184 .await?;
185 let instance = info.builder.build().await?;
186 Ok(instance)
187 }
188
189 pub fn connect_to_displaymarker(instance: &RealmInstance) -> DisplayProxy {
190 return instance
191 .root
192 .connect_to_protocol_at_exposed_dir::<DisplayMarker>()
193 .expect("connecting to Display");
194 }
195
196 pub fn get_init_manual_brightness() -> Arc<Mutex<Option<f32>>> {
197 Arc::new(Mutex::new(None))
198 }
199
200 pub fn get_init_auto_brightness() -> Arc<Mutex<Option<bool>>> {
201 Arc::new(Mutex::new(None))
202 }
203
204 pub fn get_init_num_changes() -> Arc<AtomicU32> {
205 Arc::new(AtomicU32::new(0))
206 }
207
208 pub async fn test_screen_enabled(display_proxy: DisplayProxy) {
210 let mut display_settings = DisplaySettings::default();
212 display_settings.auto_brightness = Some(false);
213 display_proxy.set(&display_settings).await.expect("set completed").expect("set successful");
214
215 let mut display_settings = DisplaySettings::default();
216 display_settings.screen_enabled = Some(false);
217 display_proxy.set(&display_settings).await.expect("set completed").expect("set successful");
218
219 let settings = display_proxy.watch().await.expect("watch completed");
220
221 assert_eq!(settings.screen_enabled, Some(false));
222
223 let mut display_settings = DisplaySettings::default();
225 display_settings.screen_enabled = Some(true);
226 display_proxy.set(&display_settings).await.expect("set completed").expect("set successful");
227
228 let settings = display_proxy.watch().await.expect("watch completed");
229
230 assert_eq!(settings.screen_enabled, Some(true));
231 assert_eq!(settings.auto_brightness, Some(false));
232
233 let mut display_settings = DisplaySettings::default();
235 display_settings.auto_brightness = Some(true);
236 display_proxy.set(&display_settings).await.expect("set completed").expect("set successful");
237
238 let settings = display_proxy.watch().await.expect("watch completed");
239
240 assert_eq!(settings.auto_brightness, Some(true));
241 assert_eq!(settings.screen_enabled, Some(true));
242 }
243}