• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 stub of the Asset service.
17 
18 use asset_common::{AutoCounter, CallingInfo, Counter, OwnerType, ProcessInfo, ProcessInfoDetail};
19 use asset_db_operator::database_file_upgrade::construct_splited_db_name;
20 use ipc::{parcel::MsgParcel, remote::RemoteStub, IpcResult, IpcStatusCode};
21 
22 use asset_ipc::{deserialize_map, serialize_maps, serialize_sync_result, IpcCode, IPC_SUCCESS, SA_NAME};
23 use asset_log::{loge, logi};
24 use asset_plugin::asset_plugin::AssetPlugin;
25 use asset_sdk::{
26     log_throw_error,
27     plugin_interface::{
28         EventType, ExtDbMap, PARAM_NAME_APP_INDEX, PARAM_NAME_BUNDLE_NAME, PARAM_NAME_IS_HAP, PARAM_NAME_USER_ID,
29     },
30     AssetError, ErrCode, Result, Tag, Value,
31 };
32 
33 use crate::{AssetService, upgrade_operator::upgrade_single_clone_app_data};
34 
35 const REDIRECT_START_CODE: u32 = 200;
36 
37 const HAP_OWNER_TYPES: [OwnerType; 2] = [OwnerType::Hap, OwnerType::HapGroup];
38 
39 impl RemoteStub for AssetService {
on_remote_request( &self, code: u32, data: &mut ipc::parcel::MsgParcel, reply: &mut ipc::parcel::MsgParcel, ) -> i3240     fn on_remote_request(
41         &self,
42         code: u32,
43         data: &mut ipc::parcel::MsgParcel,
44         reply: &mut ipc::parcel::MsgParcel,
45     ) -> i32 {
46         let counter = Counter::get_instance();
47         if counter.lock().unwrap().is_stop() {
48             loge!("[FATAL]Service is stop.");
49             let _ = reply_handle(
50                 Err(AssetError { code: ErrCode::ServiceUnavailable, msg: "service stop".to_string() }),
51                 reply,
52             );
53             return IPC_SUCCESS as i32;
54         }
55         let _counter_user = AutoCounter::new();
56         if !self.system_ability.cancel_idle() {
57             loge!("[FATAL]Cancel idle failed. Service is stop.");
58             let _ = reply_handle(
59                 Err(AssetError { code: ErrCode::ServiceUnavailable, msg: "service stop".to_string() }),
60                 reply,
61             );
62             return IPC_SUCCESS as i32;
63         }
64 
65         if code >= REDIRECT_START_CODE {
66             return on_extension_request(self, code, data, reply);
67         }
68 
69         match on_remote_request(self, code, data, reply) {
70             Ok(_) => IPC_SUCCESS as i32,
71             Err(e) => e as i32,
72         }
73     }
74 
descriptor(&self) -> &'static str75     fn descriptor(&self) -> &'static str {
76         SA_NAME
77     }
78 }
79 
on_app_request(code: IpcCode, process_info: &ProcessInfo, calling_info: &CallingInfo) -> Result<()>80 fn on_app_request(code: IpcCode, process_info: &ProcessInfo, calling_info: &CallingInfo) -> Result<()> {
81     if code as u32 > IpcCode::PostQuery as u32 {
82         // No need to process upgrade event.
83         return Ok(());
84     }
85 
86     let app_index = match &process_info.process_info_detail {
87         ProcessInfoDetail::Hap(hap_info) => hap_info.app_index,
88         ProcessInfoDetail::Native(_) => 0,
89     };
90     let mut params = ExtDbMap::new();
91 
92     // to get the real user id to operate Asset
93     params.insert(PARAM_NAME_USER_ID, Value::Number(calling_info.user_id() as u32));
94     params.insert(PARAM_NAME_BUNDLE_NAME, Value::Bytes(process_info.process_name.clone()));
95     params.insert(PARAM_NAME_IS_HAP, Value::Bool(HAP_OWNER_TYPES.contains(&process_info.owner_type)));
96     params.insert(PARAM_NAME_APP_INDEX, Value::Number(app_index as u32));
97 
98     if let Ok(load) = AssetPlugin::get_instance().load_plugin() {
99         match load.process_event(EventType::OnAppCall, &mut params) {
100             Ok(()) => return Ok(()),
101             Err(code) => {
102                 return log_throw_error!(ErrCode::BmsError, "[FATAL]process on app call event failed, code: {}", code)
103             },
104         }
105     }
106     Ok(())
107 }
108 
on_remote_request(stub: &AssetService, code: u32, data: &mut MsgParcel, reply: &mut MsgParcel) -> IpcResult<()>109 fn on_remote_request(stub: &AssetService, code: u32, data: &mut MsgParcel, reply: &mut MsgParcel) -> IpcResult<()> {
110     match data.read_interface_token() {
111         Ok(interface_token) if interface_token == stub.descriptor() => {},
112         _ => {
113             loge!("[FATAL][SA]Invalid interface token.");
114             return Err(IpcStatusCode::Failed);
115         },
116     }
117     let ipc_code = IpcCode::try_from(code).map_err(asset_err_handle)?;
118 
119     let map = deserialize_map(data).map_err(asset_err_handle)?;
120     let process_info = ProcessInfo::build(map.get(&Tag::GroupId)).map_err(asset_err_handle)?;
121     let calling_info = CallingInfo::build(map.get(&Tag::UserId).cloned(), &process_info);
122     on_app_request(ipc_code, &process_info, &calling_info).map_err(asset_err_handle)?;
123 
124     let hap_info = construct_splited_db_name(&calling_info, false).map_err(asset_err_handle)?;
125     let _ = upgrade_single_clone_app_data(calling_info.user_id(), hap_info).map_err(asset_err_handle);
126 
127     match ipc_code {
128         IpcCode::Add => reply_handle(stub.add(&calling_info, &map), reply),
129         IpcCode::Remove => reply_handle(stub.remove(&calling_info, &map), reply),
130         IpcCode::Update => {
131             let update_map = deserialize_map(data).map_err(asset_err_handle)?;
132             reply_handle(stub.update(&calling_info, &map, &update_map), reply)
133         },
134         IpcCode::PreQuery => match stub.pre_query(&calling_info, &map) {
135             Ok(res) => {
136                 reply_handle(Ok(()), reply)?;
137                 reply.write::<Vec<u8>>(&res)
138             },
139             Err(e) => reply_handle(Err(e), reply),
140         },
141         IpcCode::Query => match stub.query(&calling_info, &map) {
142             Ok(res) => {
143                 reply_handle(Ok(()), reply)?;
144                 serialize_maps(&res, reply).map_err(asset_err_handle)
145             },
146             Err(e) => reply_handle(Err(e), reply),
147         },
148         IpcCode::PostQuery => reply_handle(stub.post_query(&calling_info, &map), reply),
149         IpcCode::QuerySyncResult => match stub.query_sync_result(&calling_info, &map) {
150             Ok(res) => {
151                 reply_handle(Ok(()), reply)?;
152                 serialize_sync_result(&res, reply).map_err(asset_err_handle)
153             },
154             Err(e) => reply_handle(Err(e), reply),
155         },
156     }
157 }
158 
on_extension_request(_stub: &AssetService, code: u32, data: &mut MsgParcel, reply: &mut MsgParcel) -> i32159 fn on_extension_request(_stub: &AssetService, code: u32, data: &mut MsgParcel, reply: &mut MsgParcel) -> i32 {
160     if let Ok(load) = AssetPlugin::get_instance().load_plugin() {
161         match load.redirect_request(code, data, reply) {
162             Ok(()) => {
163                 logi!("process redirect request success.");
164                 return IPC_SUCCESS as i32;
165             },
166             Err(code) => {
167                 loge!("process redirect request failed, code: {}", code);
168                 return code as i32;
169             },
170         }
171     }
172     IpcStatusCode::Failed as i32
173 }
174 
asset_err_handle(e: AssetError) -> IpcStatusCode175 fn asset_err_handle(e: AssetError) -> IpcStatusCode {
176     loge!("[IPC]Asset error code = {}, msg is {}", e.code, e.msg);
177     IpcStatusCode::InvalidValue
178 }
179 
reply_handle(ret: Result<()>, reply: &mut MsgParcel) -> IpcResult<()>180 fn reply_handle(ret: Result<()>, reply: &mut MsgParcel) -> IpcResult<()> {
181     match ret {
182         Ok(_) => reply.write::<u32>(&IPC_SUCCESS),
183         Err(e) => {
184             reply.write::<u32>(&(e.code as u32))?;
185             reply.write::<String>(&e.msg)
186         },
187     }
188 }
189