1 // Copyright (C) 2024 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use super::database::NotificationDb;
15 use super::ffi::{self, SubscribeNotification};
16 use super::NotificationDispatcher;
17 use crate::config::{Mode, Version};
18 use crate::error::ErrorCode;
19 use crate::info::{State, TaskInfo};
20 use crate::manage::database::RequestDb;
21 use crate::manage::events::TaskManagerEvent;
22 use crate::manage::task_manager::TaskManagerTx;
23 use crate::manage::TaskManager;
24 use crate::task::request_task::RequestTask;
25 use crate::utils::Recv;
26
cancel_notification(request_id: u32)27 pub(super) fn cancel_notification(request_id: u32) {
28 info!("cancel notification {}", request_id);
29 let ret = ffi::CancelNotification(request_id);
30 if ret != 0 {
31 error!("cancel notification failed {}", ret);
32 }
33 }
34
35 impl TaskManager {
attach_group(&self, uid: u64, task_ids: Vec<u32>, group_id: u32) -> ErrorCode36 pub(crate) fn attach_group(&self, uid: u64, task_ids: Vec<u32>, group_id: u32) -> ErrorCode {
37 for task_id in task_ids.iter().copied() {
38 let Some(mode) = RequestDb::get_instance().query_task_mode(task_id) else {
39 return ErrorCode::TaskNotFound;
40 };
41 if mode != Mode::BackGround {
42 return ErrorCode::TaskModeErr;
43 }
44 let Some(state) = RequestDb::get_instance().query_task_state(task_id) else {
45 return ErrorCode::TaskNotFound;
46 };
47 if state != State::Initialized.repr {
48 return ErrorCode::TaskStateErr;
49 }
50 }
51 if !NotificationDispatcher::get_instance().attach_group(task_ids, group_id, uid) {
52 return ErrorCode::GroupNotFound;
53 }
54 ErrorCode::ErrOk
55 }
56 }
57
58 pub(crate) trait NotificationCheck {
notification_check(&self, db: &NotificationDb) -> bool59 fn notification_check(&self, db: &NotificationDb) -> bool;
60 }
61
62 impl NotificationCheck for RequestTask {
notification_check(&self, db: &NotificationDb) -> bool63 fn notification_check(&self, db: &NotificationDb) -> bool {
64 notification_check_common(
65 self.conf.version,
66 self.conf.common_data.gauge,
67 self.conf.common_data.mode,
68 self.conf.common_data.background,
69 false,
70 ) && db.check_task_notification_available(&self.conf.common_data.task_id)
71 }
72 }
73
74 impl NotificationCheck for TaskInfo {
notification_check(&self, db: &NotificationDb) -> bool75 fn notification_check(&self, db: &NotificationDb) -> bool {
76 notification_check_common(
77 Version::from(self.common_data.version),
78 self.common_data.gauge,
79 Mode::from(self.common_data.mode),
80 RequestDb::get_instance().query_task_background(self.common_data.task_id),
81 true,
82 ) && db.check_task_notification_available(&self.common_data.task_id)
83 }
84 }
85
notification_check_common( version: Version, gauge: bool, mode: Mode, background: bool, completed_notify: bool, ) -> bool86 fn notification_check_common(
87 version: Version,
88 gauge: bool,
89 mode: Mode,
90 background: bool,
91 completed_notify: bool,
92 ) -> bool {
93 version == Version::API10 && mode == Mode::BackGround && (gauge || completed_notify)
94 || version == Version::API9 && background
95 }
96
97 pub struct TaskManagerWrapper {
98 task_manager: TaskManagerTx,
99 }
100
101 impl TaskManagerWrapper {
new(task_manager: TaskManagerTx) -> Self102 fn new(task_manager: TaskManagerTx) -> Self {
103 Self { task_manager }
104 }
105
pause_task(&self, task_id: u32) -> bool106 pub(crate) fn pause_task(&self, task_id: u32) -> bool {
107 self.event_inner(task_id, TaskManagerEvent::pause)
108 }
109
resume_task(&self, task_id: u32) -> bool110 pub(crate) fn resume_task(&self, task_id: u32) -> bool {
111 self.event_inner(task_id, TaskManagerEvent::resume)
112 }
113
stop_task(&self, task_id: u32) -> bool114 pub(crate) fn stop_task(&self, task_id: u32) -> bool {
115 self.event_inner(task_id, TaskManagerEvent::stop)
116 }
117
event_inner<F>(&self, task_id: u32, f: F) -> bool where F: Fn(u64, u32) -> (TaskManagerEvent, Recv<ErrorCode>),118 fn event_inner<F>(&self, task_id: u32, f: F) -> bool
119 where
120 F: Fn(u64, u32) -> (TaskManagerEvent, Recv<ErrorCode>),
121 {
122 let Some(uid) = RequestDb::get_instance().query_task_uid(task_id) else {
123 return false;
124 };
125 let (event, rx) = f(uid, task_id);
126 self.task_manager.send_event(event);
127 let Some(ret) = rx.get() else {
128 return false;
129 };
130 if ret != ErrorCode::ErrOk {
131 error!("notification_bar {} failed: {}", task_id, ret as u32);
132 return false;
133 }
134 true
135 }
136 }
137
subscribe_notification_bar(task_manager: TaskManagerTx)138 pub(crate) fn subscribe_notification_bar(task_manager: TaskManagerTx) {
139 SubscribeNotification(Box::new(TaskManagerWrapper::new(task_manager)));
140 }
141
142 impl RequestDb {
query_task_background(&self, task_id: u32) -> bool143 fn query_task_background(&self, task_id: u32) -> bool {
144 let sql = format!(
145 "SELECT background FROM request_task WHERE task_id = {}",
146 task_id
147 );
148 self.query_integer(&sql)
149 .first()
150 .map(|background: &i32| *background == 1)
151 .unwrap_or(false)
152 }
153
query_task_mode(&self, task_id: u32) -> Option<Mode>154 fn query_task_mode(&self, task_id: u32) -> Option<Mode> {
155 let sql = format!("SELECT mode FROM request_task WHERE task_id = {}", task_id);
156 self.query_integer(&sql)
157 .first()
158 .map(|mode: &i32| Mode::from(*mode as u8))
159 }
160 }
161