• 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 //! Implement of RemoteObj type, which represent a C++ IRemoteObject.
17 
18 use std::ptr;
19 use crate::{
20     ipc_binding, IRemoteObj, DeathRecipient, IpcResult,
21     MsgParcel, BorrowedMsgParcel, AsRawPtr, IpcStatusCode,
22     parcel::vec_u16_to_string, parse_status_code,
23 };
24 use crate::ipc_binding::{CRemoteObject, CDeathRecipient};
25 use crate::parcel::parcelable::{Serialize, Deserialize, allocate_vec_with_buffer};
26 use std::ffi::{c_void, CString, c_char};
27 use crate::String16;
28 use hilog_rust::{error, hilog, HiLogLabel, LogType};
29 
30 const LOG_LABEL: HiLogLabel = HiLogLabel {
31     log_type: LogType::LogCore,
32     domain: 0xd001510,
33     tag: "RustRemoteObj"
34 };
35 
36 pub mod death_recipient;
37 pub mod cmp;
38 
39 /// RemoteObject can be used as proxy or stub object.
40 /// It always contained a native CRemoteObject pointer.
41 /// # Invariant
42 ///
43 /// `*mut CRemoteObject` must be valid
44 pub struct RemoteObj(ptr::NonNull<CRemoteObject>);
45 
46 impl RemoteObj {
47     /// Create an `RemoteObj` wrapper object from a raw `CRemoteObject` pointer.
48     /// # Safety
from_raw(obj: *mut CRemoteObject) -> Option<RemoteObj>49     pub unsafe fn from_raw(obj: *mut CRemoteObject) -> Option<RemoteObj> {
50         if obj.is_null() {
51             None
52         } else {
53             Some(RemoteObj(unsafe{ptr::NonNull::new_unchecked(obj)}))
54         }
55     }
56 
57     /// Extract a raw `CRemoteObject` pointer from this wrapper.
58     /// # Safety
as_inner(&self) -> *mut CRemoteObject59     pub unsafe fn as_inner(&self) -> *mut CRemoteObject {
60         self.0.as_ptr()
61     }
62 }
63 
64 impl IRemoteObj for RemoteObj {
send_request(&self, code: u32, data: &MsgParcel, is_async: bool) -> IpcResult<MsgParcel>65     fn send_request(&self, code: u32, data: &MsgParcel, is_async: bool) -> IpcResult<MsgParcel> {
66         // SAFETY:
67         unsafe {
68             let mut reply = MsgParcel::new().expect("create reply MsgParcel not success");
69             let result = ipc_binding::RemoteObjectSendRequest(self.as_inner(), code, data.as_raw(),
70                 reply.as_mut_raw(), is_async);
71             if result == 0 {
72                 Ok(reply)
73             } else {
74                 Err(parse_status_code(result))
75             }
76         }
77     }
78 
79     // Add death Recipient
add_death_recipient(&self, recipient: &mut DeathRecipient) -> bool80     fn add_death_recipient(&self, recipient: &mut DeathRecipient) -> bool {
81         // SAFETY:
82         unsafe {
83             ipc_binding::AddDeathRecipient(self.as_inner(), recipient.as_mut_raw())
84         }
85     }
86 
87     // remove death Recipients
remove_death_recipient(&self, recipient: &mut DeathRecipient) -> bool88     fn remove_death_recipient(&self, recipient: &mut DeathRecipient) -> bool {
89         // SAFETY:
90         unsafe {
91             ipc_binding::RemoveDeathRecipient(self.as_inner(), recipient.as_mut_raw())
92         }
93     }
94 
is_proxy(&self) -> bool95     fn is_proxy(&self) -> bool {
96         // SAFETY:
97         unsafe {
98             ipc_binding::IsProxyObject(self.as_inner())
99         }
100     }
101 
dump(&self, fd: i32, args: &mut Vec<String16>) -> i32102     fn dump(&self, fd: i32, args: &mut Vec<String16>) -> i32 {
103         let mut parcel = match MsgParcel::new() {
104             Some(parcel) => parcel,
105             None => {
106                 error!(LOG_LABEL, "create MsgParcel failed");
107                 return IpcStatusCode::Failed as i32;
108             }
109         };
110         match parcel.write::<Vec<String16>>(args) {
111             Ok(_) => {
112                 // SAFETY: `parcel` always contains a valid pointer to a  `CParcel`
113                 unsafe {
114                     ipc_binding::Dump(self.as_inner(), fd, parcel.into_raw())
115                 }
116             }
117             _ => {
118                 error!(LOG_LABEL, "create MsgParcel failed");
119                 IpcStatusCode::Failed as i32
120             }
121         }
122     }
123 
is_dead(&self) -> bool124     fn is_dead(&self) -> bool {
125         // SAFETY:
126         unsafe {
127             ipc_binding::IsObjectDead(self.as_inner())
128         }
129     }
130 
interface_descriptor(&self) -> IpcResult<String>131     fn interface_descriptor(&self) -> IpcResult<String> {
132         let mut vec: Option<Vec<u16>> = None;
133         // SAFETY:
134         let ok_status = unsafe {
135             ipc_binding::GetInterfaceDescriptor(
136                 self.as_inner(),
137                 &mut vec as *mut _ as *mut c_void,
138                 allocate_vec_with_buffer::<u16>
139             )
140         };
141         if ok_status {
142             vec_u16_to_string(vec)
143         } else {
144             Err(IpcStatusCode::Failed)
145         }
146     }
147 }
148 
149 impl Serialize for RemoteObj {
serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()>150     fn serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()> {
151         let ret = unsafe {
152             ipc_binding::CParcelWriteRemoteObject(parcel.as_mut_raw(), self.as_inner())
153         };
154         if ret {
155             Ok(())
156         } else {
157             Err(IpcStatusCode::Failed)
158         }
159     }
160 }
161 
162 impl Deserialize for RemoteObj {
deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self>163     fn deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self> {
164         // Safety: `Parcel` always contains a valid pointer to an
165         // `AParcel`. We pass a valid, mutable pointer to `val`, a
166         // literal of type `$ty`, and `$read_fn` will write the
167         let object = unsafe {
168             let remote = ipc_binding::CParcelReadRemoteObject(parcel.as_raw());
169             Self::from_raw(remote)
170         };
171         if let Some(x) = object {
172             Ok(x)
173         } else {
174             Err(IpcStatusCode::Failed)
175         }
176     }
177 }
178 
179 /// # Safety
180 ///
181 /// An `RemoteObj` is an immutable handle to CRemoteObject, which is thread-safe
182 unsafe impl Send for RemoteObj {}
183 /// # Safety
184 ///
185 /// An `RemoteObj` is an immutable handle to CRemoteObject, which is thread-safe
186 unsafe impl Sync for RemoteObj {}
187 
188 impl Clone for RemoteObj {
clone(&self) -> Self189     fn clone(&self) -> Self {
190         // SAFETY:
191         unsafe {
192             ipc_binding::RemoteObjectIncStrongRef(self.as_inner());
193         }
194         // SAFETY: no `None` here, cause `self` is valid
195         Self(self.0)
196     }
197 }
198 
199 impl Drop for RemoteObj {
drop(&mut self)200     fn drop(&mut self) {
201         // SAFETY:
202         unsafe {
203             ipc_binding::RemoteObjectDecStrongRef(self.as_inner());
204         }
205     }
206 }
207