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 }