rsbinder icon indicating copy to clipboard operation
rsbinder copied to clipboard

Add the Binder extension feature.

Open hiking90 opened this issue 1 year ago • 0 comments

However, is this feature really necessary?

When checked in AOSP, only a few services were using this feature.

/// Set the extension of a binder interface. This allows a downstream
/// developer to add an extension to an interface without modifying its
/// interface file. This should be called immediately when the object is
/// created before it is passed to another thread.
///
/// # Examples
///
/// For instance, imagine if we have this Binder AIDL interface definition:
///     interface IFoo { void doFoo(); }
///
/// If an unrelated owner (perhaps in a downstream codebase) wants to make a
/// change to the interface, they have two options:
///
/// 1) Historical option that has proven to be BAD! Only the original
///    author of an interface should change an interface. If someone
///    downstream wants additional functionality, they should not ever
///    change the interface or use this method.
///    ```AIDL
///    BAD TO DO:  interface IFoo {                       BAD TO DO
///    BAD TO DO:      void doFoo();                      BAD TO DO
///    BAD TO DO: +    void doBar(); // adding a method   BAD TO DO
///    BAD TO DO:  }                                      BAD TO DO
///    ```
///
/// 2) Option that this method enables!
///    Leave the original interface unchanged (do not change IFoo!).
///    Instead, create a new AIDL interface in a downstream package:
///    ```AIDL
///    package com.<name>; // new functionality in a new package
///    interface IBar { void doBar(); }
///    ```
///
///    When registering the interface, add:
///
///        # use binder::{Binder, Interface};
///        # type MyFoo = ();
///        # type MyBar = ();
///        # let my_foo = ();
///        # let my_bar = ();
///        let mut foo: Binder<MyFoo> = Binder::new(my_foo); // class in AOSP codebase
///        let bar: Binder<MyBar> = Binder::new(my_bar);     // custom extension class
///        foo.set_extension(&mut bar.as_binder());          // use method in Binder
///
///    Then, clients of `IFoo` can get this extension:
///
///        # use binder::{declare_binder_interface, Binder, TransactionCode, Parcel};
///        # trait IBar {}
///        # declare_binder_interface! {
///        #     IBar["test"] {
///        #         native: BnBar(on_transact),
///        #         proxy: BpBar,
///        #     }
///        # }
///        # fn on_transact(
///        #     service: &dyn IBar,
///        #     code: TransactionCode,
///        #     data: &BorrowedParcel,
///        #     reply: &mut BorrowedParcel,
///        # ) -> binder::Result<()> {
///        #     Ok(())
///        # }
///        # impl IBar for BpBar {}
///        # impl IBar for Binder<BnBar> {}
///        # fn main() -> binder::Result<()> {
///        # let binder = Binder::new(());
///        if let Some(barBinder) = binder.get_extension()? {
///            let bar = BpBar::new(barBinder)
///                .expect("Extension was not of type IBar");
///        } else {
///            // There was no extension
///        }
///        # }

hiking90 avatar Jan 27 '24 23:01 hiking90