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:
parent
eae8088caa
commit
e268a9fca0
15 changed files with 229 additions and 379 deletions
|
@ -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/
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
1
rustfmt.toml
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../build/soong/scripts/rustfmt.toml
|
Loading…
Reference in a new issue