lease_management/
flush_trigger.rs

1// Copyright 2025 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 async_trait::async_trait;
6use futures::stream::StreamExt;
7use log::warn;
8use {fidl_fuchsia_power_system as fsag, fuchsia_trace as ftrace};
9
10/// Uses |fuchsia.power.system/SuspendBlocker|s to determine when to
11/// trigger a flush.
12pub struct FlushTrigger {
13    sag: fsag::ActivityGovernorProxy,
14}
15
16impl FlushTrigger {
17    pub fn new(sag: fsag::ActivityGovernorProxy) -> Self {
18        Self { sag }
19    }
20
21    /// Calls |flusher| when it receives
22    /// |fuchsia.power.system/SuspendBlocker.BeforeSuspend| and
23    /// replies to the request *AFTER* |flusher.flush| returns.
24    pub async fn run<'a>(&self, flusher: &dyn FlushListener) -> Result<(), fidl::Error> {
25        let (client, server) = fidl::endpoints::create_endpoints::<fsag::SuspendBlockerMarker>();
26
27        let registration_lease = self
28            .sag
29            .register_suspend_blocker(fsag::ActivityGovernorRegisterSuspendBlockerRequest {
30                suspend_blocker: Some(client),
31                name: Some("flush_trigger".into()),
32                ..Default::default()
33            })
34            .await?
35            .expect("error registering suspend blocker");
36        drop(registration_lease);
37
38        let mut request_stream = server.into_stream();
39
40        while let Some(req) = request_stream.next().await {
41            match req {
42                Ok(fsag::SuspendBlockerRequest::BeforeSuspend { responder }) => {
43                    ftrace::duration!(crate::TRACE_CATEGORY, c"flush-triggered");
44                    flusher.flush().await;
45                    let _ = responder.send();
46                }
47                Ok(fsag::SuspendBlockerRequest::AfterResume { responder }) => {
48                    let _ = responder.send();
49                }
50                Ok(fsag::SuspendBlockerRequest::_UnknownMethod { .. }) => {
51                    warn!("unrecognized SuspendBlocker method, ignoring");
52                }
53                Err(_) => continue,
54            }
55        }
56        Ok(())
57    }
58}
59
60#[async_trait]
61pub trait FlushListener {
62    async fn flush(&self);
63}