rust: Enable formatting enforcement for Rust

libbinder was written before PREUPLOAD hooks worked properly. Enable
preupload hooks and reformat libbinder in Android Rust style.

Bug: 204089163
Test: Modify .rs file against style, attempt upload
Change-Id: I2204b66b533b823bc233011330f5cb65c79fd5d6
This commit is contained in:
Matthew Maurer 2022-07-26 09:31:30 -07:00
parent eae8088caa
commit e268a9fca0
15 changed files with 229 additions and 379 deletions

View file

@ -1,8 +1,10 @@
[Builtin Hooks]
rustfmt = true
bpfmt = true
clang_format = true
[Builtin Hooks Options]
rustfmt = --config-path=rustfmt.toml
# Only turn on clang-format check for the following subfolders.
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
cmds/idlcli/

View file

@ -28,22 +28,22 @@
//!
//! [`Tokio`]: crate::Tokio
use binder::{BinderAsyncPool, BoxFuture, FromIBinder, StatusCode, Strong};
use binder::binder_impl::BinderAsyncRuntime;
use binder::{BinderAsyncPool, BoxFuture, FromIBinder, StatusCode, Strong};
use std::future::Future;
/// Retrieve an existing service for a particular interface, sleeping for a few
/// seconds if it doesn't yet exist.
pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(
name: &str,
) -> Result<Strong<T>, StatusCode> {
if binder::is_handling_transaction() {
// See comment in the BinderAsyncPool impl.
return binder::get_interface::<T>(name);
}
let name = name.to_string();
let res = tokio::task::spawn_blocking(move || {
binder::get_interface::<T>(&name)
}).await;
let res = tokio::task::spawn_blocking(move || binder::get_interface::<T>(&name)).await;
// The `is_panic` branch is not actually reachable in Android as we compile
// with `panic = abort`.
@ -58,16 +58,16 @@ pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Res
/// Retrieve an existing service for a particular interface, or start it if it
/// is configured as a dynamic service and isn't yet started.
pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(
name: &str,
) -> Result<Strong<T>, StatusCode> {
if binder::is_handling_transaction() {
// See comment in the BinderAsyncPool impl.
return binder::wait_for_interface::<T>(name);
}
let name = name.to_string();
let res = tokio::task::spawn_blocking(move || {
binder::wait_for_interface::<T>(&name)
}).await;
let res = tokio::task::spawn_blocking(move || binder::wait_for_interface::<T>(&name)).await;
// The `is_panic` branch is not actually reachable in Android as we compile
// with `panic = abort`.

View file

@ -17,7 +17,7 @@
//! Trait definitions for binder objects
use crate::error::{status_t, Result, StatusCode};
use crate::parcel::{Parcel, BorrowedParcel};
use crate::parcel::{BorrowedParcel, Parcel};
use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
use crate::sys;
@ -133,7 +133,7 @@ impl TryFrom<i32> for Stability {
match stability {
0 => Ok(Local),
1 => Ok(Vintf),
_ => Err(StatusCode::BAD_VALUE)
_ => Err(StatusCode::BAD_VALUE),
}
}
}
@ -158,7 +158,12 @@ pub trait Remotable: Send + Sync {
/// Handle and reply to a request to invoke a transaction on this object.
///
/// `reply` may be [`None`] if the sender does not expect a reply.
fn on_transact(&self, code: TransactionCode, data: &BorrowedParcel<'_>, reply: &mut BorrowedParcel<'_>) -> Result<()>;
fn on_transact(
&self,
code: TransactionCode,
data: &BorrowedParcel<'_>,
reply: &mut BorrowedParcel<'_>,
) -> Result<()>;
/// Handle a request to invoke the dump transaction on this
/// object.
@ -454,28 +459,19 @@ impl<I: FromIBinder + ?Sized> Weak<I> {
/// Construct a new weak reference from a strong reference
fn new(binder: &Strong<I>) -> Self {
let weak_binder = binder.as_binder().downgrade();
Weak {
weak_binder,
interface_type: PhantomData,
}
Weak { weak_binder, interface_type: PhantomData }
}
/// Upgrade this weak reference to a strong reference if the binder object
/// is still alive
pub fn upgrade(&self) -> Result<Strong<I>> {
self.weak_binder
.promote()
.ok_or(StatusCode::DEAD_OBJECT)
.and_then(FromIBinder::try_from)
self.weak_binder.promote().ok_or(StatusCode::DEAD_OBJECT).and_then(FromIBinder::try_from)
}
}
impl<I: FromIBinder + ?Sized> Clone for Weak<I> {
fn clone(&self) -> Self {
Self {
weak_binder: self.weak_binder.clone(),
interface_type: PhantomData,
}
Self { weak_binder: self.weak_binder.clone(), interface_type: PhantomData }
}
}
@ -614,7 +610,12 @@ pub trait InterfaceClassMethods {
/// contains a `T` pointer in its user data. fd should be a non-owned file
/// descriptor, and args must be an array of null-terminated string
/// poiinters with length num_args.
unsafe extern "C" fn on_dump(binder: *mut sys::AIBinder, fd: i32, args: *mut *const c_char, num_args: u32) -> status_t;
unsafe extern "C" fn on_dump(
binder: *mut sys::AIBinder,
fd: i32,
args: *mut *const c_char,
num_args: u32,
) -> status_t;
}
/// Interface for transforming a generic SpIBinder into a specific remote

View file

@ -41,7 +41,10 @@ pub trait BinderAsyncPool {
/// boxed `Future` trait object, and including `after_spawn` in the trait function
/// allows the caller to avoid double-boxing if they want to do anything to the value
/// returned from the spawned thread.
fn spawn<'a, F1, F2, Fut, A, B, E>(spawn_me: F1, after_spawn: F2) -> BoxFuture<'a, Result<B, E>>
fn spawn<'a, F1, F2, Fut, A, B, E>(
spawn_me: F1,
after_spawn: F2,
) -> BoxFuture<'a, Result<B, E>>
where
F1: FnOnce() -> A,
F2: FnOnce(A) -> Fut,

View file

@ -106,8 +106,8 @@ mod state;
use binder_ndk_sys as sys;
pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
pub use crate::binder_async::{BinderAsyncPool, BoxFuture};
pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
pub use error::{ExceptionCode, Status, StatusCode};
pub use native::{
add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service,

View file

@ -97,10 +97,7 @@ impl<T: Remotable> Binder<T> {
// ends.
sys::AIBinder_new(class.into(), rust_object as *mut c_void)
};
let mut binder = Binder {
ibinder,
rust_object,
};
let mut binder = Binder { ibinder, rust_object };
binder.mark_stability(stability);
binder
}
@ -343,7 +340,9 @@ impl<T: Remotable> InterfaceClassMethods for Binder<T> {
vec![]
} else {
slice::from_raw_parts(args, num_args as usize)
.iter().map(|s| CStr::from_ptr(*s)).collect()
.iter()
.map(|s| CStr::from_ptr(*s))
.collect()
};
let object = sys::AIBinder_getUserData(binder);
@ -418,10 +417,7 @@ impl<B: Remotable> TryFrom<SpIBinder> for Binder<B> {
// We are transferring the ownership of the AIBinder into the new Binder
// object.
let mut ibinder = ManuallyDrop::new(ibinder);
Ok(Binder {
ibinder: ibinder.as_native_mut(),
rust_object: userdata as *mut B,
})
Ok(Binder { ibinder: ibinder.as_native_mut(), rust_object: userdata as *mut B })
}
}

View file

@ -22,10 +22,10 @@ use crate::proxy::SpIBinder;
use crate::sys;
use std::convert::TryInto;
use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ptr::{self, NonNull};
use std::fmt;
mod file_descriptor;
mod parcelable;
@ -33,8 +33,8 @@ mod parcelable_holder;
pub use self::file_descriptor::ParcelFileDescriptor;
pub use self::parcelable::{
Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption,
Parcelable, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
Deserialize, DeserializeArray, DeserializeOption, Parcelable, Serialize, SerializeArray,
SerializeOption, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
};
pub use self::parcelable_holder::{ParcelableHolder, ParcelableMetadata};
@ -78,9 +78,7 @@ impl Parcel {
// a valid pointer. If it fails, the process will crash.
sys::AParcel_create()
};
Self {
ptr: NonNull::new(ptr).expect("AParcel_create returned null pointer")
}
Self { ptr: NonNull::new(ptr).expect("AParcel_create returned null pointer") }
}
/// Create an owned reference to a parcel object from a raw pointer.
@ -116,10 +114,7 @@ impl Parcel {
// lifetime of the returned `BorrowedParcel` is tied to `self`, so the
// borrow checker will ensure that the `AParcel` can only be accessed
// via the `BorrowParcel` until it goes out of scope.
BorrowedParcel {
ptr: self.ptr,
_lifetime: PhantomData,
}
BorrowedParcel { ptr: self.ptr, _lifetime: PhantomData }
}
/// Get an immutable borrowed view into the contents of this `Parcel`.
@ -127,9 +122,7 @@ impl Parcel {
// Safety: Parcel and BorrowedParcel are both represented in the same
// way as a NonNull<sys::AParcel> due to their use of repr(transparent),
// so casting references as done here is valid.
unsafe {
&*(self as *const Parcel as *const BorrowedParcel<'_>)
}
unsafe { &*(self as *const Parcel as *const BorrowedParcel<'_>) }
}
}
@ -165,10 +158,7 @@ impl<'a> BorrowedParcel<'a> {
/// since this is a mutable borrow, it must have exclusive access to the
/// AParcel for the duration of the borrow.
pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<BorrowedParcel<'a>> {
Some(Self {
ptr: NonNull::new(ptr)?,
_lifetime: PhantomData,
})
Some(Self { ptr: NonNull::new(ptr)?, _lifetime: PhantomData })
}
/// Get a sub-reference to this reference to the parcel.
@ -177,10 +167,7 @@ impl<'a> BorrowedParcel<'a> {
// lifetime of the returned `BorrowedParcel` is tied to `self`, so the
// borrow checker will ensure that the `AParcel` can only be accessed
// via the `BorrowParcel` until it goes out of scope.
BorrowedParcel {
ptr: self.ptr,
_lifetime: PhantomData,
}
BorrowedParcel { ptr: self.ptr, _lifetime: PhantomData }
}
}
@ -269,7 +256,7 @@ impl<'a> BorrowedParcel<'a> {
/// ```
pub fn sized_write<F>(&mut self, f: F) -> Result<()>
where
for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()>
for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()>,
{
let start = self.get_data_position();
self.write(&0i32)?;
@ -324,17 +311,17 @@ impl<'a> BorrowedParcel<'a> {
///
/// This appends `size` bytes of data from `other` starting at offset
/// `start` to the current parcel, or returns an error if not possible.
pub fn append_from(&mut self, other: &impl AsNative<sys::AParcel>, start: i32, size: i32) -> Result<()> {
pub fn append_from(
&mut self,
other: &impl AsNative<sys::AParcel>,
start: i32,
size: i32,
) -> Result<()> {
let status = unsafe {
// Safety: `Parcel::appendFrom` from C++ checks that `start`
// and `size` are in bounds, and returns an error otherwise.
// Both `self` and `other` always contain valid pointers.
sys::AParcel_appendFrom(
other.as_native(),
self.as_native_mut(),
start,
size,
)
sys::AParcel_appendFrom(other.as_native(), self.as_native_mut(), start, size)
};
status_result(status)
}
@ -406,7 +393,7 @@ impl Parcel {
/// ```
pub fn sized_write<F>(&mut self, f: F) -> Result<()>
where
for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()>
for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()>,
{
self.borrowed().sized_write(f)
}
@ -438,7 +425,12 @@ impl Parcel {
///
/// This appends `size` bytes of data from `other` starting at offset
/// `start` to the current parcel, or returns an error if not possible.
pub fn append_from(&mut self, other: &impl AsNative<sys::AParcel>, start: i32, size: i32) -> Result<()> {
pub fn append_from(
&mut self,
other: &impl AsNative<sys::AParcel>,
start: i32,
size: i32,
) -> Result<()> {
self.borrowed().append_from(other, start, size)
}
@ -492,7 +484,7 @@ impl<'a> BorrowedParcel<'a> {
///
pub fn sized_read<F>(&self, f: F) -> Result<()>
where
for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()>
for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()>,
{
let start = self.get_data_position();
let parcelable_size: i32 = self.read()?;
@ -500,17 +492,13 @@ impl<'a> BorrowedParcel<'a> {
return Err(StatusCode::BAD_VALUE);
}
let end = start.checked_add(parcelable_size)
.ok_or(StatusCode::BAD_VALUE)?;
let end = start.checked_add(parcelable_size).ok_or(StatusCode::BAD_VALUE)?;
if end > self.get_data_size() {
return Err(StatusCode::NOT_ENOUGH_DATA);
}
let subparcel = ReadableSubParcel {
parcel: BorrowedParcel {
ptr: self.ptr,
_lifetime: PhantomData,
},
parcel: BorrowedParcel { ptr: self.ptr, _lifetime: PhantomData },
end_position: end,
};
f(subparcel)?;
@ -633,7 +621,7 @@ impl Parcel {
///
pub fn sized_read<F>(&self, f: F) -> Result<()>
where
for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()>
for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()>,
{
self.borrowed_ref().sized_read(f)
}
@ -716,15 +704,13 @@ impl Drop for Parcel {
impl fmt::Debug for Parcel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Parcel")
.finish()
f.debug_struct("Parcel").finish()
}
}
impl<'a> fmt::Debug for BorrowedParcel<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BorrowedParcel")
.finish()
f.debug_struct("BorrowedParcel").finish()
}
}
@ -813,10 +799,7 @@ fn test_read_data() {
assert!(parcel.set_data_position(start).is_ok());
}
assert_eq!(
parcel.read::<f32>().unwrap(),
1143139100000000000000000000.0
);
assert_eq!(parcel.read::<f32>().unwrap(), 1143139100000000000000000000.0);
assert_eq!(parcel.read::<f32>().unwrap(), 40.043392);
unsafe {
@ -842,10 +825,7 @@ fn test_utf8_utf16_conversions() {
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert_eq!(
parcel.read::<Option<String>>().unwrap().unwrap(),
"Hello, Binder!",
);
assert_eq!(parcel.read::<Option<String>>().unwrap().unwrap(), "Hello, Binder!",);
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
@ -864,13 +844,7 @@ fn test_utf8_utf16_conversions() {
assert!(parcel.write(&["str1", "str2", "str3"][..]).is_ok());
assert!(parcel
.write(
&[
String::from("str4"),
String::from("str5"),
String::from("str6"),
][..]
)
.write(&[String::from("str4"), String::from("str5"), String::from("str6"),][..])
.is_ok());
let s1 = "Hello, Binder!";
@ -882,14 +856,8 @@ fn test_utf8_utf16_conversions() {
assert!(parcel.set_data_position(start).is_ok());
}
assert_eq!(
parcel.read::<Vec<String>>().unwrap(),
["str1", "str2", "str3"]
);
assert_eq!(
parcel.read::<Vec<String>>().unwrap(),
["str4", "str5", "str6"]
);
assert_eq!(parcel.read::<Vec<String>>().unwrap(), ["str1", "str2", "str3"]);
assert_eq!(parcel.read::<Vec<String>>().unwrap(), ["str4", "str5", "str6"]);
assert_eq!(parcel.read::<Vec<String>>().unwrap(), [s1, s2, s3]);
}
@ -900,9 +868,9 @@ fn test_sized_write() {
let arr = [1i32, 2i32, 3i32];
parcel.sized_write(|subparcel| {
subparcel.write(&arr[..])
}).expect("Could not perform sized write");
parcel
.sized_write(|subparcel| subparcel.write(&arr[..]))
.expect("Could not perform sized write");
// i32 sub-parcel length + i32 array length + 3 i32 elements
let expected_len = 20i32;
@ -913,15 +881,9 @@ fn test_sized_write() {
parcel.set_data_position(start).unwrap();
}
assert_eq!(
expected_len,
parcel.read().unwrap(),
);
assert_eq!(expected_len, parcel.read().unwrap(),);
assert_eq!(
parcel.read::<Vec<i32>>().unwrap(),
&arr,
);
assert_eq!(parcel.read::<Vec<i32>>().unwrap(), &arr,);
}
#[test]

View file

@ -15,7 +15,7 @@
*/
use super::{
Deserialize, DeserializeArray, DeserializeOption, BorrowedParcel, Serialize, SerializeArray,
BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray,
SerializeOption,
};
use crate::binder::AsNative;
@ -115,10 +115,7 @@ impl DeserializeOption for ParcelFileDescriptor {
// descriptor. The read function passes ownership of the file
// descriptor to its caller if it was non-null, so we must take
// ownership of the file and ensure that it is eventually closed.
status_result(sys::AParcel_readParcelFileDescriptor(
parcel.as_native(),
&mut fd,
))?;
status_result(sys::AParcel_readParcelFileDescriptor(parcel.as_native(), &mut fd))?;
}
if fd < 0 {
Ok(None)
@ -136,9 +133,7 @@ impl DeserializeOption for ParcelFileDescriptor {
impl Deserialize for ParcelFileDescriptor {
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Deserialize::deserialize(parcel)
.transpose()
.unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
Deserialize::deserialize(parcel).transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
}

View file

@ -22,8 +22,8 @@ use crate::sys;
use std::convert::{TryFrom, TryInto};
use std::ffi::c_void;
use std::mem::{self, ManuallyDrop, MaybeUninit};
use std::os::raw::{c_char, c_ulong};
use std::mem::{self, MaybeUninit, ManuallyDrop};
use std::ptr;
use std::slice;
@ -109,17 +109,14 @@ unsafe extern "C" fn serialize_element<T: Serialize>(
// so the function signature matches what bindgen generates.
let index = index as usize;
let slice: &[T] = slice::from_raw_parts(array.cast(), index+1);
let slice: &[T] = slice::from_raw_parts(array.cast(), index + 1);
let mut parcel = match BorrowedParcel::from_raw(parcel) {
None => return StatusCode::UNEXPECTED_NULL as status_t,
Some(p) => p,
};
slice[index].serialize(&mut parcel)
.err()
.unwrap_or(StatusCode::OK)
as status_t
slice[index].serialize(&mut parcel).err().unwrap_or(StatusCode::OK) as status_t
}
/// Helper trait for types that can be deserialized as arrays.
@ -265,10 +262,7 @@ unsafe extern "C" fn allocate_vec_with_buffer<T>(
///
/// The opaque data pointer passed to the array read function must be a mutable
/// pointer to an `Option<Vec<MaybeUninit<T>>>`.
unsafe extern "C" fn allocate_vec<T>(
data: *mut c_void,
len: i32,
) -> bool {
unsafe extern "C" fn allocate_vec<T>(data: *mut c_void, len: i32) -> bool {
let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
if len < 0 {
*vec = None;
@ -286,7 +280,6 @@ unsafe extern "C" fn allocate_vec<T>(
true
}
macro_rules! parcelable_primitives {
{
$(
@ -303,11 +296,7 @@ unsafe fn vec_assume_init<T>(vec: Vec<MaybeUninit<T>>) -> Vec<T> {
// has the same alignment and size as T, so the pointer to the vector
// allocation will be compatible.
let mut vec = ManuallyDrop::new(vec);
Vec::from_raw_parts(
vec.as_mut_ptr().cast(),
vec.len(),
vec.capacity(),
)
Vec::from_raw_parts(vec.as_mut_ptr().cast(), vec.len(), vec.capacity())
}
macro_rules! impl_parcelable {
@ -522,11 +511,7 @@ impl SerializeOption for str {
// `AParcel`. If the string pointer is null,
// `AParcel_writeString` requires that the length is -1 to
// indicate that we want to serialize a null string.
status_result(sys::AParcel_writeString(
parcel.as_native_mut(),
ptr::null(),
-1,
))
status_result(sys::AParcel_writeString(parcel.as_native_mut(), ptr::null(), -1))
},
Some(s) => unsafe {
// Safety: `Parcel` always contains a valid pointer to an
@ -540,10 +525,7 @@ impl SerializeOption for str {
status_result(sys::AParcel_writeString(
parcel.as_native_mut(),
s.as_ptr() as *const c_char,
s.as_bytes()
.len()
.try_into()
.or(Err(StatusCode::BAD_VALUE))?,
s.as_bytes().len().try_into().or(Err(StatusCode::BAD_VALUE))?,
))
},
}
@ -602,9 +584,7 @@ impl DeserializeArray for Option<String> {}
impl Deserialize for String {
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Deserialize::deserialize(parcel)
.transpose()
.unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
Deserialize::deserialize(parcel).transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
}
@ -704,10 +684,7 @@ impl Serialize for Status {
// and `Status` always contains a valid pointer to an `AStatus`, so
// both parameters are valid and safe. This call does not take
// ownership of either of its parameters.
status_result(sys::AParcel_writeStatusHeader(
parcel.as_native_mut(),
self.as_native(),
))
status_result(sys::AParcel_writeStatusHeader(parcel.as_native_mut(), self.as_native()))
}
}
}
@ -881,8 +858,7 @@ macro_rules! impl_deserialize_for_parcelable {
Ok(())
} else {
use $crate::Parcelable;
this.get_or_insert_with(Self::default)
.read_from_parcel(parcel)
this.get_or_insert_with(Self::default).read_from_parcel(parcel)
}
}
}
@ -915,8 +891,8 @@ impl<T: DeserializeOption> DeserializeOption for Box<T> {
#[cfg(test)]
mod tests {
use crate::parcel::Parcel;
use super::*;
use crate::parcel::Parcel;
#[test]
fn test_custom_parcelable() {
@ -934,11 +910,11 @@ mod tests {
impl Deserialize for Custom {
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Ok(Custom(
parcel.read()?,
parcel.read()?,
parcel.read()?,
parcel.read::<Option<Vec<String>>>()?.unwrap(),
))
parcel.read()?,
parcel.read()?,
parcel.read()?,
parcel.read::<Option<Vec<String>>>()?.unwrap(),
))
}
}
@ -1157,12 +1133,7 @@ mod tests {
assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]);
let f32s = [
std::f32::NAN,
std::f32::INFINITY,
1.23456789,
std::f32::EPSILON,
];
let f32s = [std::f32::NAN, std::f32::INFINITY, 1.23456789, std::f32::EPSILON];
unsafe {
assert!(parcel.set_data_position(start).is_ok());
@ -1178,12 +1149,7 @@ mod tests {
assert!(vec[0].is_nan());
assert_eq!(vec[1..], f32s[1..]);
let f64s = [
std::f64::NAN,
std::f64::INFINITY,
1.234567890123456789,
std::f64::EPSILON,
];
let f64s = [std::f64::NAN, std::f64::INFINITY, 1.234567890123456789, std::f64::EPSILON];
unsafe {
assert!(parcel.set_data_position(start).is_ok());

View file

@ -48,10 +48,7 @@ impl<T> AnyParcelable for T where T: DowncastSync + Parcelable + std::fmt::Debug
#[derive(Debug, Clone)]
enum ParcelableHolderData {
Empty,
Parcelable {
parcelable: Arc<dyn AnyParcelable>,
name: String,
},
Parcelable { parcelable: Arc<dyn AnyParcelable>, name: String },
Parcel(Parcel),
}
@ -77,10 +74,7 @@ pub struct ParcelableHolder {
impl ParcelableHolder {
/// Construct a new `ParcelableHolder` with the given stability.
pub fn new(stability: Stability) -> Self {
Self {
data: Mutex::new(ParcelableHolderData::Empty),
stability,
}
Self { data: Mutex::new(ParcelableHolderData::Empty), stability }
}
/// Reset the contents of this `ParcelableHolder`.
@ -101,10 +95,8 @@ impl ParcelableHolder {
return Err(StatusCode::BAD_VALUE);
}
*self.data.get_mut().unwrap() = ParcelableHolderData::Parcelable {
parcelable: p,
name: T::get_descriptor().into(),
};
*self.data.get_mut().unwrap() =
ParcelableHolderData::Parcelable { parcelable: p, name: T::get_descriptor().into() };
Ok(())
}
@ -130,10 +122,7 @@ impl ParcelableHolder {
let mut data = self.data.lock().unwrap();
match *data {
ParcelableHolderData::Empty => Ok(None),
ParcelableHolderData::Parcelable {
ref parcelable,
ref name,
} => {
ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
if name != parcelable_desc {
return Err(StatusCode::BAD_VALUE);
}
@ -199,10 +188,7 @@ impl Parcelable for ParcelableHolder {
let mut data = self.data.lock().unwrap();
match *data {
ParcelableHolderData::Empty => parcel.write(&0i32),
ParcelableHolderData::Parcelable {
ref parcelable,
ref name,
} => {
ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
let length_start = parcel.get_data_position();
parcel.write(&0i32)?;
@ -251,9 +237,7 @@ impl Parcelable for ParcelableHolder {
// TODO: C++ ParcelableHolder accepts sizes up to SIZE_MAX here, but we
// only go up to i32::MAX because that's what our API uses everywhere
let data_start = parcel.get_data_position();
let data_end = data_start
.checked_add(data_size)
.ok_or(StatusCode::BAD_VALUE)?;
let data_end = data_start.checked_add(data_size).ok_or(StatusCode::BAD_VALUE)?;
let mut new_parcel = Parcel::new();
new_parcel.append_from(parcel, data_start, data_size)?;

View file

@ -22,7 +22,8 @@ use crate::binder::{
};
use crate::error::{status_result, Result, StatusCode};
use crate::parcel::{
Parcel, BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption,
BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize,
SerializeArray, SerializeOption,
};
use crate::sys;
@ -431,10 +432,7 @@ impl SerializeArray for SpIBinder {}
impl Deserialize for SpIBinder {
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<SpIBinder> {
parcel
.read_binder()
.transpose()
.unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
parcel.read_binder().transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
}
@ -610,7 +608,10 @@ impl DeathRecipient {
//
// All uses of linkToDeath in this file correctly increment the
// ref-count that this onUnlinked callback will decrement.
sys::AIBinder_DeathRecipient_setOnUnlinked(recipient, Some(Self::cookie_decr_refcount::<F>));
sys::AIBinder_DeathRecipient_setOnUnlinked(
recipient,
Some(Self::cookie_decr_refcount::<F>),
);
}
DeathRecipient {
recipient,

View file

@ -124,7 +124,8 @@ impl ThreadState {
/// kernel is too old to support this feature.
pub fn with_calling_sid<T, F>(check_permission: F) -> T
where
for<'a> F: FnOnce(Option<&'a std::ffi::CStr>) -> T {
for<'a> F: FnOnce(Option<&'a std::ffi::CStr>) -> T,
{
// Safety: AIBinder_getCallingSid returns a c-string pointer
// that is valid for a transaction. Also, the string returned
// is thread local. By restricting the lifetime of the CStr

View file

@ -60,9 +60,7 @@ fn main() -> Result<(), &'static str> {
if let Some(extension_name) = extension_name {
let extension =
BnTest::new_binder(TestService::new(&extension_name), BinderFeatures::default());
service
.set_extension(&mut extension.as_binder())
.expect("Could not add extension");
service.set_extension(&mut extension.as_binder()).expect("Could not add extension");
}
binder::add_service(&service_name, service.as_binder())
.expect("Could not register service");
@ -73,10 +71,7 @@ fn main() -> Result<(), &'static str> {
}
fn print_usage() {
eprintln!(
"Usage: {} SERVICE_NAME [EXTENSION_NAME]",
RUST_SERVICE_BINARY
);
eprintln!("Usage: {} SERVICE_NAME [EXTENSION_NAME]", RUST_SERVICE_BINARY);
eprintln!(concat!(
"Spawn a Binder test service identified by SERVICE_NAME,",
" optionally with an extesion named EXTENSION_NAME",
@ -90,10 +85,7 @@ struct TestService {
impl TestService {
fn new(s: &str) -> Self {
Self {
s: s.to_string(),
dump_args: Mutex::new(Vec::new()),
}
Self { s: s.to_string(), dump_args: Mutex::new(Vec::new()) }
}
}
@ -111,11 +103,15 @@ impl TryFrom<u32> for TestTransactionCode {
fn try_from(c: u32) -> Result<Self, Self::Error> {
match c {
_ if c == TestTransactionCode::Test as u32 => Ok(TestTransactionCode::Test),
_ if c == TestTransactionCode::GetDumpArgs as u32 => Ok(TestTransactionCode::GetDumpArgs),
_ if c == TestTransactionCode::GetDumpArgs as u32 => {
Ok(TestTransactionCode::GetDumpArgs)
}
_ if c == TestTransactionCode::GetSelinuxContext as u32 => {
Ok(TestTransactionCode::GetSelinuxContext)
}
_ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => Ok(TestTransactionCode::GetIsHandlingTransaction),
_ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => {
Ok(TestTransactionCode::GetIsHandlingTransaction)
}
_ => Err(StatusCode::UNKNOWN_TRANSACTION),
}
}
@ -200,15 +196,16 @@ fn on_transact(
TestTransactionCode::Test => reply.write(&service.test()?),
TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
TestTransactionCode::GetIsHandlingTransaction => reply.write(&service.get_is_handling_transaction()?),
TestTransactionCode::GetIsHandlingTransaction => {
reply.write(&service.get_is_handling_transaction()?)
}
}
}
impl ITest for BpTest {
fn test(&self) -> Result<String, StatusCode> {
let reply =
self.binder
.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(()))?;
self.binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(()))?;
reply.read()
}
@ -243,31 +240,45 @@ impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
let binder = self.binder.clone();
P::spawn(
move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())),
|reply| async move { reply?.read() }
|reply| async move { reply?.read() },
)
}
fn get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>> {
let binder = self.binder.clone();
P::spawn(
move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())),
|reply| async move { reply?.read() }
move || {
binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(()))
},
|reply| async move { reply?.read() },
)
}
fn get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>> {
let binder = self.binder.clone();
P::spawn(
move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())),
|reply| async move { reply?.read() }
move || {
binder.transact(
TestTransactionCode::GetSelinuxContext as TransactionCode,
0,
|_| Ok(()),
)
},
|reply| async move { reply?.read() },
)
}
fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>> {
let binder = self.binder.clone();
P::spawn(
move || binder.transact(TestTransactionCode::GetIsHandlingTransaction as TransactionCode, 0, |_| Ok(())),
|reply| async move { reply?.read() }
move || {
binder.transact(
TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
0,
|_| Ok(()),
)
},
|reply| async move { reply?.read() },
)
}
}
@ -374,7 +385,7 @@ mod tests {
use binder_tokio::Tokio;
use super::{BnTest, ITest, IATest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
use super::{BnTest, IATest, ITest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
pub struct ScopedServiceProcess(Child);
@ -405,9 +416,7 @@ mod tests {
impl Drop for ScopedServiceProcess {
fn drop(&mut self) {
self.0.kill().expect("Could not kill child process");
self.0
.wait()
.expect("Could not wait for child process to die");
self.0.wait().expect("Could not wait for child process to die");
}
}
@ -428,10 +437,7 @@ mod tests {
);
// The service manager service isn't an ITest, so this must fail.
assert_eq!(
binder::get_interface::<dyn ITest>("manager").err(),
Some(StatusCode::BAD_TYPE)
);
assert_eq!(binder::get_interface::<dyn ITest>("manager").err(), Some(StatusCode::BAD_TYPE));
assert_eq!(
binder::get_interface::<dyn IATest<Tokio>>("manager").err(),
Some(StatusCode::BAD_TYPE)
@ -450,7 +456,9 @@ mod tests {
Some(StatusCode::NAME_NOT_FOUND)
);
assert_eq!(
binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").await.err(),
binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist")
.await
.err(),
Some(StatusCode::NAME_NOT_FOUND)
);
@ -511,8 +519,9 @@ mod tests {
async fn trivial_client_async() {
let service_name = "trivial_client_test";
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn IATest<Tokio>> =
binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
.await
.expect("Did not get manager binder service");
assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
}
@ -529,8 +538,9 @@ mod tests {
async fn wait_for_trivial_client_async() {
let service_name = "wait_for_trivial_client_test";
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn IATest<Tokio>> =
binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service");
let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::wait_for_interface(service_name)
.await
.expect("Did not get manager binder service");
assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
}
@ -539,9 +549,7 @@ mod tests {
let mut out_ptr = ptr::null_mut();
assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
assert!(!out_ptr.is_null());
CStr::from_ptr(out_ptr)
.to_str()
.expect("context was invalid UTF-8")
CStr::from_ptr(out_ptr).to_str().expect("context was invalid UTF-8")
}
}
@ -551,18 +559,16 @@ mod tests {
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn ITest> =
binder::get_interface(service_name).expect("Did not get manager binder service");
assert_eq!(
test_client.get_selinux_context().unwrap(),
get_expected_selinux_context()
);
assert_eq!(test_client.get_selinux_context().unwrap(), get_expected_selinux_context());
}
#[tokio::test]
async fn get_selinux_context_async() {
let service_name = "get_selinux_context_async";
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn IATest<Tokio>> =
binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
.await
.expect("Did not get manager binder service");
assert_eq!(
test_client.get_selinux_context().await.unwrap(),
get_expected_selinux_context()
@ -586,13 +592,11 @@ mod tests {
async fn get_selinux_context_async_to_sync() {
let service_name = "get_selinux_context";
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn IATest<Tokio>> =
binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
.await
.expect("Did not get manager binder service");
let test_client = test_client.into_sync();
assert_eq!(
test_client.get_selinux_context().unwrap(),
get_expected_selinux_context()
);
assert_eq!(test_client.get_selinux_context().unwrap(), get_expected_selinux_context());
}
struct Bools {
@ -605,10 +609,7 @@ mod tests {
self.binder_died.load(Ordering::Relaxed)
}
fn assert_died(&self) {
assert!(
self.is_dead(),
"Did not receive death notification"
);
assert!(self.is_dead(), "Did not receive death notification");
}
fn assert_dropped(&self) {
assert!(
@ -639,9 +640,7 @@ mod tests {
let mut death_recipient = {
let flag = binder_died.clone();
let set_on_drop = SetOnDrop {
binder_dealloc: binder_dealloc.clone(),
};
let set_on_drop = SetOnDrop { binder_dealloc: binder_dealloc.clone() };
DeathRecipient::new(move || {
flag.store(true, Ordering::Relaxed);
// Force the closure to take ownership of set_on_drop. When the closure is
@ -650,14 +649,9 @@ mod tests {
})
};
binder
.link_to_death(&mut death_recipient)
.expect("link_to_death failed");
binder.link_to_death(&mut death_recipient).expect("link_to_death failed");
let bools = Bools {
binder_died,
binder_dealloc,
};
let bools = Bools { binder_died, binder_dealloc };
(bools, death_recipient)
}
@ -675,9 +669,7 @@ mod tests {
let (bools, recipient) = register_death_notification(&mut remote);
drop(service_process);
remote
.ping_binder()
.expect_err("Service should have died already");
remote.ping_binder().expect_err("Service should have died already");
// Pause to ensure any death notifications get delivered
thread::sleep(Duration::from_secs(1));
@ -701,22 +693,15 @@ mod tests {
let (bools, mut recipient) = register_death_notification(&mut remote);
remote
.unlink_to_death(&mut recipient)
.expect("Could not unlink death notifications");
remote.unlink_to_death(&mut recipient).expect("Could not unlink death notifications");
drop(service_process);
remote
.ping_binder()
.expect_err("Service should have died already");
remote.ping_binder().expect_err("Service should have died already");
// Pause to ensure any death notifications get delivered
thread::sleep(Duration::from_secs(1));
assert!(
!bools.is_dead(),
"Received unexpected death notification after unlinking",
);
assert!(!bools.is_dead(), "Received unexpected death notification after unlinking",);
bools.assert_not_dropped();
drop(recipient);
@ -771,9 +756,7 @@ mod tests {
let dump_args = ["dump", "args", "for", "testing"];
let null_out = File::open("/dev/null").expect("Could not open /dev/null");
remote
.dump(&null_out, &dump_args)
.expect("Could not dump remote service");
remote.dump(&null_out, &dump_args).expect("Could not dump remote service");
let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
@ -799,9 +782,7 @@ mod tests {
let mut remote = binder::get_service(service_name);
assert!(remote.is_binder_alive());
let extension = remote
.get_extension()
.expect("Could not check for an extension");
let extension = remote.get_extension().expect("Could not check for an extension");
assert!(extension.is_none());
}
@ -811,9 +792,7 @@ mod tests {
let mut remote = binder::get_service(service_name);
assert!(remote.is_binder_alive());
let maybe_extension = remote
.get_extension()
.expect("Could not check for an extension");
let maybe_extension = remote.get_extension().expect("Could not check for an extension");
let extension = maybe_extension.expect("Remote binder did not have an extension");
@ -850,15 +829,12 @@ mod tests {
#[test]
fn reassociate_rust_binder() {
let service_name = "testing_service";
let service_ibinder = BnTest::new_binder(
TestService::new(service_name),
BinderFeatures::default(),
)
.as_binder();
let service_ibinder =
BnTest::new_binder(TestService::new(service_name), BinderFeatures::default())
.as_binder();
let service: Strong<dyn ITest> = service_ibinder
.into_interface()
.expect("Could not reassociate the generic ibinder");
let service: Strong<dyn ITest> =
service_ibinder.into_interface().expect("Could not reassociate the generic ibinder");
assert_eq!(service.test().unwrap(), service_name);
}
@ -866,10 +842,7 @@ mod tests {
#[test]
fn weak_binder_upgrade() {
let service_name = "testing_service";
let service = BnTest::new_binder(
TestService::new(service_name),
BinderFeatures::default(),
);
let service = BnTest::new_binder(TestService::new(service_name), BinderFeatures::default());
let weak = Strong::downgrade(&service);
@ -882,10 +855,8 @@ mod tests {
fn weak_binder_upgrade_dead() {
let service_name = "testing_service";
let weak = {
let service = BnTest::new_binder(
TestService::new(service_name),
BinderFeatures::default(),
);
let service =
BnTest::new_binder(TestService::new(service_name), BinderFeatures::default());
Strong::downgrade(&service)
};
@ -896,10 +867,7 @@ mod tests {
#[test]
fn weak_binder_clone() {
let service_name = "testing_service";
let service = BnTest::new_binder(
TestService::new(service_name),
BinderFeatures::default(),
);
let service = BnTest::new_binder(TestService::new(service_name), BinderFeatures::default());
let weak = Strong::downgrade(&service);
let cloned = weak.clone();
@ -915,14 +883,10 @@ mod tests {
#[test]
#[allow(clippy::eq_op)]
fn binder_ord() {
let service1 = BnTest::new_binder(
TestService::new("testing_service1"),
BinderFeatures::default(),
);
let service2 = BnTest::new_binder(
TestService::new("testing_service2"),
BinderFeatures::default(),
);
let service1 =
BnTest::new_binder(TestService::new("testing_service1"), BinderFeatures::default());
let service2 =
BnTest::new_binder(TestService::new("testing_service2"), BinderFeatures::default());
assert!((service1 >= service1));
assert!((service1 <= service1));
@ -931,20 +895,20 @@ mod tests {
#[test]
fn binder_parcel_mixup() {
let service1 = BnTest::new_binder(
TestService::new("testing_service1"),
BinderFeatures::default(),
);
let service2 = BnTest::new_binder(
TestService::new("testing_service2"),
BinderFeatures::default(),
);
let service1 =
BnTest::new_binder(TestService::new("testing_service1"), BinderFeatures::default());
let service2 =
BnTest::new_binder(TestService::new("testing_service2"), BinderFeatures::default());
let service1 = service1.as_binder();
let service2 = service2.as_binder();
let parcel = service1.prepare_transact().unwrap();
let res = service2.submit_transact(super::TestTransactionCode::Test as TransactionCode, parcel, 0);
let res = service2.submit_transact(
super::TestTransactionCode::Test as TransactionCode,
parcel,
0,
);
match res {
Ok(_) => panic!("submit_transact should fail"),
@ -967,15 +931,18 @@ mod tests {
// Should also be false in spawned thread.
std::thread::spawn(|| {
assert!(!binder::is_handling_transaction());
}).join().unwrap();
})
.join()
.unwrap();
}
#[tokio::test]
async fn get_is_handling_transaction_async() {
let service_name = "get_is_handling_transaction_async";
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn IATest<Tokio>> =
binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
.await
.expect("Did not get manager binder service");
// Should be true externally.
assert!(test_client.get_is_handling_transaction().await.unwrap());
@ -985,11 +952,15 @@ mod tests {
// Should also be false in spawned task.
tokio::spawn(async {
assert!(!binder::is_handling_transaction());
}).await.unwrap();
})
.await
.unwrap();
// And in spawn_blocking task.
tokio::task::spawn_blocking(|| {
assert!(!binder::is_handling_transaction());
}).await.unwrap();
})
.await
.unwrap();
}
}

View file

@ -23,7 +23,7 @@ use binder::{
};
// Import from impl API for testing only, should not be necessary as long as you
// are using AIDL.
use binder::binder_impl::{BorrowedParcel, Binder, TransactionCode};
use binder::binder_impl::{Binder, BorrowedParcel, TransactionCode};
use std::ffi::{c_void, CStr, CString};
use std::sync::Once;
@ -64,13 +64,7 @@ macro_rules! assert_eq {
macro_rules! assert {
($expr:expr) => {
if !$expr {
eprintln!(
"assertion failed: `{:?}`, {}:{}:{}",
$expr,
file!(),
line!(),
column!()
);
eprintln!("assertion failed: `{:?}`, {}:{}:{}", $expr, file!(), line!(), column!());
return Err(StatusCode::FAILED_TRANSACTION);
}
};
@ -119,9 +113,7 @@ fn on_transact(
bindings::Transaction_TEST_BOOL => {
assert!(parcel.read::<bool>()?);
assert!(!parcel.read::<bool>()?);
assert_eq!(parcel.read::<Vec<bool>>()?, unsafe {
bindings::TESTDATA_BOOL
});
assert_eq!(parcel.read::<Vec<bool>>()?, unsafe { bindings::TESTDATA_BOOL });
assert_eq!(parcel.read::<Option<Vec<bool>>>()?, None);
reply.write(&true)?;
@ -148,9 +140,7 @@ fn on_transact(
assert_eq!(parcel.read::<u16>()?, 0);
assert_eq!(parcel.read::<u16>()?, 1);
assert_eq!(parcel.read::<u16>()?, u16::max_value());
assert_eq!(parcel.read::<Vec<u16>>()?, unsafe {
bindings::TESTDATA_CHARS
});
assert_eq!(parcel.read::<Vec<u16>>()?, unsafe { bindings::TESTDATA_CHARS });
assert_eq!(parcel.read::<Option<Vec<u16>>>()?, None);
reply.write(&0u16)?;
@ -163,9 +153,7 @@ fn on_transact(
assert_eq!(parcel.read::<i32>()?, 0);
assert_eq!(parcel.read::<i32>()?, 1);
assert_eq!(parcel.read::<i32>()?, i32::max_value());
assert_eq!(parcel.read::<Vec<i32>>()?, unsafe {
bindings::TESTDATA_I32
});
assert_eq!(parcel.read::<Vec<i32>>()?, unsafe { bindings::TESTDATA_I32 });
assert_eq!(parcel.read::<Option<Vec<i32>>>()?, None);
reply.write(&0i32)?;
@ -178,9 +166,7 @@ fn on_transact(
assert_eq!(parcel.read::<i64>()?, 0);
assert_eq!(parcel.read::<i64>()?, 1);
assert_eq!(parcel.read::<i64>()?, i64::max_value());
assert_eq!(parcel.read::<Vec<i64>>()?, unsafe {
bindings::TESTDATA_I64
});
assert_eq!(parcel.read::<Vec<i64>>()?, unsafe { bindings::TESTDATA_I64 });
assert_eq!(parcel.read::<Option<Vec<i64>>>()?, None);
reply.write(&0i64)?;
@ -193,9 +179,7 @@ fn on_transact(
assert_eq!(parcel.read::<u64>()?, 0);
assert_eq!(parcel.read::<u64>()?, 1);
assert_eq!(parcel.read::<u64>()?, u64::max_value());
assert_eq!(parcel.read::<Vec<u64>>()?, unsafe {
bindings::TESTDATA_U64
});
assert_eq!(parcel.read::<Vec<u64>>()?, unsafe { bindings::TESTDATA_U64 });
assert_eq!(parcel.read::<Option<Vec<u64>>>()?, None);
reply.write(&0u64)?;
@ -232,16 +216,9 @@ fn on_transact(
let s: Option<String> = parcel.read()?;
assert_eq!(s, None);
let s: Option<Vec<Option<String>>> = parcel.read()?;
for (s, expected) in s
.unwrap()
.iter()
.zip(unsafe { bindings::TESTDATA_STRS }.iter())
{
let expected = unsafe {
expected
.as_ref()
.and_then(|e| CStr::from_ptr(e).to_str().ok())
};
for (s, expected) in s.unwrap().iter().zip(unsafe { bindings::TESTDATA_STRS }.iter()) {
let expected =
unsafe { expected.as_ref().and_then(|e| CStr::from_ptr(e).to_str().ok()) };
assert_eq!(s.as_deref(), expected);
}
let s: Option<Vec<Option<String>>> = parcel.read()?;
@ -252,10 +229,7 @@ fn on_transact(
.iter()
.map(|s| {
s.as_ref().map(|s| {
CStr::from_ptr(s)
.to_str()
.expect("String was not UTF-8")
.to_owned()
CStr::from_ptr(s).to_str().expect("String was not UTF-8").to_owned()
})
})
.collect()
@ -284,12 +258,8 @@ fn on_transact(
assert!(ibinders[1].is_none());
assert!(parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.is_none());
let service = unsafe {
SERVICE
.as_ref()
.expect("Global binder service not initialized")
.clone()
};
let service =
unsafe { SERVICE.as_ref().expect("Global binder service not initialized").clone() };
reply.write(&service)?;
reply.write(&(None as Option<&SpIBinder>))?;
reply.write(&[Some(&service), None][..])?;
@ -300,10 +270,7 @@ fn on_transact(
assert!(status.is_ok());
let status: Status = parcel.read()?;
assert_eq!(status.exception_code(), ExceptionCode::NULL_POINTER);
assert_eq!(
status.get_description(),
"Status(-4, EX_NULL_POINTER): 'a status message'"
);
assert_eq!(status.get_description(), "Status(-4, EX_NULL_POINTER): 'a status message'");
let status: Status = parcel.read()?;
assert_eq!(status.service_specific_error(), 42);
assert_eq!(

1
rustfmt.toml Symbolic link
View file

@ -0,0 +1 @@
../../build/soong/scripts/rustfmt.toml