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