Skip to main content

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