Loading libs/binder/TEST_MAPPING +3 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,9 @@ }, { "name": "rustBinderTest" }, { "name": "binderRustNdkInteropTest" } ] } libs/binder/rust/src/binder.rs +45 −14 Original line number Diff line number Diff line Loading @@ -21,7 +21,8 @@ use crate::parcel::Parcel; use crate::proxy::{DeathRecipient, SpIBinder}; use crate::sys; use std::ffi::{c_void, CString}; use std::ffi::{c_void, CStr, CString}; use std::os::raw::c_char; use std::os::unix::io::AsRawFd; use std::ptr; Loading Loading @@ -205,6 +206,22 @@ impl InterfaceClass { pub(crate) unsafe fn from_ptr(ptr: *const sys::AIBinder_Class) -> InterfaceClass { InterfaceClass(ptr) } /// Get the interface descriptor string of this class. pub fn get_descriptor(&self) -> String { unsafe { // SAFETY: The descriptor returned by AIBinder_Class_getDescriptor // is always a two-byte null terminated sequence of u16s. Thus, we // can continue reading from the pointer until we hit a null value, // and this pointer can be a valid slice if the slice length is <= // the number of u16 elements before the null terminator. let raw_descriptor: *const c_char = sys::AIBinder_Class_getDescriptor(self.0); CStr::from_ptr(raw_descriptor).to_str() .expect("Expected valid UTF-8 string from AIBinder_Class_getDescriptor") .into() } } } impl From<InterfaceClass> for *const sys::AIBinder_Class { Loading Loading @@ -507,12 +524,7 @@ macro_rules! declare_binder_interface { } fn from_binder(mut binder: $crate::SpIBinder) -> $crate::Result<Self> { use $crate::AssociateClass; if binder.associate_class(<$native as $crate::Remotable>::get_class()) { Ok(Self { binder, $($fname: $finit),* }) } else { Err($crate::StatusCode::BAD_TYPE) } } } Loading Loading @@ -567,16 +579,35 @@ macro_rules! declare_binder_interface { impl $crate::FromIBinder for dyn $interface { fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> { use $crate::AssociateClass; if !ibinder.associate_class(<$native as $crate::Remotable>::get_class()) { return Err($crate::StatusCode::BAD_TYPE.into()); let existing_class = ibinder.get_class(); if let Some(class) = existing_class { if class != <$native as $crate::Remotable>::get_class() && class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor() { // The binder object's descriptor string matches what we // expect. We still need to treat this local or already // associated object as remote, because we can't cast it // into a Rust service object without a matching class // pointer. return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); } } let service: $crate::Result<$crate::Binder<$native>> = std::convert::TryFrom::try_from(ibinder.clone()); if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) { let service: $crate::Result<$crate::Binder<$native>> = std::convert::TryFrom::try_from(ibinder.clone()); if let Ok(service) = service { Ok(Box::new(service)) // We were able to associate with our expected class and // the service is local. return Ok(Box::new(service)); } else { Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)) // Service is remote return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); } } Err($crate::StatusCode::BAD_TYPE.into()) } } Loading libs/binder/rust/src/proxy.rs +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ impl SpIBinder { /// Return the interface class of this binder object, if associated with /// one. pub(crate) fn get_class(&mut self) -> Option<InterfaceClass> { pub fn get_class(&mut self) -> Option<InterfaceClass> { unsafe { // Safety: `SpIBinder` guarantees that it always contains a valid // `AIBinder` pointer. `AIBinder_getClass` returns either a null Loading libs/binder/rust/tests/Android.bp +49 −0 Original line number Diff line number Diff line Loading @@ -30,3 +30,52 @@ rust_test { auto_gen_config: false, test_suites: ["general-tests"], } cc_test { name: "binderRustNdkInteropTest", srcs: [ "binderRustNdkInteropTest.cpp", ], shared_libs: [ "libbinder", "libbinder_ndk", ], static_libs: [ "IBinderRustNdkInteropTest-ndk_platform", "libbinder_ndk_rust_interop", ], test_suites: ["general-tests"], require_root: true, // rustBinderTestService uses a custom config auto_gen_config: true, } aidl_interface { name: "IBinderRustNdkInteropTest", unstable: true, srcs: [ "IBinderRustNdkInteropTest.aidl", "IBinderRustNdkInteropTestOther.aidl", ], backend: { ndk: { enabled: true, }, rust: { enabled: true, }, }, } rust_ffi_static { name: "libbinder_ndk_rust_interop", crate_name: "binder_ndk_rust_interop", srcs: [ "ndk_rust_interop.rs", ], rustlibs: [ "libbinder_rs", "IBinderRustNdkInteropTest-rust", ], } libs/binder/rust/tests/IBinderRustNdkInteropTest.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * 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. */ interface IBinderRustNdkInteropTest { @utf8InCpp String echo(@utf8InCpp String str); } Loading
libs/binder/TEST_MAPPING +3 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,9 @@ }, { "name": "rustBinderTest" }, { "name": "binderRustNdkInteropTest" } ] }
libs/binder/rust/src/binder.rs +45 −14 Original line number Diff line number Diff line Loading @@ -21,7 +21,8 @@ use crate::parcel::Parcel; use crate::proxy::{DeathRecipient, SpIBinder}; use crate::sys; use std::ffi::{c_void, CString}; use std::ffi::{c_void, CStr, CString}; use std::os::raw::c_char; use std::os::unix::io::AsRawFd; use std::ptr; Loading Loading @@ -205,6 +206,22 @@ impl InterfaceClass { pub(crate) unsafe fn from_ptr(ptr: *const sys::AIBinder_Class) -> InterfaceClass { InterfaceClass(ptr) } /// Get the interface descriptor string of this class. pub fn get_descriptor(&self) -> String { unsafe { // SAFETY: The descriptor returned by AIBinder_Class_getDescriptor // is always a two-byte null terminated sequence of u16s. Thus, we // can continue reading from the pointer until we hit a null value, // and this pointer can be a valid slice if the slice length is <= // the number of u16 elements before the null terminator. let raw_descriptor: *const c_char = sys::AIBinder_Class_getDescriptor(self.0); CStr::from_ptr(raw_descriptor).to_str() .expect("Expected valid UTF-8 string from AIBinder_Class_getDescriptor") .into() } } } impl From<InterfaceClass> for *const sys::AIBinder_Class { Loading Loading @@ -507,12 +524,7 @@ macro_rules! declare_binder_interface { } fn from_binder(mut binder: $crate::SpIBinder) -> $crate::Result<Self> { use $crate::AssociateClass; if binder.associate_class(<$native as $crate::Remotable>::get_class()) { Ok(Self { binder, $($fname: $finit),* }) } else { Err($crate::StatusCode::BAD_TYPE) } } } Loading Loading @@ -567,16 +579,35 @@ macro_rules! declare_binder_interface { impl $crate::FromIBinder for dyn $interface { fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> { use $crate::AssociateClass; if !ibinder.associate_class(<$native as $crate::Remotable>::get_class()) { return Err($crate::StatusCode::BAD_TYPE.into()); let existing_class = ibinder.get_class(); if let Some(class) = existing_class { if class != <$native as $crate::Remotable>::get_class() && class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor() { // The binder object's descriptor string matches what we // expect. We still need to treat this local or already // associated object as remote, because we can't cast it // into a Rust service object without a matching class // pointer. return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); } } let service: $crate::Result<$crate::Binder<$native>> = std::convert::TryFrom::try_from(ibinder.clone()); if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) { let service: $crate::Result<$crate::Binder<$native>> = std::convert::TryFrom::try_from(ibinder.clone()); if let Ok(service) = service { Ok(Box::new(service)) // We were able to associate with our expected class and // the service is local. return Ok(Box::new(service)); } else { Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)) // Service is remote return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); } } Err($crate::StatusCode::BAD_TYPE.into()) } } Loading
libs/binder/rust/src/proxy.rs +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ impl SpIBinder { /// Return the interface class of this binder object, if associated with /// one. pub(crate) fn get_class(&mut self) -> Option<InterfaceClass> { pub fn get_class(&mut self) -> Option<InterfaceClass> { unsafe { // Safety: `SpIBinder` guarantees that it always contains a valid // `AIBinder` pointer. `AIBinder_getClass` returns either a null Loading
libs/binder/rust/tests/Android.bp +49 −0 Original line number Diff line number Diff line Loading @@ -30,3 +30,52 @@ rust_test { auto_gen_config: false, test_suites: ["general-tests"], } cc_test { name: "binderRustNdkInteropTest", srcs: [ "binderRustNdkInteropTest.cpp", ], shared_libs: [ "libbinder", "libbinder_ndk", ], static_libs: [ "IBinderRustNdkInteropTest-ndk_platform", "libbinder_ndk_rust_interop", ], test_suites: ["general-tests"], require_root: true, // rustBinderTestService uses a custom config auto_gen_config: true, } aidl_interface { name: "IBinderRustNdkInteropTest", unstable: true, srcs: [ "IBinderRustNdkInteropTest.aidl", "IBinderRustNdkInteropTestOther.aidl", ], backend: { ndk: { enabled: true, }, rust: { enabled: true, }, }, } rust_ffi_static { name: "libbinder_ndk_rust_interop", crate_name: "binder_ndk_rust_interop", srcs: [ "ndk_rust_interop.rs", ], rustlibs: [ "libbinder_rs", "IBinderRustNdkInteropTest-rust", ], }
libs/binder/rust/tests/IBinderRustNdkInteropTest.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * 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. */ interface IBinderRustNdkInteropTest { @utf8InCpp String echo(@utf8InCpp String str); }