summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Maurer <mmaurer@google.com>2020-08-26 04:13:43 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-08-26 04:13:43 +0000
commit53f928887048073715d46d0f457150d9a4d2725f (patch)
tree78d5a7c7857b213adae55e50be5484791e265910
parenta7e3f1d7f55ca60f64eb13928c8e1f19cea7b0f1 (diff)
parent994a0f0d4492b6ea1f5cf46b6007a940fd4cb78b (diff)
downloadnative-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.bp22
-rw-r--r--libs/binder/rust/src/error.rs8
-rw-r--r--libs/binder/rust/src/lib.rs2
-rw-r--r--libs/binder/rust/src/parcel.rs95
-rw-r--r--libs/binder/rust/src/proxy.rs20
-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.rs38
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)
+ }
+}