Клієнт AIDL

Нарешті ми можемо створити клієнт Rust для нашого нового сервісу.

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";

/// Виклик сервісу привітання з днем народження.
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(|_| "Не вдалося підключитися до BirthdayService")?;

    // Викликаемо сервіс.
    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, // Щоб уникнути помилки динамічного лінкування.
}

Зауважте, що клієнт не залежить від libbirthdayservice.

Створіть, завантажте та запустіть клієнт на своєму пристрої:

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> - це об'єкт трейту, що представляє сервіс, до якого підключився клієнт.
    • Strong - це спеціальний тип розумного вказівника для Binder. Він обробляє як внутрішньопроцесний лічильник посилань на об'єкт сервісного трейту, так і глобальний лічильник посилань Binder, який відстежує, скільки процесів мають посилання на об'єкт.
    • Зверніть увагу, що об'єкт трейта, який клієнт використовує для спілкування з сервісом, використовує той самий трейт, що реалізований на сервері. Для певного інтерфейсу Binder генерується єдиний трейт Rust, який використовується як клієнтом, так і сервером.
  • Використовуйте той самий ідентифікатор сервісу, який використовувався при реєстрації сервісу. В ідеалі він має бути визначений у спільному крейті, на який можуть покладатися як клієнт, так і сервер.