deprecate binder::get_service, add binder::check_service

Deprecate `get_service` because the underlying NDK function
`AServiceManager_getService` has been deprecated. `check_service` is
added to give access to one of the suggested alternatives.

Bug: 339248908
Test: atest --test-mapping frameworks/native/libs/binder/TEST_MAPPING
Change-Id: Iac89691f651c55df532a2dc2462db9f2795ad170
diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs
index 1dc0b24..71bb95b 100644
--- a/libs/binder/rust/binder_tokio/lib.rs
+++ b/libs/binder/rust/binder_tokio/lib.rs
@@ -34,6 +34,7 @@
 
 /// Retrieve an existing service for a particular interface, sleeping for a few
 /// seconds if it doesn't yet exist.
+#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
 pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(
     name: &str,
 ) -> Result<Strong<T>, StatusCode> {
@@ -56,6 +57,32 @@
     }
 }
 
+/// Retrieve an existing service for a particular interface. Returns
+/// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available.
+///
+/// NOTE: "immediately" above does not mean the future will complete the first time it is polled.
+pub async fn check_interface<T: FromIBinder + ?Sized + 'static>(
+    name: &str,
+) -> Result<Strong<T>, StatusCode> {
+    if binder::is_handling_transaction() {
+        // See comment in the BinderAsyncPool impl.
+        return binder::check_interface::<T>(name);
+    }
+
+    let name = name.to_string();
+    let res = tokio::task::spawn_blocking(move || binder::check_interface::<T>(&name)).await;
+
+    // The `is_panic` branch is not actually reachable in Android as we compile
+    // with `panic = abort`.
+    match res {
+        Ok(Ok(service)) => Ok(service),
+        Ok(Err(err)) => Err(err),
+        Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+        Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
+        Err(_) => Err(StatusCode::UNKNOWN_ERROR),
+    }
+}
+
 /// Retrieve an existing service for a particular interface, or start it if it
 /// is configured as a dynamic service and isn't yet started.
 pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 0f9c58c..e70f4f0 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -114,9 +114,9 @@
 pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
 #[cfg(not(trusty))]
 pub use service::{
-    add_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service,
-    is_declared, is_handling_transaction, register_lazy_service, wait_for_interface,
-    wait_for_service, LazyServiceGuard,
+    add_service, check_interface, check_service, force_lazy_services_persist,
+    get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction,
+    register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard,
 };
 #[cfg(not(trusty))]
 pub use state::{ProcessState, ThreadState};
diff --git a/libs/binder/rust/src/service.rs b/libs/binder/rust/src/service.rs
index 3ca3b54..29dd8e1 100644
--- a/libs/binder/rust/src/service.rs
+++ b/libs/binder/rust/src/service.rs
@@ -144,6 +144,7 @@
 
 /// Retrieve an existing service, blocking for a few seconds if it doesn't yet
 /// exist.
+#[deprecated = "this polls 5s, use wait_for_service or check_service"]
 pub fn get_service(name: &str) -> Option<SpIBinder> {
     let name = CString::new(name).ok()?;
     // Safety: `AServiceManager_getService` returns either a null pointer or a
@@ -152,6 +153,15 @@
     unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) }
 }
 
+/// Retrieve an existing service. Returns `None` immediately if the service is not available.
+pub fn check_service(name: &str) -> Option<SpIBinder> {
+    let name = CString::new(name).ok()?;
+    // Safety: `AServiceManager_checkService` returns either a null pointer or
+    // a valid pointer to an owned `AIBinder`. Either of these values is safe to
+    // pass to `SpIBinder::from_raw`.
+    unsafe { SpIBinder::from_raw(sys::AServiceManager_checkService(name.as_ptr())) }
+}
+
 /// Retrieve an existing service, or start it if it is configured as a dynamic
 /// service and isn't yet started.
 pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
@@ -164,10 +174,17 @@
 
 /// Retrieve an existing service for a particular interface, blocking for a few
 /// seconds if it doesn't yet exist.
+#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
 pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
     interface_cast(get_service(name))
 }
 
+/// Retrieve an existing service for a particular interface. Returns
+/// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available.
+pub fn check_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
+    interface_cast(check_service(name))
+}
+
 /// Retrieve an existing service for a particular interface, or start it if it
 /// is configured as a dynamic service and isn't yet started.
 pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index c87fa89..15ae56f 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -421,7 +421,7 @@
     }
 
     #[test]
-    fn check_services() {
+    fn check_get_service() {
         let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
         assert!(sm.is_binder_alive());
         assert!(sm.ping_binder().is_ok());
@@ -445,7 +445,7 @@
     }
 
     #[tokio::test]
-    async fn check_services_async() {
+    async fn check_get_service_async() {
         let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
         assert!(sm.is_binder_alive());
         assert!(sm.ping_binder().is_ok());
@@ -474,6 +474,62 @@
     }
 
     #[test]
+    fn check_check_service() {
+        let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
+        assert!(sm.is_binder_alive());
+        assert!(sm.ping_binder().is_ok());
+
+        assert!(binder::check_service("this_service_does_not_exist").is_none());
+        assert_eq!(
+            binder::check_interface::<dyn ITest>("this_service_does_not_exist").err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+        assert_eq!(
+            binder::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+
+        // The service manager service isn't an ITest, so this must fail.
+        assert_eq!(
+            binder::check_interface::<dyn ITest>("manager").err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+        assert_eq!(
+            binder::check_interface::<dyn IATest<Tokio>>("manager").err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+    }
+
+    #[tokio::test]
+    async fn check_check_service_async() {
+        let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
+        assert!(sm.is_binder_alive());
+        assert!(sm.ping_binder().is_ok());
+
+        assert!(binder::check_service("this_service_does_not_exist").is_none());
+        assert_eq!(
+            binder_tokio::check_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+        assert_eq!(
+            binder_tokio::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist")
+                .await
+                .err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+
+        // The service manager service isn't an ITest, so this must fail.
+        assert_eq!(
+            binder_tokio::check_interface::<dyn ITest>("manager").await.err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+        assert_eq!(
+            binder_tokio::check_interface::<dyn IATest<Tokio>>("manager").await.err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+    }
+
+    #[test]
     fn check_wait_for_service() {
         let mut sm =
             binder::wait_for_service("manager").expect("Did not get manager binder service");