• 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 pub mod parcelable;
17 pub mod types;
18 
19 pub use types::on_string16_writer;
20 pub use types::vec_u16_to_string;
21 pub use types::vec_to_string;
22 pub use parcelable::allocate_vec_with_buffer;
23 
24 use crate::{ipc_binding, IpcResult, IpcStatusCode};
25 use crate::ipc_binding::{CParcel};
26 use std::marker::PhantomData;
27 use std::mem::{ManuallyDrop,MaybeUninit};
28 use std::ops::{Drop};
29 use std::ptr::{NonNull};
30 use std::slice;
31 use crate::AsRawPtr;
32 use crate::parcel::parcelable::{Serialize, Deserialize};
33 
34 /// This trait implements the common function for MsgParcel
35 /// and BorrowedMsgParcel
36 pub trait IMsgParcel: AsRawPtr<CParcel> {
37     /// Get current data size in parcel
get_data_size(&self) -> u3238     fn get_data_size(&self) -> u32 {
39         // SAFETY:
40         unsafe {
41             ipc_binding::CParcelGetDataSize(self.as_raw())
42         }
43     }
44 
45     /// Set current data size in parcel
set_data_size(&mut self, new_size: u32) -> bool46     fn set_data_size(&mut self, new_size: u32) -> bool {
47         // SAFETY:
48         unsafe {
49             ipc_binding::CParcelSetDataSize(self.as_mut_raw(), new_size)
50         }
51     }
52 
53     /// Get current data capacity in parcel
get_data_capacity(&self) -> u3254     fn get_data_capacity(&self) -> u32 {
55         // SAFETY:
56         unsafe {
57             ipc_binding::CParcelGetDataCapacity(self.as_raw())
58         }
59     }
60 
61     /// Set current data capacity in parcel
set_data_capacity(&mut self, new_size: u32) -> bool62     fn set_data_capacity(&mut self, new_size: u32) -> bool {
63         // SAFETY:
64         unsafe {
65             ipc_binding::CParcelSetDataCapacity(self.as_mut_raw(), new_size)
66         }
67     }
68 
69     /// Get maximum capacity in parcel
get_max_capacity(&self) -> u3270     fn get_max_capacity(&self) -> u32 {
71         // SAFETY:
72         unsafe {
73             ipc_binding::CParcelGetMaxCapacity(self.as_raw())
74         }
75     }
76 
77     /// Set maximum capacity in parcel
set_max_capacity(&mut self, new_size: u32) -> bool78     fn set_max_capacity(&mut self, new_size: u32) -> bool {
79         // SAFETY:
80         unsafe {
81             ipc_binding::CParcelSetMaxCapacity(self.as_mut_raw(), new_size)
82         }
83     }
84 
85     /// Get current writalbe bytes in parcel
get_writable_bytes(&self) -> u3286     fn get_writable_bytes(&self) -> u32 {
87         // SAFETY:
88         unsafe {
89             ipc_binding::CParcelGetWritableBytes(self.as_raw())
90         }
91     }
92 
93     /// Get current readable bytes in parcel
get_readable_bytes(&self) -> u3294     fn get_readable_bytes(&self) -> u32 {
95         // SAFETY:
96         unsafe {
97             ipc_binding::CParcelGetReadableBytes(self.as_raw())
98         }
99     }
100 
101     /// Get current read position of parcel
get_read_position(&self) -> u32102     fn get_read_position(&self) -> u32 {
103         // SAFETY:
104         unsafe {
105             ipc_binding::CParcelGetReadPosition(self.as_raw())
106         }
107     }
108 
109     /// Get current write position of parcel
get_write_position(&self) -> u32110     fn get_write_position(&self) -> u32 {
111         // SAFETY:
112         unsafe {
113             ipc_binding::CParcelGetWritePosition(self.as_raw())
114         }
115     }
116 
117     /// Rewind the read position to a new position of parcel
rewind_read(&mut self, new_pos: u32) -> bool118     fn rewind_read(&mut self, new_pos: u32) -> bool {
119         // SAFETY:
120         unsafe {
121             ipc_binding::CParcelRewindRead(self.as_mut_raw(), new_pos)
122         }
123     }
124 
125     /// Rewind the write position to a new position of parcel
rewind_write(&mut self, new_pos: u32) -> bool126     fn rewind_write(&mut self, new_pos: u32) -> bool {
127         // SAFETY:
128         unsafe {
129             ipc_binding::CParcelRewindWrite(self.as_mut_raw(), new_pos)
130         }
131     }
132 
133     /// Write a bytes stream into parcel
write_buffer(&mut self, data: &[u8]) -> bool134     fn write_buffer(&mut self, data: &[u8]) -> bool {
135         // SAFETY:
136         unsafe {
137             ipc_binding::CParcelWriteBuffer(self.as_mut_raw(),
138                 data.as_ptr(), data.len() as u32)
139         }
140     }
141 
142     /// Read a sized bytes stream from parcel
read_buffer(&self, len: u32) -> IpcResult<Vec<u8>>143     fn read_buffer(&self, len: u32) -> IpcResult<Vec<u8>> {
144         let mut buffer: Vec<MaybeUninit<u8>> = Vec::with_capacity(len as usize);
145         // SAFETY: this is safe because the vector contains MaybeUninit elements which can be uninitialized
146         unsafe{
147             buffer.set_len(len as usize);
148         }
149         // SAFETY:
150         let ok_status = unsafe {
151             ipc_binding::CParcelReadBuffer(
152                 self.as_raw(),
153                 buffer.as_mut_ptr() as *mut u8,
154                 len
155             )
156         };
157         // SAFETY: MaybeUninit has been initialized, this should be safe
158         // since MaybeUninit should have same layout as inner type
159         unsafe fn transmute_vec(v: Vec<std::mem::MaybeUninit<u8>>) -> Vec<u8> {
160             std::mem::transmute(v)
161         }
162         // SAFETY:
163         let buffer = unsafe { transmute_vec(buffer) };
164         if ok_status { Ok(buffer) } else { Err(IpcStatusCode::Failed) }
165     }
166 
167     /// Write a large bytes stream into parcel
write_raw_data(&mut self, data: &[u8]) -> bool168     fn write_raw_data(&mut self, data: &[u8]) -> bool {
169         // SAFETY:
170         unsafe {
171             ipc_binding::CParcelWriteRawData(self.as_mut_raw(),
172                 data.as_ptr(), data.len() as u32)
173         }
174     }
175 
176     /// Read a big bytes stream from parcel
read_raw_data(&self, len: u32) -> IpcResult<RawData>177     fn read_raw_data(&self, len: u32) -> IpcResult<RawData> {
178         // SAFETY:
179         let raw_data_ptr = unsafe {
180             ipc_binding::CParcelReadRawData(self.as_raw(), len)
181         };
182         if raw_data_ptr.is_null() {
183             Err(IpcStatusCode::Failed)
184         } else {
185             Ok(RawData::new(raw_data_ptr, len))
186          }
187     }
188 
189     /// contain file descriptors
has_fd(&self) -> bool190     fn has_fd(&self) -> bool {
191         // SAFETY:
192         unsafe {
193             ipc_binding::CParcelContainFileDescriptors(self.as_raw())
194         }
195     }
196 
197     /// clear file descriptor
clear_fd(&mut self)198     fn clear_fd(&mut self) {
199         // SAFETY:
200         unsafe {
201             ipc_binding::CParcelClearFileDescriptor(self.as_mut_raw());
202         }
203     }
204 
205     /// get raw data size
get_raw_data_size(&self) -> usize206     fn get_raw_data_size(&self) -> usize {
207         // SAFETY:
208         unsafe {
209             ipc_binding::CParcelGetRawDataSize(self.as_raw())
210         }
211     }
212 
213     /// get raw data capacity
get_raw_data_capacity(&self) -> usize214     fn get_raw_data_capacity(&self) -> usize {
215         // SAFETY:
216         unsafe {
217             ipc_binding::CParcelGetRawDataCapacity(self.as_raw())
218         }
219     }
220 
221     /// set clear fd flag
set_clear_fd_flag(&mut self)222     fn set_clear_fd_flag(&mut self) {
223         // SAFETY:
224         unsafe {
225             ipc_binding::CParcelSetClearFdFlag(self.as_mut_raw());
226         }
227     }
228 
229     /// append a MsgParcel
append(&mut self, data: &mut MsgParcel) -> bool230     fn append(&mut self, data: &mut MsgParcel) -> bool {
231         let data_parcel = data.as_mut_raw();
232         // SAFETY:
233         unsafe {
234             ipc_binding::CParcelAppend(self.as_mut_raw(), data_parcel)
235         }
236     }
237 }
238 
239 /// Rust RawData type which just for fetch data from C++ MssageParcel::ReadRawData()
240 #[repr(C)]
241 pub struct RawData{
242     raw_ptr: *const u8,
243     len: u32,
244 }
245 
246 impl RawData{
247     /// Create RawData object
new(raw_ptr: *const u8, len: u32) -> Self248     pub fn new(raw_ptr: *const u8, len: u32) -> Self {
249         RawData {
250             raw_ptr,
251             len,
252         }
253     }
254 
255     /// The caller should ensure that the u8 slice can be
256     /// correctly converted to other rust types
read(&self, start: u32, len: u32) -> IpcResult<&[u8]>257     pub fn read(&self, start: u32, len: u32) -> IpcResult<&[u8]> {
258         if len == 0 || len > self.len || start >= self.len || (start + len) > self.len {
259             return Err(IpcStatusCode::Failed);
260         }
261         // SAFETY:
262         // raw_ptr is valid in [0..len], the memory is matained by C++ Parcel.
263         let data_ptr = unsafe {
264             self.raw_ptr.add(start as usize)
265         };
266         if !data_ptr.is_null() {
267             // SAFETY:
268             // 1. data is valid for reads for `len * mem::size_of::<u8>() `
269             // 2. The entire memory range of this slice be contained within a single allocated object (From Cpp)
270             // 3. data_ptr point to len consecutive properly initialized values of `u8`
271             // 4. The total size `len * mem::size_of::<u8>()` of the slice is no larger than `isize::MAX`
272             unsafe {
273                 Ok(slice::from_raw_parts::<u8>(data_ptr, len as usize))
274             }
275         } else {
276             Err(IpcStatusCode::Failed)
277         }
278     }
279 }
280 
281 
282 /// Container for a message (data and object references) that can be sent
283 /// through Binder.
284 ///
285 /// This type represents a parcel that is owned by Rust code.
286 #[repr(transparent)]
287 pub struct MsgParcel {
288     ptr: NonNull<CParcel>,
289 }
290 /// # Safety
291 ///
292 /// An `MsgParcel` is an immutable handle to CParcel, which is thread-safe
293 unsafe impl Send for MsgParcel {}
294 
295 impl IMsgParcel for MsgParcel {}
296 
297 impl MsgParcel {
298     /// Create a MsgParcel object
new() -> Option<Self>299     pub fn new() -> Option<Self> {
300         // SAFETY:
301         let cparcel: *mut CParcel = unsafe {
302             ipc_binding::CParcelObtain()
303         };
304 
305         NonNull::new(cparcel).map(|x| MsgParcel{ptr: x})
306     }
307 
308     /// # Safety
from_raw(ptr: *mut CParcel) -> Option<MsgParcel>309     pub unsafe fn from_raw(ptr: *mut CParcel) -> Option<MsgParcel> {
310         NonNull::new(ptr).map(|ptr| Self { ptr })
311     }
312 
313     /// Get a raw CParcel pointer and MsgParcel dropped its ownership
into_raw(self) -> *mut CParcel314     pub fn into_raw(self) -> *mut CParcel {
315         let ptr = self.ptr.as_ptr();
316         let _ = ManuallyDrop::new(self);
317         ptr
318     }
319 
320     /// Get a borrowed view into the contents of this `MsgParcel`.
borrowed(&mut self) -> BorrowedMsgParcel<'_>321     pub fn borrowed(&mut self) -> BorrowedMsgParcel<'_> {
322         // SAFETY: The raw pointer is a valid pointer
323         BorrowedMsgParcel {
324             ptr: self.ptr,
325             _mark: PhantomData,
326         }
327     }
328 
329     /// Get an immutable borrowed view into the contents of this `MsgParcel`.
borrowed_ref(&self) -> &BorrowedMsgParcel<'_>330     pub fn borrowed_ref(&self) -> &BorrowedMsgParcel<'_> {
331         // Safety: MsgParcel and BorrowedParcel are both represented in the same
332         // way as a NonNull<CParcel> due to their use of repr(transparent),
333         // so casting references as done here is valid.
334         unsafe {
335             &*(self as *const MsgParcel as *const BorrowedMsgParcel<'_>)
336         }
337     }
338 }
339 
340 /// # Safety
341 ///
342 /// The `MsgParcel` constructors guarantee that a `MsgParcel` object will always
343 /// contain a valid pointer to an `CParcel`.
344 unsafe impl AsRawPtr<CParcel> for MsgParcel {
as_raw(&self) -> *const CParcel345     fn as_raw(&self) -> *const CParcel {
346         self.ptr.as_ptr()
347     }
348 
as_mut_raw(&mut self) -> *mut CParcel349     fn as_mut_raw(&mut self) -> *mut CParcel {
350         self.ptr.as_ptr()
351     }
352 }
353 
354 impl Drop for MsgParcel {
drop(&mut self)355     fn drop(&mut self) {
356         // Safety:
357         unsafe {
358             ipc_binding::CParcelDecStrongRef(self.as_mut_raw())
359         }
360     }
361 }
362 
363 /// Container for a message (data and object references) that can be sent
364 /// through Binder.
365 ///
366 /// This object is a borrowed variant of [`MsgParcel`]
367 #[repr(transparent)]
368 pub struct BorrowedMsgParcel<'a> {
369     ptr: NonNull<CParcel>,
370     _mark: PhantomData<&'a mut MsgParcel>,
371 }
372 
373 impl<'a> IMsgParcel for BorrowedMsgParcel<'a> {}
374 
375 impl<'a> BorrowedMsgParcel<'a> {
376 
377     /// # Safety
378     ///
379     /// `*mut CParcel` must be a valid pointer
from_raw(ptr: *mut CParcel) -> Option<BorrowedMsgParcel<'a>>380     pub unsafe fn from_raw(ptr: *mut CParcel) -> Option<BorrowedMsgParcel<'a>> {
381         Some(Self {
382             ptr: NonNull::new(ptr)?,
383             _mark: PhantomData,
384         })
385     }
386 
387     /// Get a sub-reference to this reference to the parcel.
reborrow(&mut self) -> BorrowedMsgParcel<'_>388     pub fn reborrow(&mut self) -> BorrowedMsgParcel<'_> {
389         BorrowedMsgParcel {
390             ptr: self.ptr,
391             _mark: PhantomData,
392         }
393     }
394 }
395 
396 /// # Safety
397 ///
398 /// The `BorrowedMsgParcel` constructors guarantee that a `BorrowedMsgParcel` object
399 /// will always contain a valid pointer to an `CParcel`.
400 unsafe impl<'a> AsRawPtr<CParcel> for BorrowedMsgParcel<'a> {
as_raw(&self) -> *const CParcel401     fn as_raw(&self) -> *const CParcel {
402         self.ptr.as_ptr()
403     }
404 
as_mut_raw(&mut self) -> *mut CParcel405     fn as_mut_raw(&mut self) -> *mut CParcel {
406         self.ptr.as_ptr()
407     }
408 }
409 
410 impl MsgParcel {
411     /// Read a data object which implements the Deserialize trait from MsgParcel
read<D: Deserialize>(&self) -> IpcResult<D>412     pub fn read<D: Deserialize>(&self) -> IpcResult<D> {
413         self.borrowed_ref().read()
414     }
415 
416     /// Write a data object which implements the Serialize trait to MsgParcel
write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()>417     pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()> {
418         self.borrowed().write(parcelable)
419     }
420 }
421 
422 impl<'a> BorrowedMsgParcel<'a> {
423     /// Read a data object which implements the Deserialize trait from BorrowedMsgParcel
read<D: Deserialize>(&self) -> IpcResult<D>424     pub fn read<D: Deserialize>(&self) -> IpcResult<D> {
425         D::deserialize(self)
426     }
427 
428     /// Write a data object which implements the Serialize trait to BorrowedMsgParcel
write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()>429     pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()> {
430         parcelable.serialize(self)
431     }
432 }