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