1 /*
2 * Copyright (c) 2023 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 std::{
19 fs,
20 time::{Duration, Instant},
21 };
22
23 use asset_db_operator::database_file_upgrade::check_and_split_db;
24 use samgr::manage::SystemAbilityManager;
25 use system_ability_fwk::{
26 ability::{Ability, Handler},
27 cxx_share::SystemAbilityOnDemandReason,
28 };
29 use ylong_runtime::{builder::RuntimeBuilder, time::sleep};
30
31 use asset_common::{AutoCounter, CallingInfo, Counter, OwnerType};
32 use asset_crypto_manager::crypto_manager::CryptoManager;
33 use asset_definition::{log_throw_error, AssetMap, ErrCode, Result};
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 operations;
41 mod stub;
42 mod sys_event;
43 mod trace_scope;
44 mod unload_handler;
45
46 use sys_event::upload_system_event;
47 use trace_scope::TraceScope;
48
49 use crate::unload_handler::{UnloadHandler, DELAYED_UNLOAD_TIME_IN_SEC, SEC_TO_MILLISEC};
50
51 struct AssetAbility;
52
unload_sa(duration: u64)53 pub(crate) fn unload_sa(duration: u64) {
54 let unload_handler = UnloadHandler::get_instance();
55 unload_handler.lock().unwrap().update_task(ylong_runtime::spawn(async move {
56 sleep(Duration::from_secs(duration)).await;
57 SystemAbilityManager::unload_system_ability(SA_ID);
58 }));
59 }
60
61 impl Ability for AssetAbility {
on_start_with_reason(&self, reason: SystemAbilityOnDemandReason, handler: Handler)62 fn on_start_with_reason(&self, reason: SystemAbilityOnDemandReason, handler: Handler) {
63 logi!("[INFO]Start asset service, reason_id: {:?}", reason.reason_id);
64 if let Err(e) = RuntimeBuilder::new_multi_thread().worker_num(1).build_global() {
65 loge!("[WARNING]Ylong new global thread failed! {}", e);
66 };
67 let func_name = hisysevent::function!();
68 let start = Instant::now();
69 let _trace = TraceScope::trace(func_name);
70 let calling_info = CallingInfo::new_self();
71
72 let _ = upload_system_event(start_service(handler), &calling_info, start, func_name);
73 common_event::handle_common_event(reason);
74 }
75
on_active(&self, reason: SystemAbilityOnDemandReason)76 fn on_active(&self, reason: SystemAbilityOnDemandReason) {
77 logi!("[INFO]Asset service on_active.");
78 common_event::handle_common_event(reason);
79 }
80
on_idle(&self, _reason: SystemAbilityOnDemandReason) -> i3281 fn on_idle(&self, _reason: SystemAbilityOnDemandReason) -> i32 {
82 let crypto_manager = CryptoManager::get_instance();
83 let max_crypto_expire_duration = crypto_manager.lock().unwrap().max_crypto_expire_duration();
84 if max_crypto_expire_duration > 0 {
85 logi!("[INFO]Asset service on idle not success, delay time: {}s", max_crypto_expire_duration);
86 return max_crypto_expire_duration as i32 * SEC_TO_MILLISEC;
87 }
88
89 let counter = Counter::get_instance();
90 if counter.lock().unwrap().count() > 0 {
91 logi!(
92 "[INFO]Asset service on idle not success for use_account: {}, delay time: {}s",
93 counter.lock().unwrap().count(),
94 DELAYED_UNLOAD_TIME_IN_SEC
95 );
96 return DELAYED_UNLOAD_TIME_IN_SEC * SEC_TO_MILLISEC;
97 }
98 logi!("[INFO]Asset service on_idle.");
99 0
100 }
101
on_stop(&self)102 fn on_stop(&self) {
103 logi!("[INFO]Asset service on_stop");
104 common_event::unsubscribe();
105 }
106 }
107
upgrade_process() -> Result<()>108 async fn upgrade_process() -> Result<()> {
109 let _counter_user = AutoCounter::new();
110 for entry in fs::read_dir(DE_ROOT_PATH)? {
111 let entry = entry?;
112 if let Ok(user_id) = entry.file_name().to_string_lossy().parse::<i32>() {
113 check_and_split_db(user_id)?;
114 }
115 }
116 Ok(())
117 }
118
start_service(handler: Handler) -> Result<()>119 fn start_service(handler: Handler) -> Result<()> {
120 let asset_plugin = AssetPlugin::get_instance();
121 match asset_plugin.load_plugin() {
122 Ok(loader) => {
123 let _tr = loader
124 .init(Box::new(AssetContext { user_id: 0, calling_info: CallingInfo::new(0, OwnerType::Hap, vec![]) }));
125 logi!("load plugin success.");
126 },
127 Err(_) => loge!("load plugin failed."),
128 }
129
130 common_event::subscribe();
131 if !handler.publish(AssetService::new(handler.clone())) {
132 return log_throw_error!(ErrCode::IpcError, "Asset publish stub object failed");
133 };
134 let _handle = ylong_runtime::spawn(upgrade_process());
135 Ok(())
136 }
137
138 #[used]
139 #[link_section = ".init_array"]
140 static A: extern "C" fn() = {
init()141 extern "C" fn init() {
142 let Some(sa) = AssetAbility.build_system_ability(SA_ID, true) else {
143 loge!("Create Asset service failed.");
144 return;
145 };
146
147 sa.register();
148 }
149 init
150 };
151
152 struct AssetService {
153 system_ability: system_ability_fwk::ability::Handler,
154 }
155
156 macro_rules! execute {
157 ($func:path, $calling_info:expr, $($args:expr),+) => {{
158 let func_name = hisysevent::function!();
159 let start = Instant::now();
160 let _trace = TraceScope::trace(func_name);
161 // Create de database directory if not exists.
162 create_user_de_dir($calling_info.user_id())?;
163 upload_system_event($func($calling_info, $($args),+), $calling_info, start, func_name)
164 }};
165 }
166
167 impl AssetService {
new(handler: system_ability_fwk::ability::Handler) -> Self168 pub(crate) fn new(handler: system_ability_fwk::ability::Handler) -> Self {
169 Self { system_ability: handler }
170 }
171
add(&self, calling_info: &CallingInfo, attributes: &AssetMap) -> Result<()>172 fn add(&self, calling_info: &CallingInfo, attributes: &AssetMap) -> Result<()> {
173 execute!(operations::add, calling_info, attributes)
174 }
175
remove(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()>176 fn remove(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()> {
177 execute!(operations::remove, calling_info, query)
178 }
179
update(&self, calling_info: &CallingInfo, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()>180 fn update(&self, calling_info: &CallingInfo, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()> {
181 execute!(operations::update, calling_info, query, attributes_to_update)
182 }
183
pre_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<u8>>184 fn pre_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<u8>> {
185 execute!(operations::pre_query, calling_info, query)
186 }
187
query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<AssetMap>>188 fn query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<Vec<AssetMap>> {
189 execute!(operations::query, calling_info, query)
190 }
191
post_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()>192 fn post_query(&self, calling_info: &CallingInfo, query: &AssetMap) -> Result<()> {
193 execute!(operations::post_query, calling_info, query)
194 }
195 }
196