• 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 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::{
25     deserialize_maps, deserialize_sync_result, ipc_err_handle, serialize_map, IpcCode, IPC_SUCCESS, SA_ID, SA_NAME,
26 };
27 
28 const LOAD_TIMEOUT_IN_SECONDS: i32 = 4;
29 
load_asset_service() -> Result<RemoteObj>30 fn load_asset_service() -> Result<RemoteObj> {
31     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 
get_remote(need_check: bool) -> Result<RemoteObj>39 fn get_remote(need_check: bool) -> Result<RemoteObj> {
40     if need_check {
41         match SystemAbilityManager::check_system_ability(SA_ID) {
42             Some(remote) => Ok(remote),
43             None => load_asset_service(),
44         }
45     } else {
46         load_asset_service()
47     }
48 }
49 
50 /// This manager provides the capabilities for life cycle management of sensitive user data (Asset) such as passwords
51 /// and tokens, including adding, removing, updating, and querying.
52 pub struct Manager {
53     remote: RemoteObj,
54 }
55 
56 impl Manager {
57     /// Build and initialize the Manager.
build() -> Result<Self>58     pub fn build() -> Result<Self> {
59         let remote = get_remote(true)?;
60         Ok(Self { remote })
61     }
62 
63     /// Add an Asset.
add(&mut self, attributes: &AssetMap) -> Result<()>64     pub fn add(&mut self, attributes: &AssetMap) -> Result<()> {
65         self.process_one_agr_request(attributes, IpcCode::Add)?;
66         Ok(())
67     }
68 
69     /// Remove one or more Assets that match a search query.
remove(&mut self, query: &AssetMap) -> Result<()>70     pub fn remove(&mut self, query: &AssetMap) -> Result<()> {
71         self.process_one_agr_request(query, IpcCode::Remove)?;
72         Ok(())
73     }
74 
75     /// Update an Asset that matches a search query.
update(&mut self, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()>76     pub fn update(&mut self, query: &AssetMap, attributes_to_update: &AssetMap) -> Result<()> {
77         self.process_two_agr_request(query, attributes_to_update, IpcCode::Update)?;
78         Ok(())
79     }
80 
81     /// Preprocessing for querying one or more Assets that require user authentication.
pre_query(&mut self, query: &AssetMap) -> Result<Vec<u8>>82     pub fn pre_query(&mut self, query: &AssetMap) -> Result<Vec<u8>> {
83         let mut reply = self.process_one_agr_request(query, IpcCode::PreQuery)?;
84         let res = reply.read::<Vec<u8>>().map_err(ipc_err_handle)?;
85         Ok(res)
86     }
87 
88     /// Query one or more Assets that match a search query.
query(&mut self, query: &AssetMap) -> Result<Vec<AssetMap>>89     pub fn query(&mut self, query: &AssetMap) -> Result<Vec<AssetMap>> {
90         let mut reply = self.process_one_agr_request(query, IpcCode::Query)?;
91         let res = deserialize_maps(&mut reply)?;
92         Ok(res)
93     }
94 
95     /// Post-processing for querying multiple Assets that require user authentication.
post_query(&mut self, query: &AssetMap) -> Result<()>96     pub fn post_query(&mut self, query: &AssetMap) -> Result<()> {
97         self.process_one_agr_request(query, IpcCode::PostQuery)?;
98         Ok(())
99     }
100 
101     /// Query the result of synchronization.
query_sync_result(&mut self, query: &AssetMap) -> Result<SyncResult>102     pub fn query_sync_result(&mut self, query: &AssetMap) -> Result<SyncResult> {
103         match self.process_one_agr_request(query, IpcCode::QuerySyncResult) {
104             Ok(mut reply) => {
105                 let sync_result = deserialize_sync_result(&mut reply)?;
106                 Ok(sync_result)
107             },
108             Err(mut e) => {
109                 if e.code == ErrCode::InvalidArgument {
110                     e.code = ErrCode::ParamVerificationFailed;
111                 }
112                 Err(e)
113             },
114         }
115     }
116 
rebuild(&mut self) -> Result<()>117     fn rebuild(&mut self) -> Result<()> {
118         self.remote = get_remote(false)?;
119         Ok(())
120     }
121 
process_one_agr_request(&mut self, attributes: &AssetMap, ipc_code: IpcCode) -> Result<MsgParcel>122     fn process_one_agr_request(&mut self, attributes: &AssetMap, ipc_code: IpcCode) -> Result<MsgParcel> {
123         let mut parcel = MsgParcel::new();
124         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
125         serialize_map(attributes, &mut parcel)?;
126         match self.send_request(parcel, ipc_code) {
127             Ok(msg) => Ok(msg),
128             Err(e) => match e.code {
129                 ErrCode::ServiceUnavailable => {
130                     self.rebuild()?;
131                     let mut parcel = MsgParcel::new();
132                     parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
133                     serialize_map(attributes, &mut parcel)?;
134                     self.send_request(parcel, ipc_code)
135                 },
136                 _ => Err(e),
137             },
138         }
139     }
140 
process_two_agr_request( &mut self, query: &AssetMap, attributes_to_update: &AssetMap, ipc_code: IpcCode, ) -> Result<MsgParcel>141     fn process_two_agr_request(
142         &mut self,
143         query: &AssetMap,
144         attributes_to_update: &AssetMap,
145         ipc_code: IpcCode,
146     ) -> Result<MsgParcel> {
147         let mut parcel = MsgParcel::new();
148         parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
149         serialize_map(query, &mut parcel)?;
150         serialize_map(attributes_to_update, &mut parcel)?;
151         match self.send_request(parcel, ipc_code) {
152             Ok(msg) => Ok(msg),
153             Err(e) => match e.code {
154                 ErrCode::ServiceUnavailable => {
155                     self.rebuild()?;
156                     let mut parcel = MsgParcel::new();
157                     parcel.write_interface_token(self.descriptor()).map_err(ipc_err_handle)?;
158                     serialize_map(query, &mut parcel)?;
159                     serialize_map(attributes_to_update, &mut parcel)?;
160                     self.send_request(parcel, ipc_code)
161                 },
162                 _ => Err(e),
163             },
164         }
165     }
166 
send_request(&self, mut parcel: MsgParcel, ipc_code: IpcCode) -> Result<MsgParcel>167     fn send_request(&self, mut parcel: MsgParcel, ipc_code: IpcCode) -> Result<MsgParcel> {
168         let mut reply = self.remote.send_request(ipc_code as u32, &mut parcel).map_err(ipc_err_handle)?;
169         match reply.read::<u32>().map_err(ipc_err_handle)? {
170             IPC_SUCCESS => Ok(reply),
171             e => {
172                 let msg = reply.read::<String>().map_err(ipc_err_handle)?;
173                 throw_error!(ErrCode::try_from(e)?, "{}", msg)
174             },
175         }
176     }
177 
descriptor(&self) -> &'static str178     fn descriptor(&self) -> &'static str {
179         SA_NAME
180     }
181 }
182