Skip to main content

xpanse_api/
app.rs

1//! Application lifecycle and resource ownership.
2//!
3//! Apps lease capabilities from a [`Registry`] when they are created and must
4//! return every lease when they are released. This makes resource availability
5//! predictable as the platform switches between apps.
6
7use alloc::boxed::Box;
8use core::future::Future;
9use core::pin::Pin;
10
11use crate::registry::Registry;
12
13/// An application that can be selected and run by the xpanse firmware.
14///
15/// `can_run` should mirror the resource set acquired by `new`, without mutating
16/// the registry. After `run` completes, the platform passes the app to
17/// `release`, which must return all of its resource leases.
18///
19/// Apps run on core 1, so any task spawned will also run core 1
20///
21/// Apps can use slint ui or direct video to show stuff on the screen
22///
23/// # Example
24///
25/// ```ignore
26/// use std::{boxed::Box, future::Future, pin::Pin};
27/// use xpanse_api::{
28///     app::App,
29///     registry::{Registry, ResourceLease},
30/// };
31///
32/// struct StatusLed;
33///
34/// struct StatusApp {
35///     led: ResourceLease<StatusLed>,
36/// }
37///
38/// impl App for StatusApp {
39///     const NAME: &'static str = "Status";
40///
41///     fn can_run(registry: &Registry) -> bool {
42///         registry.has::<StatusLed>()
43///     }
44///
45///     fn new(registry: &mut Registry) -> Option<Self> {
46///         Some(Self { led: registry.take_resource()? })
47///     }
48///
49///     fn run<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = ()> + 'a>> {
50///         Box::pin(async move {
51///             let _led = self.led.resource_mut();
52///             // Drive the capability until the app decides to exit.
53///         })
54///     }
55///
56///     fn release(self, registry: &mut Registry) {
57///         registry.return_resource(self.led);
58///     }
59/// }
60/// ```
61pub trait App: Send {
62    /// User-facing name shown by the app picker.
63    const NAME: &'static str;
64
65    /// Runs the app until it exits.
66    ///
67    /// Resource leases held by `self` remain exclusive while this future is
68    /// alive. The returned future is not required to be [`Send`].
69    fn run<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = ()> + 'a>>;
70
71    /// Reports whether all resources required by this app are available.
72    ///
73    /// This method must not mutate `registry`. Use
74    /// [`Registry::has_resource_set`] when the app needs several distinct
75    /// physical resources.
76    fn can_run(registry: &Registry) -> bool
77    where
78        Self: Sized;
79
80    /// Leases the resources required to construct the app.
81    ///
82    /// Returns `None` if the resources are no longer available. Acquisition of
83    /// multiple resources should use [`Registry::take_resource_set`] so it is
84    /// atomic.
85    fn new(registry: &mut Registry) -> Option<Self>
86    where
87        Self: Sized;
88
89    /// Returns every resource lease held by the app to `registry`.
90    ///
91    /// Dropping a lease instead would permanently remove its complete physical
92    /// resource group from the registry.
93    fn release(self, registry: &mut Registry)
94    where
95        Self: Sized;
96}