Skip to main content

wake_lease/
wake_lease.rs

1// Copyright 2024 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.
4
5use anyhow::Result;
6use fidl_fuchsia_power_system as fsystem;
7
8pub struct WakeLease {
9    _token: fsystem::LeaseToken,
10}
11
12impl WakeLease {
13    pub async fn acquire(
14        activity_governor: &fsystem::ActivityGovernorProxy,
15        name: String,
16    ) -> Result<Self> {
17        let token = activity_governor
18            .acquire_wake_lease(&name)
19            .await?
20            .map_err(|e| anyhow::anyhow!("Failed to acquire wake lease: {:?}", e))?;
21        Ok(Self { _token: token })
22    }
23}
24
25#[cfg(test)]
26mod tests {
27    use super::*;
28    use anyhow::Context;
29    use fidl::endpoints::create_proxy_and_stream;
30    use fuchsia_async as fasync;
31    use futures::channel::mpsc;
32    use futures::prelude::*;
33
34    struct FakeActivityGovernor {
35        // Sends updates in server wake lease state (active, inactive).
36        wake_lease_active: mpsc::UnboundedSender<bool>,
37    }
38
39    impl FakeActivityGovernor {
40        async fn run(&self, stream: fsystem::ActivityGovernorRequestStream) -> Result<()> {
41            stream
42                .map(|request| request.context("failed request"))
43                .try_for_each(|request| async {
44                    match request {
45                        fsystem::ActivityGovernorRequest::AcquireWakeLease {
46                            name: _name,
47                            responder,
48                        } => {
49                            let (server_token, client_token) = fsystem::LeaseToken::create();
50                            let wake_lease_active = self.wake_lease_active.clone();
51                            assert!(wake_lease_active.unbounded_send(true).is_ok());
52
53                            // Listen for the client dropping its wake lease token.
54                            fasync::Task::local(async move {
55                                let _ = fasync::OnSignals::new(
56                                    server_token,
57                                    zx::Signals::EVENTPAIR_PEER_CLOSED,
58                                )
59                                .await;
60                                wake_lease_active
61                                    .unbounded_send(false)
62                                    .expect("server dropping wake lease status");
63                            })
64                            .detach();
65
66                            responder.send(Ok(client_token)).context("send failed")
67                        }
68                        _ => unreachable!(),
69                    }
70                })
71                .await
72        }
73    }
74
75    #[fasync::run_until_stalled(test)]
76    async fn test_acquire_then_release() -> Result<()> {
77        let (client, stream) = create_proxy_and_stream::<fsystem::ActivityGovernorMarker>();
78        let (wake_lease_active_tx, mut wake_lease_active_rx) = mpsc::unbounded::<bool>();
79
80        // Create a FakeActivityGovernor server and run it in the background.
81        fasync::Task::local(async move {
82            let server = FakeActivityGovernor { wake_lease_active: wake_lease_active_tx };
83            server.run(stream).await.expect("FakeActivityGovernor server completion");
84        })
85        .detach();
86
87        // Create and acquire a wake lease.
88        let wake_lease = WakeLease::acquire(&client, "example_wake_lease".to_string()).await?;
89
90        // Check that the server was notified about the acquired wake lease.
91        assert!(wake_lease_active_rx.next().await.expect("server wake lease call"));
92
93        // Release the wake lease and check that the server was notified.
94        drop(wake_lease);
95        assert!(!wake_lease_active_rx.next().await.expect("server wake lease call"));
96
97        Ok(())
98    }
99}