Skip to main content

fxfs_platform/fuchsia/
power.rs

1// Copyright 2026 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 fidl_fuchsia_power_battery::{
6    BatteryInfoWatcherMarker, BatteryInfoWatcherRequest, BatteryManagerMarker, ChargeSource,
7};
8use fidl_fuchsia_power_system as _;
9use fuchsia_component_client::connect_to_protocol;
10use futures::stream::{BoxStream, StreamExt};
11use fxfs::filesystem::{PowerManager, WakeLease};
12use fxfs::log::*;
13use std::sync::Arc;
14use zx::HandleBased;
15
16pub struct FuchsiaPowerManager {}
17
18impl FuchsiaPowerManager {
19    pub fn new() -> Arc<Self> {
20        Arc::new(Self {})
21    }
22}
23
24impl PowerManager for FuchsiaPowerManager {
25    fn watch_battery(self: Arc<Self>) -> BoxStream<'static, (bool, WakeLease)> {
26        let (watcher_client, watcher_stream) =
27            fidl::endpoints::create_request_stream::<BatteryInfoWatcherMarker>();
28
29        match connect_to_protocol::<BatteryManagerMarker>() {
30            Ok(proxy) => {
31                if let Err(error) = proxy.watch(watcher_client) {
32                    error!(error:?; "Failed to register battery watcher");
33                    return futures::stream::empty().boxed();
34                }
35            }
36            Err(error) => {
37                warn!(error:?; "Failed to connect to BatteryManager");
38                return futures::stream::empty().boxed();
39            }
40        }
41
42        futures::stream::unfold(watcher_stream, |mut stream| async move {
43            match stream.next().await {
44                Some(Ok(BatteryInfoWatcherRequest::OnChangeBatteryInfo {
45                    info,
46                    wake_lease,
47                    responder,
48                })) => {
49                    let _ = responder.send();
50                    // We check charge_source rather than charge_status because charge_status
51                    // might be FULL even when the device has just been taken off charge.
52                    // charge_source will indicate the actual source of power for the system.
53                    let on_battery = !matches!(
54                        info.charge_source,
55                        Some(ChargeSource::AcAdapter)
56                            | Some(ChargeSource::Usb)
57                            | Some(ChargeSource::Wireless)
58                    );
59                    let handle =
60                        wake_lease.map_or(zx::NullableHandle::invalid(), |l| l.into_handle());
61                    Some(((on_battery, handle), stream))
62                }
63                Some(Err(error)) => {
64                    error!(error:?; "Battery watcher stream error");
65                    None
66                }
67                None => None,
68            }
69        })
70        .boxed()
71    }
72}