1 /*
2 * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 //! This module implements the Asset service.
17
18 use ipc::parcel::MsgParcel;
19 use samgr::manage::SystemAbilityManager;
20 use std::{
21 fs,
22 time::{Duration, Instant},
23 };
24 use system_ability_fwk::{
25 ability::{Ability, Handler},
26 cxx_share::SystemAbilityOnDemandReason,
27 };
28 use ylong_runtime::builder::RuntimeBuilder;
29
30 use asset_common::{AutoCounter, CallingInfo, ConstAssetBlob, ConstAssetBlobArray, Counter, TaskManager};
31 use asset_crypto_manager::crypto_manager::CryptoManager;
32 use asset_db_operator::database_file_upgrade::check_and_split_db;
33 use asset_definition::{log_throw_error, AssetMap, ErrCode, Result, SyncResult};
34 use asset_file_operator::{common::DE_ROOT_PATH, de_operator::create_user_de_dir};
35 use asset_ipc::SA_ID;
36 use asset_log::{loge, logi};
37 use asset_plugin::asset_plugin::{AssetContext, AssetPlugin};
38
39 mod common_event;
40 mod data_size_mod;
41 mod operations;
42 mod stub;
43 mod sys_event;
44 mod trace_scope;
45 mod upgrade_operator;
46
47 use sys_event::upload_system_event;
48 use trace_scope::TraceScope;
49
50 use crate::data_size_mod::handle_data_size_upload;
51
52 struct AssetAbility;
53
54 trait WantParser<T> {
parse(&self) -> Result<T>55 fn parse(&self) -> Result<T>;
56 }
57
58 struct PackageInfo {
59 user_id: i32,
60 app_index: i32,
61 app_id: String,
62 developer_id: Option<String>,
63 group_ids: Option<Vec<String>>,
64 bundle_name: String,
65 }
66
67 #[repr(C)]
68 struct PackageInfoFfi {
69 user_id: i32,
70 app_index: i32,
71 owner: ConstAssetBlob,
72 developer_id: ConstAssetBlob,
73 group_ids: ConstAssetBlobArray,
74 bundle_name: ConstAssetBlob,
75 }
76
77 static DELAYED_UNLOAD_TIME_IN_SEC: i32 = 20;
78 static SEC_TO_MILLISEC: i32 = 1000;
79
80 impl PackageInfo {
developer_id(&self) -> &Option<String>81 fn developer_id(&self) -> &Option<String> {
82 &self.developer_id
83 }
84
group_ids(&self) -> &Option<Vec<String>>85 fn group_ids(&self) -> &Option<Vec<String>> {
86 &self.group_ids
87 }
88 }
89
unload_sa()90 pub(crate) fn unload_sa() {
91 ylong_runtime::spawn(async move {
92 loop {
93 ylong_runtime::time::sleep(Duration::from_secs(DELAYED_UNLOAD_TIME_IN_SEC as u64)).await;
94 let crypto_manager = CryptoManager::get_instance();
95 let max_crypto_expire_duration = crypto_manager.lock().unwrap().max_crypto_expire_duration();
96 if max_crypto_expire_duration > 0 {
97 continue;
98 }
99 let counter = Counter::get_instance();
100 if counter.lock().unwrap().count() > 0 {
101 continue;
102 }
103 let task_manager = TaskManager::get_instance();
104 if !task_manager.lock().unwrap().is_empty() {
105 continue;
106 }
107
108 SystemAbilityManager::unload_system_ability(SA_ID);
109 break;
110 }
111 });
112 }
113
114 impl Ability for AssetAbility {
on_start_with_reason(&self, reason: SystemAbilityOnDemandReason, handler: Handler)115 fn on_start_with_reason(&self, reason: SystemAbilityOnDemandReason, handler: Handler) {
116 logi!("[INFO]Start asset service, reason_id: {:?}", reason.reason_id);
117 if let Err(e) = RuntimeBuilder::new_multi_thread().worker_num(1).max_blocking_pool_size(1).build_global() {
118 loge!("[WARNING]Ylong new global thread failed! {}", e);
119 };
120 let func_name = hisysevent::function!();
121 let start = Instant::now();
122 let _trace = TraceScope::trace(func_name);
123 let calling_info = CallingInfo::new_self();
124 let _ = upload_system_event(start_service(handler), &calling_info, start, func_name, &AssetMap::new());
125 if let Err(e) = handle_data_size_upload() {
126 loge!("Failed to handle data upload: {}", e);
127 }
128 common_event::handle_common_event(reason);
129 }
130
on_active(&self, reason: SystemAbilityOnDemandReason)131 fn on_active(&self, reason: SystemAbilityOnDemandReason) {
132 logi!("[INFO]Asset service on_active.");
133 if let Err(e) = handle_data_size_upload() {
134 loge!("Failed to handle data upload: {}", e);
135 }
136 common_event::handle_common_event(reason);
137 }
138
on_idle(&self, _reason: SystemAbilityOnDemandReason) -> i32139 fn on_idle(&self, _reason: SystemAbilityOnDemandReason) -> i32 {
140 let crypto_manager = CryptoManager::get_instance();
141 let max_crypto_expire_duration = crypto_manager.lock().unwrap().max_crypto_expire_duration();
142 if max_crypto_expire_duration > 0 {
143 logi!("[INFO]Asset service on idle not success, delay time: {}s", max_crypto_expire_duration);
144 return max_crypto_expire_duration as i32 * SEC_TO_MILLISEC;
145 }
146
147 let counter = Counter::get_instance();
148 if counter.lock().unwrap().count() > 0 {
149 logi!(
150 "[INFO]Asset service on idle not success for use_account: {}, delay time: {}s",
151 counter.lock().unwrap().count(),
152 DELAYED_UNLOAD_TIME_IN_SEC
153 );
154 return DELAYED_UNLOAD_TIME_IN_SEC * SEC_TO_MILLISEC;
155 }
156 logi!("[INFO]Asset service on_idle.");
157 0
158 }
159
on_stop(&self)160 fn on_stop(&self) {
161 logi!("[INFO]Asset service on_stop");
162 let counter = Counter::get_instance();
163 counter.lock().unwrap().stop();
164 common_event::unsubscribe();
165 }
166
on_extension(&self, extension: String, data: &mut MsgParcel, reply: &mut MsgParcel) -> i32167 fn on_extension(&self, extension: String, data: &mut MsgParcel, reply: &mut MsgParcel) -> i32 {
168 logi!("[INFO]Asset on_extension, extension is {}", extension);
169 if let Ok(load) = AssetPlugin::get_instance().load_plugin() {
170 match load.on_sa_extension(extension, data, reply) {
171 Ok(()) => logi!("process sa extension event success."),
172 Err(code) => loge!("process sa extension event failed, code: {}", code),
173 };
174 }
175 logi!("[INFO]Asset on_extension end");
176 0
177 }
178 }
179
execute_upgrade_process()180 async fn execute_upgrade_process() {
181 match upgrade_process() {
182 Ok(()) => (),
183 Err(e) => loge!("upgrade failed, error is:[{}]", e.code),
184 }
185 }
186
upgrade_process() -> Result<()>187 fn upgrade_process() -> Result<()> {
188 let _counter_user = AutoCounter::new();
189 for entry in fs::read_dir(DE_ROOT_PATH)? {
190 let entry = entry?;
191 if let Ok(user_id) = entry.file_name().to_string_lossy().parse::<i32>() {
192 logi!("[INFO]start to check and split db in upgrade process.");
193 check_and_split_db(user_id)?;
194 }
195 }
196 Ok(())
197 }
198
start_service(handler: Handler) -> Result<()>199 fn start_service(handler: Handler) -> Result<()> {
200 let asset_plugin = AssetPlugin::get_instance();
201 match asset_plugin.load_plugin() {
202 Ok(loader) => {
203 let _tr = loader.init(Box::new(AssetContext { user_id: 0 }));
204 logi!("load plugin success.");
205 },
206 Err(_) => loge!("load plugin failed."),
207 }
208
209 if !handler.publish(AssetService::new(handler.clone())) {
210 return log_throw_error!(ErrCode::IpcError, "Asset publish stub object failed");
211 };
212 common_event::subscribe();
213 let handle = ylong_runtime::spawn(execute_upgrade_process());
214 let task_manager = TaskManager::get_instance();
215 task_manager.lock().unwrap().push_task(handle);
216 Ok(())
217 }
218
219 #[used]
220 #[link_section = ".init_array"]
221 static A: extern "C" fn() = {
init()222 extern "C" fn init() {
223 let Some(sa) = AssetAbility.build_system_ability(SA_ID, true) else {
224 loge!("Create Asset service failed.");
225 return;
226 };
227
228 sa.register();
229 }
230 init
231 };
232
233 struct AssetService {
234 system_ability: system_ability_fwk::ability::Handler,
235 }
236
237 macro_rules! execute {
238 ($func:path, $calling_info:expr, $first_arg:expr) => {{
239 let func_name = hisysevent::function!();
240 let start = Instant::now();
241 let _trace = TraceScope::trace(func_name);
242 // Create de database directory if not exists.
243 create_user_de_dir($calling_info.user_id())?;
244 upload_system_event($func($calling_info, $first_arg), $calling_info, start, func_name, $first_arg)
245 }};
246 ($func:path, $calling_info:expr, $first_arg:expr, $second_arg:expr) => {{
247 let func_name = hisysevent::function!();
248 let start = Instant::now();
249 let _trace = TraceScope::trace(func_name);
250 // Create de database directory if not exists.
251 create_user_de_dir($calling_info.user_id())?;
252 upload_system_event($func($calling_info, $first_arg, $second_arg), $calling_info, start, func_name, $first_arg)
253 }};
254 }
255
256 impl AssetService {
new(handler: system_ability_fwk::ability::Handler) -> Self257 pub(crate) fn new(handler: system_ability_fwk::ability::Handler) -> Self {
258 Self { system_ability: handler }
259 }
260
add(&self, calling_info: &CallingInfo, attributes: &AssetMap) -> Result<()>261 fn add(&self, calling_info: &CallingInfo, attributes: &AssetMap) -> Result<()> {
262 execute!(operations::add, calling_info, attributes)
263 }
264
remove(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()>265 fn remove(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()> {
266 execute!(operations::remove, calling_info, query)
267 }
268
update(&self, calling_info: &CallingInfo, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()>269 fn update(&self, calling_info: &CallingInfo, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()> {
270 execute!(operations::update, calling_info, query, attributes_to_update)
271 }
272
pre_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<u8>>273 fn pre_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<u8>> {
274 execute!(operations::pre_query, calling_info, query)
275 }
276
query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<AssetMap>>277 fn query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<AssetMap>> {
278 execute!(operations::query, calling_info, query)
279 }
280
post_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()>281 fn post_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()> {
282 execute!(operations::post_query, calling_info, query)
283 }
284
query_sync_result(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<SyncResult>285 fn query_sync_result(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<SyncResult> {
286 execute!(operations::query_sync_result, calling_info, query)
287 }
288 }
289