1 // Copyright (C) 2023 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 std::fmt::Debug;
15 
16 use ylong_runtime::sync::oneshot::{channel, Sender};
17 
18 use super::account::AccountEvent;
19 use crate::config::{Action, Mode};
20 use crate::error::ErrorCode;
21 use crate::info::TaskInfo;
22 use crate::task::config::TaskConfig;
23 use crate::task::info::{DumpAllInfo, DumpOneInfo};
24 use crate::task::reason::Reason;
25 use crate::utils::Recv;
26 
27 mod construct;
28 mod dump;
29 mod pause;
30 mod remove;
31 mod resume;
32 mod start;
33 mod stop;
34 
35 #[derive(Debug)]
36 pub(crate) enum TaskManagerEvent {
37     Service(ServiceEvent),
38     State(StateEvent),
39     Schedule(ScheduleEvent),
40     Task(TaskEvent),
41     Device(i32),
42     Account(AccountEvent),
43     Query(QueryEvent),
44     Reschedule,
45 }
46 
47 impl TaskManagerEvent {
construct(config: TaskConfig) -> (Self, Recv<Result<u32, ErrorCode>>)48     pub(crate) fn construct(config: TaskConfig) -> (Self, Recv<Result<u32, ErrorCode>>) {
49         let (tx, rx) = channel::<Result<u32, ErrorCode>>();
50         (
51             Self::Service(ServiceEvent::Construct(
52                 Box::new(ConstructMessage { config }),
53                 tx,
54             )),
55             Recv::new(rx),
56         )
57     }
58 
pause(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>)59     pub(crate) fn pause(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
60         let (tx, rx) = channel::<ErrorCode>();
61         (
62             Self::Service(ServiceEvent::Pause(uid, task_id, tx)),
63             Recv::new(rx),
64         )
65     }
66 
start(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>)67     pub(crate) fn start(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
68         let (tx, rx) = channel::<ErrorCode>();
69         (
70             Self::Service(ServiceEvent::Start(uid, task_id, tx)),
71             Recv::new(rx),
72         )
73     }
74 
stop(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>)75     pub(crate) fn stop(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
76         let (tx, rx) = channel::<ErrorCode>();
77         (
78             Self::Service(ServiceEvent::Stop(uid, task_id, tx)),
79             Recv::new(rx),
80         )
81     }
82 
remove(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>)83     pub(crate) fn remove(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
84         let (tx, rx) = channel::<ErrorCode>();
85         (
86             Self::Service(ServiceEvent::Remove(uid, task_id, tx)),
87             Recv::new(rx),
88         )
89     }
90 
resume(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>)91     pub(crate) fn resume(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
92         let (tx, rx) = channel::<ErrorCode>();
93         (
94             Self::Service(ServiceEvent::Resume(uid, task_id, tx)),
95             Recv::new(rx),
96         )
97     }
98 
dump_all() -> (Self, Recv<DumpAllInfo>)99     pub(crate) fn dump_all() -> (Self, Recv<DumpAllInfo>) {
100         let (tx, rx) = channel::<DumpAllInfo>();
101         (Self::Service(ServiceEvent::DumpAll(tx)), Recv::new(rx))
102     }
103 
dump_one(task_id: u32) -> (Self, Recv<Option<DumpOneInfo>>)104     pub(crate) fn dump_one(task_id: u32) -> (Self, Recv<Option<DumpOneInfo>>) {
105         let (tx, rx) = channel::<Option<DumpOneInfo>>();
106         (
107             Self::Service(ServiceEvent::DumpOne(task_id, tx)),
108             Recv::new(rx),
109         )
110     }
111 
network() -> Self112     pub(crate) fn network() -> Self {
113         Self::State(StateEvent::Network)
114     }
115 
subscribe(task_id: u32, token_id: u64) -> (Self, Recv<ErrorCode>)116     pub(crate) fn subscribe(task_id: u32, token_id: u64) -> (Self, Recv<ErrorCode>) {
117         let (tx, rx) = channel::<ErrorCode>();
118         (
119             Self::Task(TaskEvent::Subscribe(task_id, token_id, tx)),
120             Recv::new(rx),
121         )
122     }
123 }
124 
125 #[derive(Debug)]
126 pub(crate) enum QueryEvent {
127     Query(u32, Action, Sender<Option<TaskInfo>>),
128     Show(u32, u64, Sender<Option<TaskInfo>>),
129     Touch(u32, u64, String, Sender<Option<TaskInfo>>),
130 }
131 
132 pub(crate) enum ServiceEvent {
133     Construct(Box<ConstructMessage>, Sender<Result<u32, ErrorCode>>),
134     Pause(u64, u32, Sender<ErrorCode>),
135     Start(u64, u32, Sender<ErrorCode>),
136     Stop(u64, u32, Sender<ErrorCode>),
137     Remove(u64, u32, Sender<ErrorCode>),
138     Resume(u64, u32, Sender<ErrorCode>),
139     DumpOne(u32, Sender<Option<DumpOneInfo>>),
140     DumpAll(Sender<DumpAllInfo>),
141 }
142 
143 #[derive(Debug)]
144 pub(crate) enum TaskEvent {
145     Completed(u32, u64, Mode),
146     Failed(u32, u64, Reason, Mode),
147     Offline(u32, u64, Mode),
148     Running(u32, u64, Mode),
149     Subscribe(u32, u64, Sender<ErrorCode>),
150 }
151 
152 #[derive(Debug)]
153 pub(crate) enum StateEvent {
154     Network,
155     ForegroundApp(u64),
156     Background(u64),
157     BackgroundTimeout(u64),
158     SpecialTerminate(u64),
159 }
160 
161 pub(crate) struct ConstructMessage {
162     pub(crate) config: TaskConfig,
163 }
164 
165 impl Debug for ConstructMessage {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result166     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167         f.debug_struct("Construct")
168             .field("uid", &self.config.common_data.uid)
169             .field("task_id", &self.config.common_data.task_id)
170             .field("title", &self.config.title)
171             .field("mode", &self.config.method)
172             .field("version", &self.config.version)
173             .finish()
174     }
175 }
176 
177 impl Debug for ServiceEvent {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result178     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179         match self {
180             Self::Construct(message, _) => message.fmt(f),
181             Self::Pause(uid, task_id, _) => f
182                 .debug_struct("Pause")
183                 .field("uid", uid)
184                 .field("task_id", task_id)
185                 .finish(),
186             Self::Start(uid, task_id, _) => f
187                 .debug_struct("Start")
188                 .field("uid", uid)
189                 .field("task_id", task_id)
190                 .finish(),
191             Self::Stop(uid, task_id, _) => f
192                 .debug_struct("Stop")
193                 .field("uid", uid)
194                 .field("task_id", task_id)
195                 .finish(),
196             Self::Remove(uid, task_id, _) => f
197                 .debug_struct("Remove")
198                 .field("uid", uid)
199                 .field("task_id", task_id)
200                 .finish(),
201             Self::Resume(uid, task_id, _) => f
202                 .debug_struct("Resume")
203                 .field("uid", uid)
204                 .field("task_id", task_id)
205                 .finish(),
206             Self::DumpOne(task_id, _) => {
207                 f.debug_struct("DumpOne").field("task_id", task_id).finish()
208             }
209 
210             Self::DumpAll(_) => f.debug_struct("DumpAll").finish(),
211         }
212     }
213 }
214 
215 #[derive(Debug)]
216 pub(crate) enum ScheduleEvent {
217     ClearTimeoutTasks,
218     LogTasks,
219     RestoreAllTasks,
220     Unload,
221 }
222 
223 #[cfg(not(feature = "oh"))]
224 #[cfg(test)]
225 mod test {
226     use core::time;
227     use std::fs::File;
228 
229     use once_cell::sync::Lazy;
230 
231     use super::TaskManagerEvent;
232     use crate::config::{Action, ConfigBuilder, Mode};
233     use crate::error::ErrorCode;
234     use crate::manage::network::Network;
235     use crate::manage::task_manager::TaskManagerTx;
236     use crate::manage::TaskManager;
237     use crate::service::client::{ClientManager, ClientManagerEntry};
238     use crate::service::run_count::{RunCountManager, RunCountManagerEntry};
239 
240     static CLIENT: Lazy<ClientManagerEntry> = Lazy::new(|| ClientManager::init());
241     static RUN_COUNT_MANAGER: Lazy<RunCountManagerEntry> = Lazy::new(|| RunCountManager::init());
242     static NETWORK: Lazy<Network> = Lazy::new(|| Network::new());
243 
244     static TASK_MANGER: Lazy<TaskManagerTx> =
245         Lazy::new(|| TaskManager::init(RUN_COUNT_MANAGER.clone(), CLIENT.clone(), NETWORK.clone()));
build_task()246     fn build_task() {}
247 
init()248     fn init() {
249         let _ = env_logger::builder().is_test(true).try_init();
250         let _ = std::fs::create_dir("test_files/");
251     }
252 
253     #[test]
ut_task_manager_construct()254     fn ut_task_manager_construct() {
255         init();
256         let file_path = "test_files/ut_task_manager_construct.txt";
257 
258         let file = File::create(file_path).unwrap();
259         let config = ConfigBuilder::new()
260         .action(Action::Download)
261         .mode(Mode::BackGround)
262         .file_spec(file)
263         .url("https://www.gitee.com/tiga-ultraman/downloadTests/releases/download/v1.01/test.txt")
264         .redirect(true)
265         .build();
266         let (event, rx) = TaskManagerEvent::construct(config);
267         TASK_MANGER.send_event(event);
268         rx.get().unwrap().unwrap();
269     }
270 
271     #[test]
ut_task_manager_start()272     fn ut_task_manager_start() {
273         init();
274         let file_path = "test_files/ut_task_manager_construct.txt";
275 
276         let file = File::create(file_path).unwrap();
277         let uid = 111;
278         let config = ConfigBuilder::new()
279         .action(Action::Download)
280         .mode(Mode::BackGround)
281         .file_spec(file)
282         .url("https://sf3-cn.feishucdn.com/obj/ee-appcenter/47273f95/Feishu-win32_ia32-7.9.7-signed.exe")
283         .redirect(true)
284         .uid(uid)
285         .build();
286         let (event, rx) = TaskManagerEvent::construct(config.clone());
287         TASK_MANGER.send_event(event);
288         let task_id = rx.get().unwrap().unwrap();
289         let (event, rx) = TaskManagerEvent::start(uid, task_id);
290         TASK_MANGER.send_event(event);
291         let res = rx.get().unwrap();
292         assert_eq!(res, ErrorCode::ErrOk);
293         std::thread::sleep(time::Duration::from_secs(10));
294     }
295 
296     #[test]
ut_task_manager_pause_resume()297     fn ut_task_manager_pause_resume() {
298         init();
299         let file_path = "test_files/ut_task_manager_pause_resume.txt";
300 
301         let file = File::create(file_path).unwrap();
302         let uid = 111;
303         let config = ConfigBuilder::new()
304         .action(Action::Download)
305         .mode(Mode::BackGround)
306         .file_spec(file)
307         .url("https://sf3-cn.feishucdn.com/obj/ee-appcenter/47273f95/Feishu-win32_ia32-7.9.7-signed.exe")
308         .redirect(true)
309         .uid(uid)
310         .build();
311         let (event, rx) = TaskManagerEvent::construct(config.clone());
312         TASK_MANGER.send_event(event);
313         let task_id = rx.get().unwrap().unwrap();
314         let (event, _rx) = TaskManagerEvent::start(uid, task_id);
315         TASK_MANGER.send_event(event);
316         let (event, _rx) = TaskManagerEvent::pause(uid, task_id);
317         TASK_MANGER.send_event(event);
318         let (event, _rx) = TaskManagerEvent::resume(uid, task_id);
319         TASK_MANGER.send_event(event);
320         std::thread::sleep(time::Duration::from_secs(20));
321     }
322 
323     #[test]
ut_task_manager_stop_resume()324     fn ut_task_manager_stop_resume() {
325         init();
326         let file_path = "test_files/ut_task_manager_pause_resume.txt";
327 
328         let file = File::create(file_path).unwrap();
329         let uid = 111;
330         let config = ConfigBuilder::new()
331         .action(Action::Download)
332         .mode(Mode::BackGround)
333         .file_spec(file)
334         .url("https://sf3-cn.feishucdn.com/obj/ee-appcenter/47273f95/Feishu-win32_ia32-7.9.7-signed.exe")
335         .redirect(true)
336         .uid(uid)
337         .build();
338         let (event, rx) = TaskManagerEvent::construct(config.clone());
339         TASK_MANGER.send_event(event);
340         let task_id = rx.get().unwrap().unwrap();
341         let (event, _rx) = TaskManagerEvent::start(uid, task_id);
342         TASK_MANGER.send_event(event);
343         let (event, _rx) = TaskManagerEvent::stop(uid, task_id);
344         TASK_MANGER.send_event(event);
345         let (event, _rx) = TaskManagerEvent::resume(uid, task_id);
346         TASK_MANGER.send_event(event);
347         std::thread::sleep(time::Duration::from_secs(20));
348     }
349 }
350