• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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