• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 use crate::{
17     ipc_binding, MsgParcel, RemoteObj, IRemoteObj,
18     InterfaceToken, String16, IpcResult, IpcStatusCode,
19     parse_status_code
20 };
21 use crate::parcel::{vec_to_string, allocate_vec_with_buffer};
22 use std::ffi::{CString, c_char, c_void};
23 use hilog_rust::{info, hilog, HiLogLabel, LogType};
24 
25 const LOG_LABEL: HiLogLabel = HiLogLabel {
26     log_type: LogType::LogCore,
27     domain: 0xD0057CA,
28     tag: "RustProcess"
29 };
30 
31 /// Get proxy object of samgr
get_context_object() -> Option<RemoteObj>32 pub fn get_context_object() -> Option<RemoteObj>
33 {
34     // SAFETY: If no SamgrContextManager object is available, the function might return nullptr,
35     // causing the subsequent RemoteObj::from_raw call to fail.
36     unsafe {
37         let samgr = ipc_binding::GetContextManager();
38         RemoteObj::from_raw(samgr)
39     }
40 }
41 
42 /// Add a service to samgr
add_service(service: &RemoteObj, said: i32) -> IpcResult<()>43 pub fn add_service(service: &RemoteObj, said: i32) -> IpcResult<()>
44 {
45     let samgr = get_context_object().expect("samgr is not null");
46     let mut data = MsgParcel::new().expect("MsgParcel is not null");
47     data.write(&InterfaceToken::new("ohos.samgr.accessToken"))?;
48     data.write(&said)?;
49     data.write(service)?;
50     data.write(&false)?;
51     data.write(&0)?;
52     data.write(&String16::new(""))?;
53     data.write(&String16::new(""))?;
54     let reply = samgr.send_request(3, &data, false)?;
55     let reply_value: i32 = reply.read()?;
56     info!(LOG_LABEL, "register service result: {}", reply_value);
57     if reply_value == 0 { Ok(())} else { Err(parse_status_code(reply_value)) }
58 }
59 
60 /// Get a service proxy from samgr
get_service(said: i32) -> IpcResult<RemoteObj>61 pub fn get_service(said: i32) -> IpcResult<RemoteObj>
62 {
63     let samgr = get_context_object().expect("samgr is not null");
64     let mut data = MsgParcel::new().expect("MsgParcel is not null");
65     data.write(&InterfaceToken::new("ohos.samgr.accessToken"))?;
66     data.write(&said)?;
67     let reply = samgr.send_request(2, &data, false)?;
68     let remote: RemoteObj = reply.read()?;
69     info!(LOG_LABEL, "get service success");
70     Ok(remote)
71 }
72 
73 /// Make current thread join to the IPC/RPC work thread pool
74 #[inline]
join_work_thread()75 pub fn join_work_thread()
76 {
77     // SAFETY:
78     // It should only be called from a thread not already part of the pool.
79     // The potential blocking nature of the function and its impact on other threads.
80     unsafe {
81         ipc_binding::JoinWorkThread();
82     }
83 }
84 
85 /// Exit current thread from IPC/RPC work thread pool
86 #[inline]
stop_work_thread()87 pub fn stop_work_thread()
88 {
89     // SAFETY:
90     // It should only be called from a thread belonging to the pool.
91     // Prematurely exiting might leave pending requests unprocessed and cause unexpected behavior.
92     unsafe {
93         ipc_binding::StopWorkThread()
94     }
95 }
96 
97 /// Get calling token ID of caller
98 #[inline]
get_calling_token_id() -> u6499 pub fn get_calling_token_id() -> u64
100 {
101     // SAFETY:
102     // Consider verifying it with additional security measures and context-based information when necessary.
103     unsafe {
104         ipc_binding::GetCallingTokenId()
105     }
106 }
107 
108 /// Get first calling token ID of caller
109 #[inline]
get_first_token_id() -> u64110 pub fn get_first_token_id() -> u64
111 {
112     // SAFETY:
113     // Consider verifying it with additional security measures and context-based information when necessary.
114     unsafe {
115         ipc_binding::GetFirstToekenId()
116     }
117 }
118 
119 /// Get self token id of current process
120 #[inline]
get_self_token_id() -> u64121 pub fn get_self_token_id() -> u64
122 {
123     // SAFETY:
124     // Minimize its exposure, restrict access to authorized parties within your application.
125     unsafe {
126         ipc_binding::GetSelfToekenId()
127     }
128 }
129 
130 /// Get calling process id of caller
131 #[inline]
get_calling_pid() -> u64132 pub fn get_calling_pid() -> u64
133 {
134     // SAFETY:
135     // The returned PID might be incorrect or invalid due to potential issues
136     // with the IPC mechanism or malicious attempts to manipulate it.
137     unsafe {
138         ipc_binding::GetCallingPid()
139     }
140 }
141 
142 /// Get calling user id of caller
143 #[inline]
get_calling_uid() -> u64144 pub fn get_calling_uid() -> u64
145 {
146     // SAFETY:
147     // Minimize its exposure, restrict access to authorized parties,
148     // and implement robust security measures to prevent unauthorized leaks or manipulation.
149     unsafe {
150         ipc_binding::GetCallingUid()
151     }
152 }
153 
154 /// Set the maximum number of threads
155 #[inline]
set_max_work_thread(max_thread_num: i32) -> bool156 pub fn set_max_work_thread(max_thread_num: i32) -> bool
157 {
158     // SAFETY:
159     // Ensuring the provided value is valid and appropriate for the system resources and workload.
160     unsafe {
161         ipc_binding::SetMaxWorkThreadNum(max_thread_num)
162     }
163 }
164 
165 /// Determine whether it is a local call
166 #[inline]
is_local_calling() -> bool167 pub fn is_local_calling() -> bool
168 {
169     // SAFETY:
170     // Ensure proper usage within the context of the IPC binding system and its intended behavior.
171     unsafe {
172         ipc_binding::IsLocalCalling()
173     }
174 }
175 
176 /// Set calling identity
177 #[inline]
set_calling_identity(identity: String) -> bool178 pub fn set_calling_identity(identity: String) -> bool
179 {
180     match CString::new(identity.as_str()) {
181         Ok(name) => {
182             // SAFETY:
183             // Name is valid
184             unsafe {
185                 ipc_binding::SetCallingIdentity(name.as_ptr())
186             }
187         },
188         Err(_) => false,
189     }
190 }
191 
192 /// get local device id
193 #[inline]
get_local_device_id() -> IpcResult<String>194 pub fn get_local_device_id() -> IpcResult<String>
195 {
196     let mut vec: Option<Vec<u8>> = None;
197     // SAFETY:
198     // it's important to ensure that the vec contains valid data and is not null.
199     // The provided buffer size is sufficient to hold the returned data.
200     let ok_status = unsafe {
201         ipc_binding::GetLocalDeviceID(
202             &mut vec as *mut _ as *mut c_void,
203             allocate_vec_with_buffer::<u8>
204         )
205     };
206 
207     if ok_status {
208         vec_to_string(vec)
209     } else {
210         Err(IpcStatusCode::Failed)
211     }
212 }
213 
214 /// get calling device id
215 #[inline]
get_calling_device_id() -> IpcResult<String>216 pub fn get_calling_device_id() -> IpcResult<String>
217 {
218     let mut vec: Option<Vec<u8>> = None;
219     // SAFETY:
220     // it's important to ensure that the vec contains valid data and is not null.
221     // The provided buffer size is sufficient to hold the returned data.
222     let ok_status = unsafe {
223         ipc_binding::GetCallingDeviceID(
224             &mut vec as *mut _ as *mut c_void,
225             allocate_vec_with_buffer::<u8>
226         )
227     };
228 
229     if ok_status {
230         vec_to_string(vec)
231     } else {
232         Err(IpcStatusCode::Failed)
233     }
234 }
235 
236 /// reset calling identity
237 #[inline]
reset_calling_identity() -> IpcResult<String>238 pub fn reset_calling_identity() -> IpcResult<String>
239 {
240     let mut vec: Option<Vec<u8>> = None;
241     // SAFETY:
242     // The provided buffer size is sufficient to hold the returned data.
243     // The returned `String` is validated before using it.
244     let ok_status = unsafe {
245         ipc_binding::ResetCallingIdentity(
246             &mut vec as *mut _ as *mut c_void,
247             allocate_vec_with_buffer::<u8>
248         )
249     };
250 
251     if ok_status {
252         vec_to_string(vec)
253     } else {
254         Err(IpcStatusCode::Failed)
255     }
256 }
257 
258 /// Determine whether the current thread is currently executing an incoming transaction.
259 #[inline]
is_handling_transaction() -> bool260 pub fn is_handling_transaction() -> bool
261 {
262     // SAFETY:
263     // Ensure proper usage within the context of the IPC binding system and its intended behavior.
264     unsafe {
265         ipc_binding::IsHandlingTransaction()
266     }
267 }