Cliente AIDL

Por fim, podemos criar um cliente Rust para nosso novo serviço.

birthday_server/src/client.rs:

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

const SERVICE_IDENTIFIER: &str = "birthdayservice";

/// Chama o serviço de aniversário.
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(|_| "Falha ao conectar-se a BirthdayService")?;

    // Chama o serviço.
    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, // Para evitar erro de ligação dinâmica.
}

Observe que o cliente não depende de libbirthdayservice.

Compile, envie e execute o cliente em seu dispositivo:

m birthday_client
adb push "$ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp"
adb shell /data/local/tmp/birthday_client Carlos 60
Happy Birthday Charlie, congratulations with the 60 years!
  • Strong<dyn IBirthdayService> é o objeto de trait que representa o serviço ao qual o cliente se conectou.
    • Strong é um tipo de ponteiro inteligente personalizado para Binder. Ele manipula tanto uma contagem de referência no processo para o objeto de trait do serviço, quanto a contagem de referência global do Binder que rastreia quantos processos têm uma referência ao objeto.
    • Observe que o objeto de trait que o cliente usa para falar com o serviço usa exatamente o mesmo trait que o servidor implementa. Para uma interface Binder dada, há um único trait Rust gerado que tanto o cliente quanto o servidor usam.
  • Use o mesmo identificador de serviço usado ao registrar o serviço. Isso deve ser idealmente definido em uma crate comum na qual tanto o cliente quanto o servidor possam depender.