Service Implementation

We can now implement the AIDL service:

birthday_service/src/lib.rs:

//! Implementation of the `IBirthdayService` AIDL interface. use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService; use com_example_birthdayservice::binder; /// The `IBirthdayService` implementation. pub struct BirthdayService; impl binder::Interface for BirthdayService {} impl IBirthdayService for BirthdayService { fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result<String> { Ok(format!("Happy Birthday {name}, congratulations with the {years} years!")) } }

birthday_service/Android.bp:

rust_library { name: "libbirthdayservice", srcs: ["src/lib.rs"], crate_name: "birthdayservice", rustlibs: [ "com.example.birthdayservice-rust", "libbinder_rs", ], }

Speaker Notes

  • Point out the path to the generated IBirthdayService trait, and explain why each of the segments is necessary.
  • Note that wishHappyBirthday and other AIDL IPC methods take &self (instead of &mut self).
    • This is necessary because binder responds to incoming requests on a thread pool, allowing for multiple requests to be processed in parallel. This requires that the service methods only get a shared reference to self.
    • Any state that needs to be modified by the service will have to be put in something like a Mutex to allow for safe mutation.
    • The correct approach for managing service state depends heavily on the details of your service.
  • TODO: What does the binder::Interface trait do? Are there methods to override? Where source?