Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75d71127 authored by Matthew Maurer's avatar Matthew Maurer
Browse files

rust: Bind to NDK subset of libbinder

Test: cargo build --target aarch64-linux-android
Bug: 368303574
Change-Id: Id4db842d5dff195393e1ce563479c58b91e3e879
parent cf0037d8
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
[package]
name = "android-binder"
version = "0.1.0"
edition = "2021"
description = "Safe bindings to Android Binder, restricted to the NDK"
license = "Apache-2.0"

[dependencies]
binder-ndk-sys = { package = "android-binder-ndk-sys", version = "0.1", path = "./sys" }
downcast-rs = "1.2.1"
libc = "0.2.159"

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = ["cfg(android_vendor)", "cfg(android_ndk)", "cfg(android_vndk)", "cfg(trusty)"]
+4 −0
Original line number Diff line number Diff line
fn main() {
    // Anything with cargo is NDK only. If you want to access anything else, use Soong.
    println!("cargo::rustc-cfg=android_ndk");
}
+9 −4
Original line number Diff line number Diff line
@@ -207,8 +207,10 @@ pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
/// Corresponds to TF_ONE_WAY -- an asynchronous call.
pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
#[cfg(not(android_ndk))]
pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
/// Set to the vendor flag if we are building for the VNDK, 0 otherwise
#[cfg(not(android_ndk))]
pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL;

/// Internal interface of binder local or remote objects for making
@@ -221,7 +223,7 @@ pub trait IBinderInternal: IBinder {
    fn is_binder_alive(&self) -> bool;

    /// Indicate that the service intends to receive caller security contexts.
    #[cfg(not(android_vndk))]
    #[cfg(not(any(android_vndk, android_ndk)))]
    fn set_requesting_sid(&mut self, enable: bool);

    /// Dump this object to the given file handle
@@ -346,7 +348,6 @@ impl InterfaceClass {
                panic!("Expected non-null class pointer from AIBinder_Class_define!");
            }
            sys::AIBinder_Class_setOnDump(class, Some(I::on_dump));
            sys::AIBinder_Class_setHandleShellCommand(class, None);
            class
        };
        InterfaceClass(ptr)
