rsbinder
rsbinder copied to clipboard
Add the Binder extension feature.
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
/// }
/// # }