• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::mem::MaybeUninit;
15 use std::sync::Once;
16 
17 use super::task_manager::TaskManagerTx;
18 use crate::manage::events::{StateEvent, TaskManagerEvent};
19 use crate::service::client::ClientManagerEntry;
20 use crate::utils::c_wrapper::CStringWrapper;
21 use crate::utils::{call_once, CommonEventSubscriber, CommonEventWant};
22 
23 pub(crate) struct AppStateListener {
24     client_manager: ClientManagerEntry,
25     task_manager: TaskManagerTx,
26 }
27 
28 static mut APP_STATE_LISTENER: MaybeUninit<AppStateListener> = MaybeUninit::uninit();
29 static ONCE: Once = Once::new();
30 
31 impl AppStateListener {
init(client_manager: ClientManagerEntry, task_manager: TaskManagerTx)32     pub(crate) fn init(client_manager: ClientManagerEntry, task_manager: TaskManagerTx) {
33         unsafe {
34             call_once(&ONCE, || {
35                 APP_STATE_LISTENER.write(AppStateListener {
36                     client_manager,
37                     task_manager,
38                 });
39             });
40             RegisterAPPStateCallback(app_state_change_callback);
41             RegisterProcessDiedCallback(process_died_callback);
42         }
43     }
44 
register()45     pub(crate) fn register() {
46         if ONCE.is_completed() {
47             unsafe {
48                 RegisterAPPStateCallback(app_state_change_callback);
49                 RegisterProcessDiedCallback(process_died_callback);
50             }
51         } else {
52             error!("ONCE not completed");
53         }
54     }
55 }
56 
app_state_change_callback(uid: i32, state: i32, _pid: i32)57 extern "C" fn app_state_change_callback(uid: i32, state: i32, _pid: i32) {
58     if state == 2 {
59         unsafe {
60             APP_STATE_LISTENER
61                 .assume_init_ref()
62                 .task_manager
63                 .notify_foreground_app_change(uid as u64)
64         };
65     } else if state == 4 {
66         unsafe {
67             APP_STATE_LISTENER
68                 .assume_init_ref()
69                 .task_manager
70                 .notify_app_background(uid as u64)
71         };
72     }
73 }
74 
process_died_callback(uid: i32, state: i32, pid: i32, bundle_name: CStringWrapper)75 extern "C" fn process_died_callback(uid: i32, state: i32, pid: i32, bundle_name: CStringWrapper) {
76     debug!(
77         "Receives process change, uid {} pid {} state {}",
78         uid, pid, state
79     );
80     let name = bundle_name.to_string();
81     if name.starts_with("com.") && name.ends_with(".hmos.hiviewx") {
82         unsafe {
83             APP_STATE_LISTENER
84                 .assume_init_ref()
85                 .task_manager
86                 .notify_special_process_terminate(uid as u64);
87         }
88         info!("hiviewx terminate. {:?}, {:?}", uid, pid);
89     }
90 
91     if state == 5 {
92         info!("Receives process died, uid {} pid {}", uid, pid);
93         unsafe {
94             APP_STATE_LISTENER
95                 .assume_init_ref()
96                 .client_manager
97                 .notify_process_terminate(pid as u64)
98         };
99     }
100 }
101 
102 pub(crate) struct AppUninstallSubscriber {
103     task_manager: TaskManagerTx,
104 }
105 
106 impl AppUninstallSubscriber {
new(task_manager: TaskManagerTx) -> Self107     pub(crate) fn new(task_manager: TaskManagerTx) -> Self {
108         Self { task_manager }
109     }
110 }
111 
112 impl CommonEventSubscriber for AppUninstallSubscriber {
on_receive_event(&self, _code: i32, _data: String, want: CommonEventWant)113     fn on_receive_event(&self, _code: i32, _data: String, want: CommonEventWant) {
114         if let Some(uid) = want.get_int_param("uid") {
115             info!("Receive app uninstall event, uid: {}", uid);
116             self.task_manager
117                 .send_event(TaskManagerEvent::State(StateEvent::AppUninstall(
118                     uid as u64,
119                 )));
120         }
121     }
122 }
123 
124 #[cfg(feature = "oh")]
125 extern "C" {
RegisterAPPStateCallback(f: extern "C" fn(i32, i32, i32))126     fn RegisterAPPStateCallback(f: extern "C" fn(i32, i32, i32));
RegisterProcessDiedCallback(f: extern "C" fn(i32, i32, i32, CStringWrapper))127     fn RegisterProcessDiedCallback(f: extern "C" fn(i32, i32, i32, CStringWrapper));
128 }
129