diff options
author | Matthew Maurer <mmaurer@google.com> | 2020-08-26 04:13:43 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-08-26 04:13:43 +0000 |
commit | 53f928887048073715d46d0f457150d9a4d2725f (patch) | |
tree | 78d5a7c7857b213adae55e50be5484791e265910 | |
parent | a7e3f1d7f55ca60f64eb13928c8e1f19cea7b0f1 (diff) | |
parent | 994a0f0d4492b6ea1f5cf46b6007a940fd4cb78b (diff) | |
download | native-53f928887048073715d46d0f457150d9a4d2725f.tar.gz |
Merge changes Ia2f891c2,Ibbe111b0
* changes:
Add trait implementations for Rust binder crate
Add sized sub-parcel write method
-rw-r--r-- | libs/binder/rust/Android.bp | 22 | ||||
-rw-r--r-- | libs/binder/rust/src/error.rs | 8 | ||||
-rw-r--r-- | libs/binder/rust/src/lib.rs | 2 | ||||
-rw-r--r-- | libs/binder/rust/src/parcel.rs | 95 | ||||
-rw-r--r-- | libs/binder/rust/src/proxy.rs | 20 | ||||
-rw-r--r-- | libs/binder/rust/sys/BinderBindings.h (renamed from libs/binder/rust/BinderBindings.h) | 0 | ||||
-rw-r--r-- | libs/binder/rust/sys/lib.rs | 38 |
7 files changed, 171 insertions, 14 deletions
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index 16811eebe4..0234820b02 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -3,12 +3,24 @@ rust_library { crate_name: "binder", srcs: ["src/lib.rs"], shared_libs: [ - "libbinder_ndk", "libutils", ], rustlibs: [ "liblibc", - "libbinder_ndk_bindgen", + "libbinder_ndk_sys", + ], + host_supported: true, +} + +rust_library { + name: "libbinder_ndk_sys", + crate_name: "binder_ndk_sys", + srcs: [ + "sys/lib.rs", + ":libbinder_ndk_bindgen", + ], + shared_libs: [ + "libbinder_ndk", ], host_supported: true, } @@ -16,8 +28,8 @@ rust_library { rust_bindgen { name: "libbinder_ndk_bindgen", crate_name: "binder_ndk_bindgen", - wrapper_src: "BinderBindings.h", - source_stem: "ndk_bindings", + wrapper_src: "sys/BinderBindings.h", + source_stem: "bindings", cflags: [ "-x c++", ], @@ -69,6 +81,6 @@ rust_test { ], rustlibs: [ "liblibc", - "libbinder_ndk_bindgen", + "libbinder_ndk_sys", ], } diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs index 289b1573db..4492cf72f4 100644 --- a/libs/binder/rust/src/error.rs +++ b/libs/binder/rust/src/error.rs @@ -43,14 +43,6 @@ pub fn status_result(status: status_t) -> Result<()> { } } -// impl Display for StatusCode { -// fn fmt(&self, f: &mut Formatter) -> FmtResult { -// write!(f, "StatusCode::{:?}", self) -// } -// } - -// impl error::Error for StatusCode {} - fn parse_status_code(code: i32) -> StatusCode { match code { e if e == StatusCode::OK as i32 => StatusCode::OK, diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 4b9cccf41b..8ee6a62180 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -102,7 +102,7 @@ mod error; mod native; mod state; -use binder_ndk_bindgen as sys; +use binder_ndk_sys as sys; pub mod parcel; diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs index 43850fe411..a248f5c510 100644 --- a/libs/binder/rust/src/parcel.rs +++ b/libs/binder/rust/src/parcel.rs @@ -21,6 +21,7 @@ use crate::error::{status_result, Result, StatusCode}; use crate::proxy::SpIBinder; use crate::sys; +use std::cell::RefCell; use std::convert::TryInto; use std::mem::ManuallyDrop; use std::ptr; @@ -117,6 +118,55 @@ impl Parcel { } } + /// Perform a series of writes to the `Parcel`, prepended with the length + /// (in bytes) of the written data. + /// + /// The length `0i32` will be written to the parcel first, followed by the + /// writes performed by the callback. The initial length will then be + /// updated to the length of all data written by the callback, plus the + /// size of the length elemement itself (4 bytes). + /// + /// # Examples + /// + /// After the following call: + /// + /// ``` + /// # use binder::{Binder, Interface, Parcel}; + /// # let mut parcel = Parcel::Owned(std::ptr::null_mut()); + /// parcel.sized_write(|subparcel| { + /// subparcel.write(&1u32)?; + /// subparcel.write(&2u32)?; + /// subparcel.write(&3u32) + /// }); + /// ``` + /// + /// `parcel` will contain the following: + /// + /// ```ignore + /// [16i32, 1u32, 2u32, 3u32] + /// ``` + pub fn sized_write<F>(&mut self, f: F) -> Result<()> + where for<'a> + F: Fn(&'a WritableSubParcel<'a>) -> Result<()> + { + let start = self.get_data_position(); + self.write(&0i32)?; + { + let subparcel = WritableSubParcel(RefCell::new(self)); + f(&subparcel)?; + } + let end = self.get_data_position(); + unsafe { + self.set_data_position(start)?; + } + assert!(end >= start); + self.write(&(end - start))?; + unsafe { + self.set_data_position(end)?; + } + Ok(()) + } + /// Returns the current position in the parcel data. pub fn get_data_position(&self) -> i32 { unsafe { @@ -143,6 +193,16 @@ impl Parcel { } } +/// A segment of a writable parcel, used for [`Parcel::sized_write`]. +pub struct WritableSubParcel<'a>(RefCell<&'a mut Parcel>); + +impl<'a> WritableSubParcel<'a> { + /// Write a type that implements [`Serialize`] to the sub-parcel. + pub fn write<S: Serialize + ?Sized>(&self, parcelable: &S) -> Result<()> { + parcelable.serialize(&mut *self.0.borrow_mut()) + } +} + // Data deserialization methods impl Parcel { /// Attempt to read a type that implements [`Deserialize`] from this @@ -445,3 +505,38 @@ fn test_utf8_utf16_conversions() { ); assert_eq!(parcel.read::<Vec<String>>().unwrap(), [s1, s2, s3]); } + +#[test] +fn test_sized_write() { + use crate::binder::Interface; + use crate::native::Binder; + + let mut service = Binder::new(()).as_binder(); + let mut parcel = Parcel::new_for_test(&mut service).unwrap(); + let start = parcel.get_data_position(); + + let arr = [1i32, 2i32, 3i32]; + + 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; + + assert_eq!(parcel.get_data_position(), start + expected_len); + + unsafe { + parcel.set_data_position(start).unwrap(); + } + + assert_eq!( + expected_len, + parcel.read().unwrap(), + ); + + assert_eq!( + parcel.read::<Vec<i32>>().unwrap(), + &arr, + ); +} diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs index f9519b4d01..13e5619237 100644 --- a/libs/binder/rust/src/proxy.rs +++ b/libs/binder/rust/src/proxy.rs @@ -122,6 +122,14 @@ impl AssociateClass for SpIBinder { } } +impl PartialEq for SpIBinder { + fn eq(&self, other: &Self) -> bool { + ptr::eq(self.0, other.0) + } +} + +impl Eq for SpIBinder {} + impl Clone for SpIBinder { fn clone(&self) -> Self { unsafe { @@ -363,6 +371,18 @@ impl WpIBinder { assert!(!ptr.is_null()); Self(ptr) } + + /// Promote this weak reference to a strong reference to the binder object. + pub fn promote(&self) -> Option<SpIBinder> { + unsafe { + // Safety: `WpIBinder` always contains a valid weak reference, so we + // can pass this pointer to `AIBinder_Weak_promote`. Returns either + // null or an AIBinder owned by the caller, both of which are valid + // to pass to `SpIBinder::from_raw`. + let ptr = sys::AIBinder_Weak_promote(self.0); + SpIBinder::from_raw(ptr) + } + } } /// Rust wrapper around DeathRecipient objects. diff --git a/libs/binder/rust/BinderBindings.h b/libs/binder/rust/sys/BinderBindings.h index c7a06d9a1c..c7a06d9a1c 100644 --- a/libs/binder/rust/BinderBindings.h +++ b/libs/binder/rust/sys/BinderBindings.h diff --git a/libs/binder/rust/sys/lib.rs b/libs/binder/rust/sys/lib.rs new file mode 100644 index 0000000000..9095af29e0 --- /dev/null +++ b/libs/binder/rust/sys/lib.rs @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! Generated Rust bindings to libbinder_ndk + +#![allow( + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused, + improper_ctypes, + missing_docs +)] +use std::error::Error; +use std::fmt; + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +impl Error for android_c_interface_StatusCode {} + +impl fmt::Display for android_c_interface_StatusCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "StatusCode::{:?}", self) + } +} |