starnix_core/power/
wake_lock.rs1use crate::power::WakeupSourceOrigin;
6use crate::task::CurrentTask;
7use crate::vfs::FsNodeOps;
8use crate::vfs::pseudo::simple_file::{BytesFile, BytesFileOps};
9use itertools::Itertools;
10use starnix_uapi::errors::Errno;
11use starnix_uapi::{errno, error};
12use std::borrow::Cow;
13
14pub struct PowerWakeLockFile;
15
16impl PowerWakeLockFile {
17 pub fn new_node() -> impl FsNodeOps {
18 BytesFile::new_node(Self {})
19 }
20}
21
22impl BytesFileOps for PowerWakeLockFile {
23 fn write(&self, current_task: &CurrentTask, data: Vec<u8>) -> Result<(), Errno> {
31 let lock_str = std::str::from_utf8(&data).map_err(|_| errno!(EINVAL))?;
32 let clean_str = lock_str.trim_end_matches('\n');
33 let mut clean_str_split = clean_str.split(' ');
34 let Some(clean_lock_str) = clean_str_split.next() else {
35 return error!(EINVAL);
36 };
37
38 let target_monotonic = match clean_str_split.next() {
40 Some(timeout_str) => Some(
41 zx::MonotonicInstant::get() + zx::MonotonicDuration::from_nanos(
43 timeout_str
44 .parse()
45 .map_err(|_| errno!(EINVAL, "Failed to parse the timeout string"))?,
46 ),
47 ),
48 None => None,
49 };
50
51 current_task
52 .kernel()
53 .suspend_resume_manager
54 .activate_wakeup_source(WakeupSourceOrigin::WakeLock(clean_lock_str.to_owned()));
55
56 if let Some(target_monotonic) = target_monotonic {
58 let kernel_ref = current_task.kernel().clone();
59 let clean_lock_string = clean_lock_str.to_string();
60 current_task.kernel().kthreads.spawn_future(
61 move || async move {
62 fuchsia_async::Timer::new(target_monotonic).await;
63 kernel_ref
64 .suspend_resume_manager
65 .timeout_wakeup_source(&WakeupSourceOrigin::WakeLock(clean_lock_string));
66 },
67 "wake-lock-timeout",
68 );
69 }
70
71 Ok(())
72 }
73
74 fn read(&self, current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
75 let wake_locks = current_task.kernel().suspend_resume_manager.lock().active_wake_locks();
76 let content = wake_locks.iter().map(|o| o.to_string()).join(" ") + "\n";
77 Ok(content.as_bytes().to_owned().into())
78 }
79}
80
81pub struct PowerWakeUnlockFile;
82
83impl PowerWakeUnlockFile {
84 pub fn new_node() -> impl FsNodeOps {
85 BytesFile::new_node(Self {})
86 }
87}
88
89impl BytesFileOps for PowerWakeUnlockFile {
90 fn write(&self, current_task: &CurrentTask, data: Vec<u8>) -> Result<(), Errno> {
92 let lock_str = std::str::from_utf8(&data).map_err(|_| errno!(EINVAL))?;
93 let clean_lock_str = lock_str.trim_end_matches('\n').to_string();
94 if !current_task
95 .kernel()
96 .suspend_resume_manager
97 .deactivate_wakeup_source(&WakeupSourceOrigin::WakeLock(clean_lock_str))
98 {
99 return error!(EPERM);
100 }
101 Ok(())
102 }
103
104 fn read(&self, current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
107 let wake_locks = current_task.kernel().suspend_resume_manager.lock().inactive_wake_locks();
108 let content = wake_locks.iter().map(|o| o.to_string()).join(" ") + "\n";
109 Ok(content.as_bytes().to_owned().into())
110 }
111}