AIDL Client

در‌نهایت، ما می‌توانیم یک Rust client برای سرویس جدید خود ایجاد کنیم.

birthday_service/src/client.rs:

use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;
use com_example_birthdayservice::binder;

const SERVICE_IDENTIFIER: &str = "birthdayservice";

/// Call the birthday service.
fn main() -> Result<(), Box<dyn Error>> {
    let name = std::env::args().nth(1).unwrap_or_else(|| String::from("Bob"));
    let years = std::env::args()
        .nth(2)
        .and_then(|arg| arg.parse::<i32>().ok())
        .unwrap_or(42);

    binder::ProcessState::start_thread_pool();
    let service = binder::get_interface::<dyn IBirthdayService>(SERVICE_IDENTIFIER)
        .map_err(|_| "Failed to connect to BirthdayService")?;

    // Call the service.
    let msg = service.wishHappyBirthday(&name, years)?;
    println!("{msg}");
}

birthday_service/Android.bp:

rust_binary {
    name: "birthday_client",
    crate_name: "birthday_client",
    srcs: ["src/client.rs"],
    rustlibs: [
        "com.example.birthdayservice-rust",
        "libbinder_rs",
    ],
    prefer_rlib: true, // To avoid dynamic link error.
}

توجه داشته باشید که client به libbirthdayservice وابسته نیست.

کلاینت را در دستگاه خود بسازید، push کرده و اجرا کنید:

m birthday_client
adb push "$ANDROID_PRODUCT_OUT/system/bin/birthday_client" /data/local/tmp
adb shell /data/local/tmp/birthday_client Charlie 60
Happy Birthday Charlie, congratulations with the 60 years!
  • Strong<dyn IBirthdayService> یک trait object است که نشان‌دهنده سرویسی است که کلاینت به آن متصل شده است.
    • Strong یک نوع اشاره‌گر هوشمند سفارشی برای Binder است. هم تعداد ref های درون فرآیندی (in-process) را برای سرویس trait object مدیریت می‌کند و هم شمارنده global Binder را که تعداد فرآیندهایی را که به object ارجاع دارند را ردیابی می‌کند.
    • توجه داشته باشید که trait object که کلاینت برای صحبت با سرویس استفاده می‌کند، دقیقاً از همان ویژگی استفاده می‌کند که سرور پیاده‌سازی می‌کند. برای یک Binder interface معین، یک trait یا ویژگی Rust ایجاد شده است که هم کلاینت و هم سرور از آن استفاده می‌کنند.
  • از همان شناسه سرویس استفاده شده در هنگام ثبت سرویس استفاده کنید. این به طور ایده‌آل باید در یک crate مشترک تعریف شود که هم کلاینت و هم سرور می توانند به آن وابسته باشند.