@@ -714,7 +715,7 @@ unsafe impl<T, V: AsNative<T>> AsNative<T> for Option<V> {
pub struct BinderFeatures {
    /// Indicates that the service intends to receive caller security contexts. This must be true
    /// for `ThreadState::with_calling_sid` to work.
    #[cfg(not(android_vndk))]
    #[cfg(not(any(android_vndk, android_ndk)))]
    pub set_requesting_sid: bool,
    // Ensure that clients include a ..BinderFeatures::default() to preserve backwards compatibility
    // when new fields are added. #[non_exhaustive] doesn't work because it prevents struct
@@ -916,8 +917,12 @@ macro_rules! declare_binder_interface {
        impl $native {
            /// Create a new binder service.
            pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
                #[cfg(not(android_ndk))]
                let mut binder = $crate::binder_impl::Binder::new_with_stability($native(Box::new(inner)), $stability);
                #[cfg(not(android_vndk))]
                #[cfg(android_ndk)]
                let mut binder = $crate::binder_impl::Binder::new($native(Box::new(inner)));

                #[cfg(not(any(android_vndk, android_ndk)))]
                $crate::binder_impl::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
                $crate::Strong::new(Box::new(binder))
            }
+14 −10
Original line number Diff line number Diff line
@@ -100,11 +100,11 @@ mod error;
mod native;
mod parcel;
mod proxy;
#[cfg(not(trusty))]
#[cfg(not(any(trusty, android_ndk)))]
mod service;
#[cfg(not(trusty))]
#[cfg(not(any(trusty, android_ndk)))]
mod state;
#[cfg(not(any(android_vendor, android_vndk)))]
#[cfg(not(any(android_vendor, android_ndk, android_vndk)))]
mod system_only;

use binder_ndk_sys as sys;
@@ -114,15 +114,18 @@ pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
pub use error::{ExceptionCode, IntoBinderResult, Status, StatusCode};
pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
#[cfg(not(trusty))]
#[cfg(not(any(trusty, android_ndk)))]
pub use service::{
    add_service, check_interface, check_service, force_lazy_services_persist,
    get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction,
    register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard,
    get_declared_instances, is_declared, is_handling_transaction, register_lazy_service,
    wait_for_interface, wait_for_service, LazyServiceGuard,
};
#[cfg(not(trusty))]
#[cfg(not(any(trusty, android_ndk)))]
#[allow(deprecated)]
pub use service::{get_interface, get_service};
#[cfg(not(any(trusty, android_ndk)))]
pub use state::{ProcessState, ThreadState};
#[cfg(not(any(android_vendor, android_vndk)))]
#[cfg(not(any(android_vendor, android_vndk, android_ndk)))]
pub use system_only::{delegate_accessor, Accessor, ConnectionInfo};

/// Binder result containing a [`Status`] on error.
@@ -134,9 +137,10 @@ pub mod binder_impl {
    pub use crate::binder::{
        IBinderInternal, InterfaceClass, LocalStabilityType, Remotable, Stability, StabilityType,
        ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, VintfStabilityType,
        FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL,
        LAST_CALL_TRANSACTION,
        FIRST_CALL_TRANSACTION, FLAG_ONEWAY, LAST_CALL_TRANSACTION,
    };
    #[cfg(not(android_ndk))]
    pub use crate::binder::{FLAG_CLEAR_BUF, FLAG_PRIVATE_LOCAL};
    pub use crate::binder_async::BinderAsyncRuntime;
    pub use crate::error::status_t;
    pub use crate::native::Binder;
+25 −8
Original line number Diff line number Diff line
@@ -14,9 +14,9 @@
 * limitations under the License.
 */

use crate::binder::{
    AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode,
};
#[cfg(not(android_ndk))]
use crate::binder::Stability;
use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, TransactionCode};
use crate::error::{status_result, status_t, Result, StatusCode};
use crate::parcel::{BorrowedParcel, Serialize};
use crate::proxy::SpIBinder;
@@ -76,14 +76,32 @@ impl<T: Remotable> Binder<T> {
    /// This moves the `rust_object` into an owned [`Box`] and Binder will
    /// manage its lifetime.
    pub fn new(rust_object: T) -> Binder<T> {
        #[cfg(not(android_ndk))]
        {
            Self::new_with_stability(rust_object, Stability::default())
        }
        #[cfg(android_ndk)]
        {
            Self::new_unmarked(rust_object)
        }
    }

    /// Create a new Binder remotable object with the given stability
    ///
    /// This moves the `rust_object` into an owned [`Box`] and Binder will
    /// manage its lifetime.
    #[cfg(not(android_ndk))]
    pub fn new_with_stability(rust_object: T, stability: Stability) -> Binder<T> {
        let mut binder = Self::new_unmarked(rust_object);
        binder.mark_stability(stability);
        binder
    }

    /// Creates a new Binder remotable object with unset stability
    ///
    /// This is internal because normally we want to set the stability explicitly,
    /// however for the NDK variant we cannot mark the stability.
    fn new_unmarked(rust_object: T) -> Binder<T> {
        let class = T::get_class();
        let rust_object = Box::into_raw(Box::new(rust_object));
        // Safety: `AIBinder_new` expects a valid class pointer (which we
@@ -93,9 +111,7 @@ impl<T: Remotable> Binder<T> {
        // decremented via `AIBinder_decStrong` when the reference lifetime
        // ends.
        let ibinder = unsafe { sys::AIBinder_new(class.into(), rust_object as *mut c_void) };
        let mut binder = Binder { ibinder, rust_object };
        binder.mark_stability(stability);
        binder
        Binder { ibinder, rust_object }
    }

    /// Set the extension of a binder interface. This allows a downstream
@@ -189,6 +205,7 @@ impl<T: Remotable> Binder<T> {
    }

    /// Mark this binder object with the given stability guarantee
    #[cfg(not(android_ndk))]
    fn mark_stability(&mut self, stability: Stability) {
        match stability {
            Stability::Local => self.mark_local_stability(),
@@ -215,7 +232,7 @@ impl<T: Remotable> Binder<T> {

    /// Mark this binder object with local stability, which is vendor if we are
    /// building for android_vendor and system otherwise.
    #[cfg(not(android_vendor))]
    #[cfg(not(any(android_vendor, android_ndk)))]
    fn mark_local_stability(&mut self) {
        // Safety: Self always contains a valid `AIBinder` pointer, so we can
        // always call this C API safely.
Loading