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 std::collections::HashSet;
15 use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
16 use std::sync::{Mutex, Once};
17
18 pub(crate) use ffi::*;
19
20 use super::database::RequestDb;
21 use crate::manage::events::TaskManagerEvent;
22 use crate::manage::task_manager::TaskManagerTx;
23 use crate::utils::{call_once, runtime_spawn};
24
25 #[derive(Debug)]
26 pub(crate) enum AccountEvent {
27 Remove(i32),
28 Changed,
29 }
30
31 pub(crate) static FOREGROUND_ACCOUNT: AtomicI32 = AtomicI32::new(0);
32 pub(crate) static BACKGROUND_ACCOUNTS: Mutex<Option<Vec<i32>>> = Mutex::new(None);
33 static UPDATE_FLAG: AtomicBool = AtomicBool::new(false);
34 static mut TASK_MANAGER_TX: Option<TaskManagerTx> = None;
35
remove_account_tasks(user_id: i32)36 pub(crate) fn remove_account_tasks(user_id: i32) {
37 info!("delete database task, uid {}", user_id);
38 let request_db = RequestDb::get_instance();
39 request_db.delete_all_account_tasks(user_id);
40 }
41
update_accounts(task_manager: TaskManagerTx)42 pub(crate) fn update_accounts(task_manager: TaskManagerTx) {
43 if UPDATE_FLAG
44 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
45 .is_ok()
46 {
47 runtime_spawn(AccountUpdater::new(task_manager).update());
48 }
49 }
50
query_active_accounts() -> (u64, HashSet<u64>)51 pub(crate) fn query_active_accounts() -> (u64, HashSet<u64>) {
52 let mut active_accounts = HashSet::new();
53 let foreground_account = FOREGROUND_ACCOUNT.load(Ordering::SeqCst) as u64;
54 active_accounts.insert(foreground_account);
55 if let Some(background_accounts) = BACKGROUND_ACCOUNTS.lock().unwrap().as_ref() {
56 for account in background_accounts.iter() {
57 active_accounts.insert(*account as u64);
58 }
59 }
60 (foreground_account, active_accounts)
61 }
62
63 struct AccountUpdater {
64 change_flag: bool,
65 task_manager: TaskManagerTx,
66 }
67
68 impl AccountUpdater {
new(task_manager: TaskManagerTx) -> Self69 fn new(task_manager: TaskManagerTx) -> Self {
70 Self {
71 change_flag: false,
72 task_manager,
73 }
74 }
75
76 #[cfg_attr(not(feature = "oh"), allow(unused))]
update(mut self)77 async fn update(mut self) {
78 info!("AccountUpdate Start");
79 let old_foreground = FOREGROUND_ACCOUNT.load(Ordering::SeqCst);
80 let old_background = BACKGROUND_ACCOUNTS.lock().unwrap().clone();
81
82 #[cfg(feature = "oh")]
83 if let Some(foreground_account) = get_foreground_account().await {
84 if old_foreground != foreground_account {
85 self.change_flag = true;
86 FOREGROUND_ACCOUNT.store(foreground_account, Ordering::SeqCst);
87 }
88 }
89
90 #[cfg(feature = "oh")]
91 if let Some(background_accounts) = get_background_accounts().await {
92 if !old_background.is_some_and(|old_background| old_background == background_accounts) {
93 self.change_flag = true;
94 *BACKGROUND_ACCOUNTS.lock().unwrap() = Some(background_accounts);
95 }
96 }
97 }
98 }
99
100 impl Drop for AccountUpdater {
drop(&mut self)101 fn drop(&mut self) {
102 info!("AccountUpdate Finished");
103 UPDATE_FLAG.store(false, Ordering::SeqCst);
104 if self.change_flag {
105 info!("AccountInfo changed, notify task manager");
106 self.task_manager
107 .send_event(TaskManagerEvent::Account(AccountEvent::Changed));
108 }
109 }
110 }
111
112 #[cfg(feature = "oh")]
get_foreground_account() -> Option<i32>113 async fn get_foreground_account() -> Option<i32> {
114 let mut foreground_account = 0;
115 for i in 0..10 {
116 let res = GetForegroundOsAccount(&mut foreground_account);
117 if res == 0 {
118 return Some(foreground_account);
119 } else {
120 error!("GetForegroundOsAccount failed: {} retry {} times", res, i);
121 sys_event!(
122 ExecFault,
123 DfxCode::OS_ACCOUNT_FAULT_01,
124 &format!("GetForegroundOsAccount failed: {} retry {} times", res, i)
125 );
126 ylong_runtime::time::sleep(std::time::Duration::from_millis(500)).await;
127 }
128 }
129 None
130 }
131
132 #[cfg(feature = "oh")]
get_background_accounts() -> Option<Vec<i32>>133 async fn get_background_accounts() -> Option<Vec<i32>> {
134 for i in 0..10 {
135 let mut accounts = vec![];
136 let res = GetBackgroundOsAccounts(&mut accounts);
137 if res == 0 {
138 return Some(accounts);
139 } else {
140 error!("GetBackgroundOsAccounts failed: {} retry {} times", res, i);
141 sys_event!(
142 ExecFault,
143 DfxCode::INVALID_IPC_MESSAGE_A00,
144 &format!("GetBackgroundOsAccounts failed: {} retry {} times", res, i)
145 );
146
147 ylong_runtime::time::sleep(std::time::Duration::from_millis(500)).await;
148 }
149 }
150 None
151 }
152
153 #[cfg(feature = "oh")]
registry_account_subscribe(task_manager: TaskManagerTx)154 pub(crate) fn registry_account_subscribe(task_manager: TaskManagerTx) {
155 static ONCE: Once = Once::new();
156
157 call_once(&ONCE, || unsafe {
158 TASK_MANAGER_TX = Some(task_manager.clone());
159 });
160
161 info!("registry_account_subscribe");
162
163 loop {
164 let ret = RegistryAccountSubscriber(
165 OS_ACCOUNT_SUBSCRIBE_TYPE::SWITCHED,
166 Box::new(task_manager.clone()),
167 |_, _| {},
168 |_new_id, _old_id, task_manager| update_accounts(task_manager.clone()),
169 );
170
171 if ret != 0 {
172 error!(
173 "registry_account_switch_subscribe failed: {} retry 500ms later",
174 ret
175 );
176 sys_event!(
177 ExecFault,
178 DfxCode::OS_ACCOUNT_FAULT_00,
179 &format!(
180 "registry_account_switch_subscribe failed: {} retry 500ms later",
181 ret
182 )
183 );
184 std::thread::sleep(std::time::Duration::from_millis(500));
185 } else {
186 break;
187 }
188 }
189
190 loop {
191 let ret = RegistryAccountSubscriber(
192 OS_ACCOUNT_SUBSCRIBE_TYPE::ACTIVATED,
193 Box::new(task_manager.clone()),
194 |_id, task_manager| update_accounts(task_manager.clone()),
195 |_, _, _| {},
196 );
197
198 if ret != 0 {
199 error!(
200 "registry_account_active_subscribe failed: {} retry 500ms later",
201 ret
202 );
203 sys_event!(
204 ExecFault,
205 DfxCode::OS_ACCOUNT_FAULT_00,
206 &format!(
207 "registry_account_active_subscribe failed: {} retry 500ms later",
208 ret
209 )
210 );
211 std::thread::sleep(std::time::Duration::from_millis(500));
212 } else {
213 break;
214 }
215 }
216
217 loop {
218 let ret = RegistryAccountSubscriber(
219 OS_ACCOUNT_SUBSCRIBE_TYPE::REMOVED,
220 Box::new(task_manager.clone()),
221 |id, task_manager| {
222 task_manager.send_event(TaskManagerEvent::Account(AccountEvent::Remove(*id)));
223 },
224 |_, _, _| {},
225 );
226
227 if ret != 0 {
228 error!(
229 "registry_account_remove_subscribe failed: {} retry 500ms later",
230 ret
231 );
232 sys_event!(
233 ExecFault,
234 DfxCode::OS_ACCOUNT_FAULT_00,
235 &format!(
236 "registry_account_remove_subscribe failed: {} retry 500ms later",
237 ret
238 )
239 );
240
241 std::thread::sleep(std::time::Duration::from_millis(500));
242 } else {
243 break;
244 }
245 }
246
247 loop {
248 let ret = RegistryAccountSubscriber(
249 OS_ACCOUNT_SUBSCRIBE_TYPE::STOPPED,
250 Box::new(task_manager.clone()),
251 |_id, task_manager| update_accounts(task_manager.clone()),
252 |_, _, _| {},
253 );
254
255 if ret != 0 {
256 error!(
257 "registry_account_stop_subscribe failed: {} retry 500ms later",
258 ret
259 );
260 sys_event!(
261 ExecFault,
262 DfxCode::OS_ACCOUNT_FAULT_00,
263 &format!(
264 "registry_account_stop_subscribe failed: {} retry 500ms later",
265 ret
266 )
267 );
268
269 std::thread::sleep(std::time::Duration::from_millis(500));
270 } else {
271 break;
272 }
273 }
274
275 update_accounts(task_manager.clone());
276 }
277
278 impl RequestDb {
delete_all_account_tasks(&self, user_id: i32)279 pub(crate) fn delete_all_account_tasks(&self, user_id: i32) {
280 let sql = format!("DELETE from request_task WHERE uid/200000 = {}", user_id);
281 if let Err(e) = self.execute(&sql) {
282 error!("delete_all_account_tasks failed: {}", e);
283 sys_event!(
284 ExecFault,
285 DfxCode::RDB_FAULT_04,
286 &format!("delete_all_account_tasks failed: {}", e)
287 );
288 };
289 }
290 }
291
292 #[cxx::bridge(namespace = "OHOS::Request")]
293 mod ffi {
294 #[repr(i32)]
295 enum OS_ACCOUNT_SUBSCRIBE_TYPE {
296 INVALID_TYPE = -1,
297 ACTIVATED = 0,
298 ACTIVATING,
299 UNLOCKED,
300 CREATED,
301 REMOVED,
302 STOPPING,
303 STOPPED,
304 SWITCHING,
305 SWITCHED,
306 }
307
308 extern "Rust" {
309 type TaskManagerTx;
310 }
311
312 unsafe extern "C++" {
313 include!("account.h");
314 include!("os_account_subscribe_info.h");
315 include!("c_request_database.h");
316
317 type OS_ACCOUNT_SUBSCRIBE_TYPE;
GetForegroundOsAccount(account: &mut i32) -> i32318 fn GetForegroundOsAccount(account: &mut i32) -> i32;
GetBackgroundOsAccounts(accounts: &mut Vec<i32>) -> i32319 fn GetBackgroundOsAccounts(accounts: &mut Vec<i32>) -> i32;
320
RegistryAccountSubscriber( subscribe_type: OS_ACCOUNT_SUBSCRIBE_TYPE, task_manager: Box<TaskManagerTx>, on_accounts_changed: fn(&i32, task_manager: &TaskManagerTx), on_accounts_switch: fn(&i32, &i32, task_manager: &TaskManagerTx), ) -> i32321 fn RegistryAccountSubscriber(
322 subscribe_type: OS_ACCOUNT_SUBSCRIBE_TYPE,
323 task_manager: Box<TaskManagerTx>,
324 on_accounts_changed: fn(&i32, task_manager: &TaskManagerTx),
325 on_accounts_switch: fn(&i32, &i32, task_manager: &TaskManagerTx),
326 ) -> i32;
327
GetOhosAccountUid() -> String328 fn GetOhosAccountUid() -> String;
329 }
330 }
331
332 #[cfg(feature = "oh")]
333 #[cfg(test)]
334 mod ut_account {
335 include!("../../tests/ut/manage/ut_account.rs");
336 }
337