• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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