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 }