1use crate::lib::{Position, Size};
6use crate::pointerinjector_config::{
7 InjectorViewportChangeFn, InjectorViewportHangingGet, InjectorViewportPublisher,
8 InjectorViewportSpec, InjectorViewportSubscriber,
9};
10use crate::{DisplayMetrics, ViewingDistance};
11use anyhow::{Context, Error, Result};
12use async_trait::async_trait;
13use async_utils::hanging_get::server as hanging_get;
14use fidl::endpoints::{Proxy, create_proxy};
15use fidl_fuchsia_accessibility_scene as a11y_scene;
16use fidl_fuchsia_math as math;
17use fidl_fuchsia_ui_app as ui_app;
18use fidl_fuchsia_ui_composition::{self as ui_comp, ContentId, TransformId};
19use fidl_fuchsia_ui_display_singleton as singleton_display;
20use fidl_fuchsia_ui_pointerinjector_configuration::{
21 SetupRequest as PointerInjectorConfigurationSetupRequest,
22 SetupRequestStream as PointerInjectorConfigurationSetupRequestStream,
23};
24use fidl_fuchsia_ui_views as ui_views;
25use flatland_frame_scheduling_lib::*;
26use fuchsia_async::{self as fasync, TimeoutExt};
27use fuchsia_scenic as scenic;
28use fuchsia_trace as trace;
29use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender, unbounded};
30use futures::channel::oneshot;
31use futures::prelude::*;
32use log::{error, info, warn};
33use math as fmath;
34use std::cell::{Cell, RefCell};
35use std::collections::VecDeque;
36use std::ffi::CStr;
37use std::process;
38use std::rc::Rc;
39use std::sync::{Arc, Weak};
40use zx;
41
42pub enum PresentationMessage {
44 RequestPresent,
46 RequestPresentWithPingback(oneshot::Sender<()>),
49}
50
51pub type PresentationSender = UnboundedSender<PresentationMessage>;
53
54pub type PresentationReceiver = UnboundedReceiver<PresentationMessage>;
56
57const _CURSOR_SIZE: (u32, u32) = (18, 29);
58const CURSOR_HOTSPOT: (u32, u32) = (2, 4);
59
60const CURSOR_SCALE_MULTIPLIER: u32 = 5;
63const CURSOR_SCALE_DIVIDER: u32 = 4;
64
65const DEFAULT_VIEW_CONNECTION_TIMEOUT: zx::MonotonicDuration =
66 zx::MonotonicDuration::from_seconds(15);
67
68fn physical_cursor_size(value: u32) -> u32 {
70 (CURSOR_SCALE_MULTIPLIER * value) / CURSOR_SCALE_DIVIDER
71}
72
73pub type FlatlandPtr = Arc<ui_comp::FlatlandProxy>;
74
75#[derive(Clone)]
76struct TransformContentIdPair {
77 transform_id: TransformId,
78 content_id: ContentId,
79}
80
81struct FlatlandInstance {
86 flatland: FlatlandPtr,
87 view_ref: ui_views::ViewRef,
88 root_transform_id: TransformId,
89 parent_viewport_watcher: ui_comp::ParentViewportWatcherProxy,
90 focuser: ui_views::FocuserProxy,
91}
92
93impl FlatlandInstance {
94 fn new(
95 flatland: ui_comp::FlatlandProxy,
96 view_creation_token: ui_views::ViewCreationToken,
97 id_generator: &mut scenic::flatland::IdGenerator,
98 ) -> Result<FlatlandInstance, Error> {
99 let (parent_viewport_watcher, parent_viewport_watcher_request) =
100 create_proxy::<ui_comp::ParentViewportWatcherMarker>();
101
102 let (focuser, focuser_request) = create_proxy::<ui_views::FocuserMarker>();
103
104 let view_bound_protocols = ui_comp::ViewBoundProtocols {
105 view_focuser: Some(focuser_request),
106 ..Default::default()
107 };
108
109 let view_identity = ui_views::ViewIdentityOnCreation::from(scenic::ViewRefPair::new()?);
110 let view_ref = scenic::duplicate_view_ref(&view_identity.view_ref)?;
111 flatland.create_view2(
112 view_creation_token,
113 view_identity,
114 view_bound_protocols,
115 parent_viewport_watcher_request,
116 )?;
117
118 let root_transform_id = id_generator.next_transform_id();
119 flatland.create_transform(&root_transform_id)?;
120 flatland.set_root_transform(&root_transform_id)?;
121 flatland.set_hit_regions(&root_transform_id, &[])?;
122
123 Ok(FlatlandInstance {
124 flatland: Arc::new(flatland),
125 view_ref,
126 root_transform_id,
127 parent_viewport_watcher,
128 focuser,
129 })
130 }
131}
132
133fn request_present_with_pingback(
134 presentation_sender: &PresentationSender,
135) -> Result<oneshot::Receiver<()>, Error> {
136 let (sender, receiver) = oneshot::channel::<()>();
137 presentation_sender.unbounded_send(PresentationMessage::RequestPresentWithPingback(sender))?;
138 Ok(receiver)
139}
140
141async fn setup_child_view(
142 parent_flatland: &FlatlandInstance,
143 viewport_creation_token: scenic::flatland::ViewportCreationToken,
144 id_generator: &mut scenic::flatland::IdGenerator,
145 client_viewport_size: math::SizeU,
146) -> Result<ui_comp::ChildViewWatcherProxy, Error> {
147 let child_viewport_transform_id = id_generator.next_transform_id();
148 let child_viewport_content_id = id_generator.next_content_id();
149
150 let (child_view_watcher, child_view_watcher_request) =
151 create_proxy::<ui_comp::ChildViewWatcherMarker>();
152
153 {
154 let flatland = &parent_flatland.flatland;
155 flatland.create_transform(&child_viewport_transform_id)?;
156 flatland.add_child(&parent_flatland.root_transform_id, &child_viewport_transform_id)?;
157
158 let link_properties = ui_comp::ViewportProperties {
159 logical_size: Some(client_viewport_size),
160 ..Default::default()
161 };
162
163 flatland.create_viewport(
164 &child_viewport_content_id,
165 viewport_creation_token,
166 &link_properties,
167 child_view_watcher_request,
168 )?;
169 flatland.set_content(&child_viewport_transform_id, &child_viewport_content_id)?;
170 }
171
172 Ok(child_view_watcher)
173}
174
175pub struct SceneManager {
222 _display: ui_comp::FlatlandDisplayProxy,
224
225 client_viewport_size: math::SizeU,
228
229 root_flatland: FlatlandInstance,
234
235 _pointerinjector_flatland: FlatlandInstance,
244
245 scene_flatland: FlatlandInstance,
249
250 context_view_ref: ui_views::ViewRef,
253 target_view_ref: ui_views::ViewRef,
254
255 root_flatland_presentation_sender: PresentationSender,
257 _pointerinjector_flatland_presentation_sender: PresentationSender,
258 scene_flatland_presentation_sender: PresentationSender,
259
260 scene_root_viewport_ids: RefCell<Option<TransformContentIdPair>>,
264
265 id_generator: RefCell<scenic::flatland::IdGenerator>,
268
269 viewport_hanging_get: Rc<RefCell<InjectorViewportHangingGet>>,
272
273 _viewport_publisher: Rc<RefCell<InjectorViewportPublisher>>,
276
277 cursor_transform_id: Option<TransformId>,
279
280 cursor_visibility: Cell<bool>,
282
283 display_metrics: DisplayMetrics,
285
286 device_pixel_ratio: f32,
290
291 set_root_view_lock: futures::lock::Mutex<()>,
293
294 _tasks: RefCell<Vec<fasync::Task<()>>>,
296}
297
298#[async_trait(?Send)]
313pub trait SceneManagerTrait {
314 async fn set_root_view(
320 &self,
321 viewport_creation_token: ui_views::ViewportCreationToken,
322 view_ref: Option<ui_views::ViewRef>,
323 ) -> Result<(), Error>;
324
325 async fn set_root_view_deprecated(
330 &self,
331 view_provider: ui_app::ViewProviderProxy,
332 ) -> Result<ui_views::ViewRef, Error>;
333
334 fn present_root_view(&self);
336
337 fn set_cursor_position(&self, position_physical_px: Position);
349
350 fn set_cursor_visibility(&self, visible: bool);
355
356 fn get_pointerinjection_view_refs(&self) -> (ui_views::ViewRef, ui_views::ViewRef);
358
359 fn get_pointerinjection_display_size(&self) -> crate::lib::Size;
362
363 fn get_pointerinjector_viewport_watcher_subscription(&self) -> InjectorViewportSubscriber;
366
367 fn get_display_metrics(&self) -> &DisplayMetrics;
368
369 fn manage_task(&self, task: fasync::Task<()>);
371}
372
373#[async_trait(?Send)]
374impl SceneManagerTrait for SceneManager {
375 async fn set_root_view(
381 &self,
382 viewport_creation_token: ui_views::ViewportCreationToken,
383 _view_ref: Option<ui_views::ViewRef>,
384 ) -> Result<(), Error> {
385 let _guard = self.set_root_view_lock.lock().await;
386 self.set_root_view_internal(viewport_creation_token).await.map(|_view_ref| {})
387 }
388
389 async fn set_root_view_deprecated(
394 &self,
395 view_provider: ui_app::ViewProviderProxy,
396 ) -> Result<ui_views::ViewRef, Error> {
397 let _guard = self.set_root_view_lock.lock().await;
398 let link_token_pair = scenic::flatland::ViewCreationTokenPair::new()?;
399
400 view_provider.create_view2(ui_app::CreateView2Args {
403 view_creation_token: Some(link_token_pair.view_creation_token),
404 ..Default::default()
405 })?;
406
407 self.set_root_view_internal(link_token_pair.viewport_creation_token).await
408 }
409
410 fn present_root_view(&self) {
412 self.root_flatland_presentation_sender
413 .unbounded_send(PresentationMessage::RequestPresent)
414 .expect("send failed");
415 }
416
417 fn get_pointerinjection_view_refs(&self) -> (ui_views::ViewRef, ui_views::ViewRef) {
419 (
420 scenic::duplicate_view_ref(&self.context_view_ref).expect("failed to copy ViewRef"),
421 scenic::duplicate_view_ref(&self.target_view_ref).expect("failed to copy ViewRef"),
422 )
423 }
424
425 fn set_cursor_position(&self, position_physical_px: Position) {
437 if let Some(cursor_transform_id) = self.cursor_transform_id {
438 let position_logical = position_physical_px / self.device_pixel_ratio;
439 let x =
440 position_logical.x.round() as i32 - physical_cursor_size(CURSOR_HOTSPOT.0) as i32;
441 let y =
442 position_logical.y.round() as i32 - physical_cursor_size(CURSOR_HOTSPOT.1) as i32;
443 self.root_flatland
444 .flatland
445 .set_translation(&cursor_transform_id, &fmath::Vec_ { x, y })
446 .expect("fidl error");
447 self.root_flatland_presentation_sender
448 .unbounded_send(PresentationMessage::RequestPresent)
449 .expect("send failed");
450 }
451 }
452
453 fn set_cursor_visibility(&self, visible: bool) {
458 if let Some(cursor_transform_id) = self.cursor_transform_id {
459 if self.cursor_visibility.get() != visible {
460 self.cursor_visibility.set(visible);
461 let flatland = &self.root_flatland.flatland;
462 if visible {
463 flatland
464 .add_child(&self.root_flatland.root_transform_id, &cursor_transform_id)
465 .expect("failed to add cursor to scene");
466 } else {
467 flatland
468 .remove_child(&self.root_flatland.root_transform_id, &cursor_transform_id)
469 .expect("failed to remove cursor from scene");
470 }
471 self.root_flatland_presentation_sender
472 .unbounded_send(PresentationMessage::RequestPresent)
473 .expect("send failed");
474 }
475 }
476 }
477
478 fn get_pointerinjection_display_size(&self) -> Size {
481 self.display_metrics.size_in_pixels()
483 }
484
485 fn get_pointerinjector_viewport_watcher_subscription(&self) -> InjectorViewportSubscriber {
488 self.viewport_hanging_get.borrow_mut().new_subscriber()
489 }
490
491 fn get_display_metrics(&self) -> &DisplayMetrics {
492 &self.display_metrics
493 }
494
495 fn manage_task(&self, task: fasync::Task<()>) {
496 self._tasks.borrow_mut().push(task);
497 }
498}
499
500const ROOT_VIEW_DEBUG_NAME: &str = "SceneManager Display";
501const POINTER_INJECTOR_DEBUG_NAME: &str = "SceneManager PointerInjector";
502const SCENE_DEBUG_NAME: &str = "SceneManager Scene";
503const ROOT_VIEW_PRESENT_TRACING_NAME: &CStr = c"Flatland::PerAppPresent[SceneManager Display]";
504const POINTER_INJECTOR_PRESENT_TRACING_NAME: &CStr =
505 c"Flatland::PerAppPresent[SceneManager PointerInjector]";
506const SCENE_TRACING_NAME: &CStr = c"Flatland::PerAppPresent[SceneManager Scene]";
507
508impl SceneManager {
509 #[allow(clippy::vec_init_then_push, reason = "mass allow for https://fxbug.dev/381896734")]
510 pub async fn new(
511 display: ui_comp::FlatlandDisplayProxy,
512 singleton_display_info: singleton_display::InfoProxy,
513 root_flatland: ui_comp::FlatlandProxy,
514 pointerinjector_flatland: ui_comp::FlatlandProxy,
515 scene_flatland: ui_comp::FlatlandProxy,
516 a11y_view_provider: Option<a11y_scene::ProviderProxy>,
517 display_rotation: u64,
518 display_pixel_density: Option<f32>,
519 viewing_distance: Option<ViewingDistance>,
520 ) -> Result<Self, Error> {
521 let mut tasks = vec![start_exit_on_scenic_closed_task(display.clone())];
524
525 let mut id_generator = scenic::flatland::IdGenerator::new();
526
527 let pointerinjector_viewport_transform_id = id_generator.next_transform_id();
530 let pointerinjector_viewport_content_id = id_generator.next_content_id();
531
532 root_flatland.set_debug_name(ROOT_VIEW_DEBUG_NAME)?;
533 pointerinjector_flatland.set_debug_name(POINTER_INJECTOR_DEBUG_NAME)?;
534 scene_flatland.set_debug_name(SCENE_DEBUG_NAME)?;
535
536 let root_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
537 let root_flatland = FlatlandInstance::new(
538 root_flatland,
539 root_view_creation_pair.view_creation_token,
540 &mut id_generator,
541 )?;
542
543 let pointerinjector_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
544 let pointerinjector_flatland = FlatlandInstance::new(
545 pointerinjector_flatland,
546 pointerinjector_view_creation_pair.view_creation_token,
547 &mut id_generator,
548 )?;
549
550 let scene_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
551 let scene_flatland = FlatlandInstance::new(
552 scene_flatland,
553 scene_view_creation_pair.view_creation_token,
554 &mut id_generator,
555 )?;
556
557 let info = singleton_display_info.get_metrics().await?;
559 let extent_in_px =
560 info.extent_in_px.ok_or_else(|| anyhow::anyhow!("Did not receive display size"))?;
561 let display_metrics = DisplayMetrics::new(
562 Size { width: extent_in_px.width as f32, height: extent_in_px.height as f32 },
563 display_pixel_density,
564 viewing_distance,
565 None,
566 );
567
568 display.set_device_pixel_ratio(&fmath::VecF {
569 x: display_metrics.pixels_per_pip(),
570 y: display_metrics.pixels_per_pip(),
571 })?;
572
573 {
575 let (_, child_view_watcher_request) = create_proxy::<ui_comp::ChildViewWatcherMarker>();
578
579 display.set_content(
580 root_view_creation_pair.viewport_creation_token,
581 child_view_watcher_request,
582 )?;
583 }
584
585 let layout_info = root_flatland.parent_viewport_watcher.get_layout().await?;
588 let root_viewport_size = layout_info
589 .logical_size
590 .ok_or_else(|| anyhow::anyhow!("Did not receive layout info from the display"))?;
591
592 let (
593 display_rotation_enum,
594 injector_viewport_translation,
595 flip_injector_viewport_dimensions,
596 ) = match display_rotation % 360 {
597 0 => Ok((ui_comp::Orientation::Ccw0Degrees, math::Vec_ { x: 0, y: 0 }, false)),
598 90 => Ok((
599 ui_comp::Orientation::Ccw270Degrees,
603 math::Vec_ { x: root_viewport_size.width as i32, y: 0 },
604 true,
605 )),
606 180 => Ok((
607 ui_comp::Orientation::Ccw180Degrees,
608 math::Vec_ {
609 x: root_viewport_size.width as i32,
610 y: root_viewport_size.height as i32,
611 },
612 false,
613 )),
614 270 => Ok((
615 ui_comp::Orientation::Ccw90Degrees,
619 math::Vec_ { x: 0, y: root_viewport_size.height as i32 },
620 true,
621 )),
622 _ => Err(anyhow::anyhow!("Invalid display rotation; must be {{0,90,180,270}}")),
623 }?;
624 let client_viewport_size = match flip_injector_viewport_dimensions {
625 true => {
626 math::SizeU { width: root_viewport_size.height, height: root_viewport_size.width }
627 }
628 false => {
629 math::SizeU { width: root_viewport_size.width, height: root_viewport_size.height }
630 }
631 };
632
633 {
635 let flatland = &root_flatland.flatland;
636 flatland.create_transform(&pointerinjector_viewport_transform_id)?;
637 flatland.add_child(
638 &root_flatland.root_transform_id,
639 &pointerinjector_viewport_transform_id,
640 )?;
641 flatland
642 .set_orientation(&pointerinjector_viewport_transform_id, display_rotation_enum)?;
643 flatland.set_translation(
644 &pointerinjector_viewport_transform_id,
645 &injector_viewport_translation,
646 )?;
647
648 let link_properties = ui_comp::ViewportProperties {
649 logical_size: Some(client_viewport_size),
650 ..Default::default()
651 };
652
653 let (_, child_view_watcher_request) = create_proxy::<ui_comp::ChildViewWatcherMarker>();
654
655 flatland.create_viewport(
656 &pointerinjector_viewport_content_id,
657 pointerinjector_view_creation_pair.viewport_creation_token,
658 &link_properties,
659 child_view_watcher_request,
660 )?;
661 flatland.set_content(
662 &pointerinjector_viewport_transform_id,
663 &pointerinjector_viewport_content_id,
664 )?;
665 }
666
667 let mut a11y_view_watcher: Option<ui_comp::ChildViewWatcherProxy> = None;
668 match a11y_view_provider {
669 Some(a11y_view_provider) => {
670 let a11y_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
671
672 a11y_view_watcher = Some(
674 setup_child_view(
675 &pointerinjector_flatland,
676 a11y_view_creation_pair.viewport_creation_token,
677 &mut id_generator,
678 client_viewport_size,
679 )
680 .await?,
681 );
682
683 a11y_view_provider.create_view(
685 a11y_view_creation_pair.view_creation_token,
686 scene_view_creation_pair.viewport_creation_token,
687 )?;
688 }
689 None => {
690 let _ = setup_child_view(
692 &pointerinjector_flatland,
693 scene_view_creation_pair.viewport_creation_token,
694 &mut id_generator,
695 client_viewport_size,
696 )
697 .await?;
698 }
699 }
700
701 let (root_flatland_presentation_sender, root_receiver) = unbounded();
703 tasks.push(start_flatland_presentation_loop(
704 root_receiver,
705 Arc::downgrade(&root_flatland.flatland),
706 ROOT_VIEW_DEBUG_NAME.to_string(),
707 ));
708 let (pointerinjector_flatland_presentation_sender, pointerinjector_receiver) = unbounded();
709 tasks.push(start_flatland_presentation_loop(
710 pointerinjector_receiver,
711 Arc::downgrade(&pointerinjector_flatland.flatland),
712 POINTER_INJECTOR_DEBUG_NAME.to_string(),
713 ));
714 let (scene_flatland_presentation_sender, scene_receiver) = unbounded();
715 tasks.push(start_flatland_presentation_loop(
716 scene_receiver,
717 Arc::downgrade(&scene_flatland.flatland),
718 SCENE_DEBUG_NAME.to_string(),
719 ));
720
721 let mut pingback_channels = Vec::new();
722 pingback_channels.push(request_present_with_pingback(&root_flatland_presentation_sender)?);
723 pingback_channels
724 .push(request_present_with_pingback(&pointerinjector_flatland_presentation_sender)?);
725 pingback_channels.push(request_present_with_pingback(&scene_flatland_presentation_sender)?);
726
727 if let Some(a11y_view_watcher) = a11y_view_watcher {
728 let a11y_view_status = a11y_view_watcher.get_status().await?;
730 match a11y_view_status {
731 ui_comp::ChildViewStatus::ContentHasPresented => {}
732 }
733 }
734
735 let device_pixel_ratio = display_metrics.pixels_per_pip();
737 let viewport_hanging_get: Rc<RefCell<InjectorViewportHangingGet>> =
738 create_viewport_hanging_get({
739 InjectorViewportSpec {
740 width: display_metrics.width_in_pixels() as f32,
741 height: display_metrics.height_in_pixels() as f32,
742 scale: 1. / device_pixel_ratio,
743 x_offset: 0.,
744 y_offset: 0.,
745 }
746 });
747 let viewport_publisher =
748 Rc::new(RefCell::new(viewport_hanging_get.borrow_mut().new_publisher()));
749
750 let context_view_ref = scenic::duplicate_view_ref(&root_flatland.view_ref)?;
751 let target_view_ref = scenic::duplicate_view_ref(&pointerinjector_flatland.view_ref)?;
752
753 for receiver in pingback_channels {
755 _ = receiver.await;
756 }
757
758 Ok(SceneManager {
759 _display: display,
760 client_viewport_size,
761 root_flatland,
762 _pointerinjector_flatland: pointerinjector_flatland,
763 scene_flatland,
764 context_view_ref,
765 target_view_ref,
766 root_flatland_presentation_sender,
767 _pointerinjector_flatland_presentation_sender:
768 pointerinjector_flatland_presentation_sender,
769 scene_flatland_presentation_sender,
770 scene_root_viewport_ids: RefCell::new(None),
771 id_generator: RefCell::new(id_generator),
772 viewport_hanging_get,
773 _viewport_publisher: viewport_publisher,
774 cursor_transform_id: None,
775 cursor_visibility: Cell::new(true),
776 display_metrics,
777 device_pixel_ratio,
778 set_root_view_lock: futures::lock::Mutex::new(()),
779 _tasks: RefCell::new(tasks),
780 })
781 }
782
783 async fn set_root_view_internal(
784 &self,
785 viewport_creation_token: ui_views::ViewportCreationToken,
786 ) -> Result<ui_views::ViewRef> {
787 {
789 let mut scene_root_viewport_ids = self.scene_root_viewport_ids.borrow_mut();
790 if let Some(ids) = &*scene_root_viewport_ids {
791 let flatland = &self.scene_flatland.flatland;
792 flatland
793 .set_content(&ids.transform_id, &ContentId { value: 0 })
794 .context("could not set content")?;
795 flatland.remove_child(&self.scene_flatland.root_transform_id, &ids.transform_id)?;
796 flatland
797 .release_transform(&ids.transform_id)
798 .context("could not release transform")?;
799 let _ = flatland.release_viewport(&ids.content_id);
800 }
801 *scene_root_viewport_ids = None;
802 }
803
804 let ids = {
806 let mut id_generator = self.id_generator.borrow_mut();
807 TransformContentIdPair {
808 transform_id: id_generator.next_transform_id(),
809 content_id: id_generator.next_content_id(),
810 }
811 };
812 let (child_view_watcher, child_view_watcher_request) =
813 create_proxy::<ui_comp::ChildViewWatcherMarker>();
814 {
815 let flatland = &self.scene_flatland.flatland;
816 let viewport_properties = ui_comp::ViewportProperties {
817 logical_size: Some(self.client_viewport_size),
818 ..Default::default()
819 };
820 flatland.create_viewport(
821 &ids.content_id,
822 viewport_creation_token,
823 &viewport_properties,
824 child_view_watcher_request,
825 )?;
826 flatland.create_transform(&ids.transform_id).context("could not create transform")?;
827 flatland.add_child(&self.scene_flatland.root_transform_id, &ids.transform_id)?;
828 flatland
829 .set_content(&ids.transform_id, &ids.content_id)
830 .context("could not set content #2")?;
831 }
832 *self.scene_root_viewport_ids.borrow_mut() = Some(ids);
833
834 let mut pingback_channels = Vec::new();
838 pingback_channels.push(
839 request_present_with_pingback(&self.scene_flatland_presentation_sender)
840 .context("could not request present with pingback")?,
841 );
842
843 let _child_status = child_view_watcher
844 .get_status()
845 .on_timeout(fasync::MonotonicInstant::after(DEFAULT_VIEW_CONNECTION_TIMEOUT), || {
846 make_timeout_error("fuchsia.ui.composition.ChildViewWatcher")
847 })
848 .await
849 .context("could not call get_status")?;
850 let child_view_ref = child_view_watcher
851 .get_view_ref()
852 .on_timeout(fasync::MonotonicInstant::after(DEFAULT_VIEW_CONNECTION_TIMEOUT), || {
853 make_timeout_error("fuchsia.ui.composition.ChildViewWatcher")
854 })
855 .await
856 .context("could not get view_ref")?;
857 let child_view_ref_copy =
858 scenic::duplicate_view_ref(&child_view_ref).context("could not duplicate view_ref")?;
859
860 let request_focus_result = self
861 .root_flatland
862 .focuser
863 .request_focus(child_view_ref)
864 .on_timeout(fasync::MonotonicInstant::after(DEFAULT_VIEW_CONNECTION_TIMEOUT), || {
865 make_timeout_error("fuchsia.ui.views.Focuser")
866 })
867 .await;
868 match request_focus_result {
869 Err(e) => warn!("Request focus failed with err: {}", e),
870 Ok(Err(value)) => warn!("Request focus failed with err: {:?}", value),
871 Ok(_) => {}
872 }
873 pingback_channels.push(
874 request_present_with_pingback(&self.root_flatland_presentation_sender)
875 .context("could not request present with pingback #2")?,
876 );
877
878 for receiver in pingback_channels {
880 _ = receiver.await;
881 }
882
883 Ok(child_view_ref_copy)
884 }
885}
886
887fn make_timeout_error<T>(protocol_name: &'static str) -> Result<T, fidl::Error> {
888 Err(fidl::Error::ClientChannelClosed { epitaph: fidl::Epitaph::PeerClosed, protocol_name })
889}
890
891pub fn create_viewport_hanging_get(
892 initial_spec: InjectorViewportSpec,
893) -> Rc<RefCell<InjectorViewportHangingGet>> {
894 let notify_fn: InjectorViewportChangeFn = Box::new(|viewport_spec, responder| {
895 if let Err(fidl_error) = responder.send(&(*viewport_spec).into()) {
896 info!("Viewport hanging get notification, FIDL error: {}", fidl_error);
897 }
898 true
900 });
901
902 Rc::new(RefCell::new(hanging_get::HangingGet::new(initial_spec, notify_fn)))
903}
904
905pub fn start_exit_on_scenic_closed_task(
906 flatland_proxy: ui_comp::FlatlandDisplayProxy,
907) -> fasync::Task<()> {
908 fasync::Task::local(async move {
909 let _ = flatland_proxy.on_closed().await;
910 info!("Scenic died, closing SceneManager too.");
911 process::exit(1);
912 })
913}
914
915pub fn start_flatland_presentation_loop(
916 mut receiver: PresentationReceiver,
917 weak_flatland: Weak<ui_comp::FlatlandProxy>,
918 debug_name: String,
919) -> fasync::Task<()> {
920 fasync::Task::local(async move {
921 let mut present_count = 0;
922 let scheduler = ThroughputScheduler::new();
923 let mut flatland_event_stream = {
924 if let Some(flatland) = weak_flatland.upgrade() {
925 flatland.take_event_stream()
926 } else {
927 warn!(
928 "Failed to upgrade Flatand weak ref; exiting presentation loop for {debug_name}"
929 );
930 return;
931 }
932 };
933
934 let mut channels_awaiting_pingback = VecDeque::from([Vec::new()]);
935
936 loop {
937 futures::select! {
938 message = receiver.next() => {
939 match message {
940 Some(PresentationMessage::RequestPresent) => {
941 scheduler.request_present();
942 }
943 Some(PresentationMessage::RequestPresentWithPingback(channel)) => {
944 channels_awaiting_pingback.back_mut().unwrap().push(channel);
945 scheduler.request_present();
946 }
947 None => {}
948 }
949 }
950 flatland_event = flatland_event_stream.next() => {
951 match flatland_event {
952 Some(Ok(ui_comp::FlatlandEvent::OnNextFrameBegin{ values })) => {
953 trace::duration!("scene_manager", "SceneManager::OnNextFrameBegin",
954 "debug_name" => &*debug_name);
955 let credits = values
956 .additional_present_credits
957 .expect("Present credits must exist");
958 let infos = values
959 .future_presentation_infos
960 .expect("Future presentation infos must exist")
961 .iter()
962 .map(
963 |x| PresentationInfo{
964 latch_point: zx::MonotonicInstant::from_nanos(x.latch_point.unwrap()),
965 presentation_time: zx::MonotonicInstant::from_nanos(
966 x.presentation_time.unwrap())
967 })
968 .collect();
969 scheduler.on_next_frame_begin(credits, infos);
970 }
971 Some(Ok(ui_comp::FlatlandEvent::OnFramePresented{ frame_presented_info })) => {
972 trace::duration!("scene_manager", "SceneManager::OnFramePresented",
973 "debug_name" => &*debug_name);
974 let actual_presentation_time =
975 zx::MonotonicInstant::from_nanos(frame_presented_info.actual_presentation_time);
976 let presented_infos: Vec<PresentedInfo> =
977 frame_presented_info.presentation_infos
978 .into_iter()
979 .map(|x| x.into())
980 .collect();
981
982 for _ in 0..presented_infos.len() {
985 for channel in channels_awaiting_pingback.pop_back().unwrap() {
986 _ = channel.send(());
987 }
988 }
989
990 scheduler.on_frame_presented(actual_presentation_time, presented_infos);
991 }
992 Some(Ok(ui_comp::FlatlandEvent::OnError{ error })) => {
993 error!(
994 "Received FlatlandError code: {}; exiting listener loop for {debug_name}",
995 error.into_primitive()
996 );
997 return;
998 }
999 _ => {}
1000 }
1001 }
1002 present_parameters = scheduler.wait_to_update().fuse() => {
1003 trace::duration!("scene_manager", "SceneManager::Present",
1004 "debug_name" => &*debug_name);
1005
1006 match debug_name.as_str() {
1007 ROOT_VIEW_DEBUG_NAME => {
1008 trace::flow_begin!("gfx", ROOT_VIEW_PRESENT_TRACING_NAME, present_count.into());
1009 }
1010 POINTER_INJECTOR_DEBUG_NAME => {
1011 trace::flow_begin!("gfx", POINTER_INJECTOR_PRESENT_TRACING_NAME, present_count.into());
1012 }
1013 SCENE_DEBUG_NAME => {
1014 trace::flow_begin!("gfx", SCENE_TRACING_NAME, present_count.into());
1015 }
1016 _ => {
1017 warn!("SceneManager::Present with unknown debug_name {:?}", debug_name);
1018 }
1019 }
1020 present_count += 1;
1021 channels_awaiting_pingback.push_front(Vec::new());
1022 if let Some(flatland) = weak_flatland.upgrade() {
1023 flatland
1024 .present(present_parameters.into())
1025 .expect("Present failed for {debug_name}");
1026 } else {
1027 warn!(
1028 "Failed to upgrade Flatand weak ref; exiting listener loop for {debug_name}"
1029 );
1030 return;
1031 }
1032 }
1033 }
1034 }
1035 })
1036}
1037
1038pub fn handle_pointer_injector_configuration_setup_request_stream(
1039 mut request_stream: PointerInjectorConfigurationSetupRequestStream,
1040 scene_manager: Rc<dyn SceneManagerTrait>,
1041) -> fasync::Task<()> {
1042 fasync::Task::local(async move {
1043 let subscriber = scene_manager.get_pointerinjector_viewport_watcher_subscription();
1044
1045 loop {
1046 let request = request_stream.try_next().await;
1047 match request {
1048 Ok(Some(PointerInjectorConfigurationSetupRequest::GetViewRefs { responder })) => {
1049 let (context_view_ref, target_view_ref) =
1050 scene_manager.get_pointerinjection_view_refs();
1051 if let Err(e) = responder.send(context_view_ref, target_view_ref) {
1052 warn!("Failed to send GetViewRefs() response: {}", e);
1053 }
1054 }
1055 Ok(Some(PointerInjectorConfigurationSetupRequest::WatchViewport { responder })) => {
1056 if let Err(e) = subscriber.register(responder) {
1057 warn!("Failed to register WatchViewport() subscriber: {}", e);
1058 }
1059 }
1060 Ok(None) => {
1061 return;
1062 }
1063 Err(e) => {
1064 error!("Error obtaining SetupRequest: {}", e);
1065 return;
1066 }
1067 }
1068 }
1069 })
1070}