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