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 defines the interface of the Asset Rust SDK.
17 
18 pub use asset_definition::*;
19 pub mod plugin_interface;
20 
21 use ipc::{parcel::MsgParcel, remote::RemoteObj};
22 use samgr::manage::SystemAbilityManager;
23 
24 use asset_ipc::{deserialize_maps, ipc_err_handle, serialize_map, IpcCode, IPC_SUCCESS, SA_ID, SA_NAME};
25 
26 const LOAD_TIMEOUT_IN_SECONDS: i32 = 4;
27 
get_remote() -> Result<RemoteObj>28 fn get_remote() -> Result<RemoteObj> {
29     match SystemAbilityManager::check_system_ability(SA_ID) {
30         Some(remote) => Ok(remote),
31         None => match SystemAbilityManager::load_system_ability(SA_ID, LOAD_TIMEOUT_IN_SECONDS) {
32             Some(remote) => Ok(remote),
33             None => {
34                 log_throw_error!(ErrCode::ServiceUnavailable, "[FATAL][RUST SDK]get remote service failed")
35             },
36         },
37     }
38 }
39 
40 /// This manager provides the capabilities for life cycle management of sensitive user data (Asset) such as passwords
41 /// and tokens, including adding, removing, updating, and querying.
42 pub struct Manager {
43     remote: RemoteObj,
44 }
45 
46 impl Manager {
47     /// Build and initialize the Manager.
build() -> Result<Self>48     pub fn build() -> Result<Self> {
49         let remote = get_remote()?;
50         Ok(Self { remote })
51     }
52 
53     /// Add an Asset.
add(&self, attributes: &AssetMap) -> Result<()>54     pub fn add(&self, attributes: &AssetMap) -> Result<()> {
55         let mut parcel = MsgParcel::new();
56         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
57         serialize_map(attributes, &mut parcel)?;
58         self.send_request(parcel, IpcCode::Add)?;
59         Ok(())
60     }
61 
62     /// Remove one or more Assets that match a search query.
remove(&self, query: &AssetMap) -> Result<()>63     pub fn remove(&self, query: &AssetMap) -> Result<()> {
64         let mut parcel = MsgParcel::new();
65         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
66         serialize_map(query, &mut parcel)?;
67         self.send_request(parcel, IpcCode::Remove)?;
68         Ok(())
69     }
70 
71     /// Update an Asset that matches a search query.
update(&self, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()>72     pub fn update(&self, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()> {
73         let mut parcel = MsgParcel::new();
74         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
75         serialize_map(query, &mut parcel)?;
76         serialize_map(attributes_to_update, &mut parcel)?;
77         self.send_request(parcel, IpcCode::Update)?;
78         Ok(())
79     }
80 
81     /// Preprocessing for querying one or more Assets that require user authentication.
pre_query(&self, query: &AssetMap) -> Result<Vec<u8>>82     pub fn pre_query(&self, query: &AssetMap) -> Result<Vec<u8>> {
83         let mut parcel = MsgParcel::new();
84         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
85         serialize_map(query, &mut parcel)?;
86         let mut reply = self.send_request(parcel, IpcCode::PreQuery)?;
87         let res = reply.read::<Vec<u8>>().map_err(ipc_err_handle)?;
88         Ok(res)
89     }
90 
91     /// Query one or more Assets that match a search query.
query(&self, query: &AssetMap) -> Result<Vec<AssetMap>>92     pub fn query(&self, query: &AssetMap) -> Result<Vec<AssetMap>> {
93         let mut parcel = MsgParcel::new();
94         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
95         serialize_map(query, &mut parcel)?;
96         let mut reply = self.send_request(parcel, IpcCode::Query)?;
97         let res = deserialize_maps(&mut reply)?;
98         Ok(res)
99     }
100 
101     /// Post-processing for querying multiple Assets that require user authentication.
post_query(&self, query: &AssetMap) -> Result<()>102     pub fn post_query(&self, query: &AssetMap) -> Result<()> {
103         let mut parcel = MsgParcel::new();
104         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
105         serialize_map(query, &mut parcel)?;
106         self.send_request(parcel, IpcCode::PostQuery)?;
107         Ok(())
108     }
109 
send_request(&self, mut parcel: MsgParcel, ipc_code: IpcCode) -> Result<MsgParcel>110     fn send_request(&self, mut parcel: MsgParcel, ipc_code: IpcCode) -> Result<MsgParcel> {
111         let mut reply = self.remote.send_request(ipc_code as u32, &mut parcel).map_err(ipc_err_handle)?;
112         match reply.read::<u32>().map_err(ipc_err_handle)? {
113             IPC_SUCCESS => Ok(reply),
114             e => {
115                 let msg = reply.read::<String>().map_err(ipc_err_handle)?;
116                 log_throw_error!(ErrCode::try_from(e)?, "{}", msg)
117             },
118         }
119     }
120 
descriptor(&self) -> &'static str121     fn descriptor(&self) -> &'static str {
122         SA_NAME
123     }
124 }
125