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(async move || {
61 fuchsia_async::Timer::new(target_monotonic).await;
62 kernel_ref
63 .suspend_resume_manager
64 .timeout_wakeup_source(&WakeupSourceOrigin::WakeLock(clean_lock_string));
65 });
66 }
67
68 Ok(())
69 }
70
71 fn read(&self, current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
72 let wake_locks = current_task.kernel().suspend_resume_manager.lock().active_wake_locks();
73 let content = wake_locks.iter().map(|o| o.to_string()).join(" ") + "\n";
74 Ok(content.as_bytes().to_owned().into())
75 }
76}
77
78pub struct PowerWakeUnlockFile;
79
80impl PowerWakeUnlockFile {
81 pub fn new_node() -> impl FsNodeOps {
82 BytesFile::new_node(Self {})
83 }
84}
85
86impl BytesFileOps for PowerWakeUnlockFile {
87 fn write(&self, current_task: &CurrentTask, data: Vec<u8>) -> Result<(), Errno> {
89 let lock_str = std::str::from_utf8(&data).map_err(|_| errno!(EINVAL))?;
90 let clean_lock_str = lock_str.trim_end_matches('\n').to_string();
91 if !current_task
92 .kernel()
93 .suspend_resume_manager
94 .deactivate_wakeup_source(&WakeupSourceOrigin::WakeLock(clean_lock_str))
95 {
96 return error!(EPERM);
97 }
98 Ok(())
99 }
100
101 fn read(&self, current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
104 let wake_locks = current_task.kernel().suspend_resume_manager.lock().inactive_wake_locks();
105 let content = wake_locks.iter().map(|o| o.to_string()).join(" ") + "\n";
106 Ok(content.as_bytes().to_owned().into())
107 }
108}