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