xref: /aosp_15_r20/frameworks/native/libs/binder/rust/tests/integration.rs (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Rust Binder crate integration tests
18 
19 use binder::{declare_binder_enum, declare_binder_interface};
20 use binder::{BinderFeatures, Interface, StatusCode, ThreadState};
21 // Import from internal API for testing only, do not use this module in
22 // production.
23 use binder::binder_impl::{
24     Binder, BorrowedParcel, IBinderInternal, TransactionCode, FIRST_CALL_TRANSACTION,
25 };
26 
27 use std::convert::{TryFrom, TryInto};
28 use std::ffi::CStr;
29 use std::io::Write;
30 use std::sync::Mutex;
31 
32 /// Name of service runner.
33 ///
34 /// Must match the binary name in Android.bp
35 const RUST_SERVICE_BINARY: &str = "rustBinderTestService";
36 
37 /// Binary to run a test service.
38 ///
39 /// This needs to be in a separate process from the tests, so we spawn this
40 /// binary as a child, providing the service name as an argument.
main() -> Result<(), &'static str>41 fn main() -> Result<(), &'static str> {
42     // Ensure that we can handle all transactions on the main thread.
43     binder::ProcessState::set_thread_pool_max_thread_count(0);
44     binder::ProcessState::start_thread_pool();
45 
46     let mut args = std::env::args().skip(1);
47     if args.len() < 1 || args.len() > 2 {
48         print_usage();
49         return Err("");
50     }
51     let service_name = args.next().ok_or_else(|| {
52         print_usage();
53         "Missing SERVICE_NAME argument"
54     })?;
55     let extension_name = args.next();
56 
57     {
58         let mut service = Binder::new(BnTest(Box::new(TestService::new(&service_name))));
59         service.set_requesting_sid(true);
60         if let Some(extension_name) = extension_name {
61             let extension =
62                 BnTest::new_binder(TestService::new(&extension_name), BinderFeatures::default());
63             service.set_extension(&mut extension.as_binder()).expect("Could not add extension");
64         }
65         binder::add_service(&service_name, service.as_binder())
66             .expect("Could not register service");
67     }
68 
69     binder::ProcessState::join_thread_pool();
70     Err("Unexpected exit after join_thread_pool")
71 }
72 
print_usage()73 fn print_usage() {
74     eprintln!("Usage: {} SERVICE_NAME [EXTENSION_NAME]", RUST_SERVICE_BINARY);
75     eprintln!(concat!(
76         "Spawn a Binder test service identified by SERVICE_NAME,",
77         " optionally with an extesion named EXTENSION_NAME",
78     ));
79 }
80 
81 struct TestService {
82     s: String,
83     dump_args: Mutex<Vec<String>>,
84 }
85 
86 impl TestService {
new(s: &str) -> Self87     fn new(s: &str) -> Self {
88         Self { s: s.to_string(), dump_args: Mutex::new(Vec::new()) }
89     }
90 }
91 
92 #[repr(u32)]
93 enum TestTransactionCode {
94     Test = FIRST_CALL_TRANSACTION,
95     GetDumpArgs,
96     GetSelinuxContext,
97     GetIsHandlingTransaction,
98 }
99 
100 impl TryFrom<u32> for TestTransactionCode {
101     type Error = StatusCode;
102 
try_from(c: u32) -> Result<Self, Self::Error>103     fn try_from(c: u32) -> Result<Self, Self::Error> {
104         match c {
105             _ if c == TestTransactionCode::Test as u32 => Ok(TestTransactionCode::Test),
106             _ if c == TestTransactionCode::GetDumpArgs as u32 => {
107                 Ok(TestTransactionCode::GetDumpArgs)
108             }
109             _ if c == TestTransactionCode::GetSelinuxContext as u32 => {
110                 Ok(TestTransactionCode::GetSelinuxContext)
111             }
112             _ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => {
113                 Ok(TestTransactionCode::GetIsHandlingTransaction)
114             }
115             _ => Err(StatusCode::UNKNOWN_TRANSACTION),
116         }
117     }
118 }
119 
120 impl Interface for TestService {
dump(&self, _writer: &mut dyn Write, args: &[&CStr]) -> Result<(), StatusCode>121     fn dump(&self, _writer: &mut dyn Write, args: &[&CStr]) -> Result<(), StatusCode> {
122         let mut dump_args = self.dump_args.lock().unwrap();
123         dump_args.extend(args.iter().map(|s| s.to_str().unwrap().to_owned()));
124         Ok(())
125     }
126 }
127 
128 impl ITest for TestService {
test(&self) -> Result<String, StatusCode>129     fn test(&self) -> Result<String, StatusCode> {
130         Ok(self.s.clone())
131     }
132 
get_dump_args(&self) -> Result<Vec<String>, StatusCode>133     fn get_dump_args(&self) -> Result<Vec<String>, StatusCode> {
134         let args = self.dump_args.lock().unwrap().clone();
135         Ok(args)
136     }
137 
get_selinux_context(&self) -> Result<String, StatusCode>138     fn get_selinux_context(&self) -> Result<String, StatusCode> {
139         let sid =
140             ThreadState::with_calling_sid(|sid| sid.map(|s| s.to_string_lossy().into_owned()));
141         sid.ok_or(StatusCode::UNEXPECTED_NULL)
142     }
143 
get_is_handling_transaction(&self) -> Result<bool, StatusCode>144     fn get_is_handling_transaction(&self) -> Result<bool, StatusCode> {
145         Ok(binder::is_handling_transaction())
146     }
147 }
148 
149 /// Trivial testing binder interface
150 pub trait ITest: Interface {
151     /// Returns a test string
test(&self) -> Result<String, StatusCode>152     fn test(&self) -> Result<String, StatusCode>;
153 
154     /// Return the arguments sent via dump
get_dump_args(&self) -> Result<Vec<String>, StatusCode>155     fn get_dump_args(&self) -> Result<Vec<String>, StatusCode>;
156 
157     /// Returns the caller's SELinux context
get_selinux_context(&self) -> Result<String, StatusCode>158     fn get_selinux_context(&self) -> Result<String, StatusCode>;
159 
160     /// Returns the value of calling `is_handling_transaction`.
get_is_handling_transaction(&self) -> Result<bool, StatusCode>161     fn get_is_handling_transaction(&self) -> Result<bool, StatusCode>;
162 }
163 
164 /// Async trivial testing binder interface
165 pub trait IATest<P>: Interface {
166     /// Returns a test string
test(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>167     fn test(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>;
168 
169     /// Return the arguments sent via dump
get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>>170     fn get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>>;
171 
172     /// Returns the caller's SELinux context
get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>173     fn get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>;
174 
175     /// Returns the value of calling `is_handling_transaction`.
get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>>176     fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>>;
177 }
178 
179 declare_binder_interface! {
180     ITest["android.os.ITest"] {
181         native: BnTest(on_transact),
182         proxy: BpTest {
183             x: i32 = 100
184         },
185         async: IATest(try_into_local_async),
186     }
187 }
188 
on_transact( service: &dyn ITest, code: TransactionCode, _data: &BorrowedParcel<'_>, reply: &mut BorrowedParcel<'_>, ) -> Result<(), StatusCode>189 fn on_transact(
190     service: &dyn ITest,
191     code: TransactionCode,
192     _data: &BorrowedParcel<'_>,
193     reply: &mut BorrowedParcel<'_>,
194 ) -> Result<(), StatusCode> {
195     match code.try_into()? {
196         TestTransactionCode::Test => reply.write(&service.test()?),
197         TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
198         TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
199         TestTransactionCode::GetIsHandlingTransaction => {
200             reply.write(&service.get_is_handling_transaction()?)
201         }
202     }
203 }
204 
205 impl ITest for BpTest {
test(&self) -> Result<String, StatusCode>206     fn test(&self) -> Result<String, StatusCode> {
207         let reply =
208             self.binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(()))?;
209         reply.read()
210     }
211 
get_dump_args(&self) -> Result<Vec<String>, StatusCode>212     fn get_dump_args(&self) -> Result<Vec<String>, StatusCode> {
213         let reply =
214             self.binder
215                 .transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(()))?;
216         reply.read()
217     }
218 
get_selinux_context(&self) -> Result<String, StatusCode>219     fn get_selinux_context(&self) -> Result<String, StatusCode> {
220         let reply = self.binder.transact(
221             TestTransactionCode::GetSelinuxContext as TransactionCode,
222             0,
223             |_| Ok(()),
224         )?;
225         reply.read()
226     }
227 
get_is_handling_transaction(&self) -> Result<bool, StatusCode>228     fn get_is_handling_transaction(&self) -> Result<bool, StatusCode> {
229         let reply = self.binder.transact(
230             TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
231             0,
232             |_| Ok(()),
233         )?;
234         reply.read()
235     }
236 }
237 
238 impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
test(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>239     fn test(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>> {
240         let binder = self.binder.clone();
241         P::spawn(
242             move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())),
243             |reply| async move { reply?.read() },
244         )
245     }
246 
get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>>247     fn get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>> {
248         let binder = self.binder.clone();
249         P::spawn(
250             move || {
251                 binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(()))
252             },
253             |reply| async move { reply?.read() },
254         )
255     }
256 
get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>257     fn get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>> {
258         let binder = self.binder.clone();
259         P::spawn(
260             move || {
261                 binder.transact(
262                     TestTransactionCode::GetSelinuxContext as TransactionCode,
263                     0,
264                     |_| Ok(()),
265                 )
266             },
267             |reply| async move { reply?.read() },
268         )
269     }
270 
get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>>271     fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>> {
272         let binder = self.binder.clone();
273         P::spawn(
274             move || {
275                 binder.transact(
276                     TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
277                     0,
278                     |_| Ok(()),
279                 )
280             },
281             |reply| async move { reply?.read() },
282         )
283     }
284 }
285 
286 impl ITest for Binder<BnTest> {
test(&self) -> Result<String, StatusCode>287     fn test(&self) -> Result<String, StatusCode> {
288         self.0.test()
289     }
290 
get_dump_args(&self) -> Result<Vec<String>, StatusCode>291     fn get_dump_args(&self) -> Result<Vec<String>, StatusCode> {
292         self.0.get_dump_args()
293     }
294 
get_selinux_context(&self) -> Result<String, StatusCode>295     fn get_selinux_context(&self) -> Result<String, StatusCode> {
296         self.0.get_selinux_context()
297     }
298 
get_is_handling_transaction(&self) -> Result<bool, StatusCode>299     fn get_is_handling_transaction(&self) -> Result<bool, StatusCode> {
300         self.0.get_is_handling_transaction()
301     }
302 }
303 
304 impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
test(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>305     fn test(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>> {
306         let res = self.0.test();
307         Box::pin(async move { res })
308     }
309 
get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>>310     fn get_dump_args(&self) -> binder::BoxFuture<'static, Result<Vec<String>, StatusCode>> {
311         let res = self.0.get_dump_args();
312         Box::pin(async move { res })
313     }
314 
get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>>315     fn get_selinux_context(&self) -> binder::BoxFuture<'static, Result<String, StatusCode>> {
316         let res = self.0.get_selinux_context();
317         Box::pin(async move { res })
318     }
319 
get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>>320     fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, Result<bool, StatusCode>> {
321         let res = self.0.get_is_handling_transaction();
322         Box::pin(async move { res })
323     }
324 }
325 
326 impl BnTest {
try_into_local_async<P: binder::BinderAsyncPool + 'static>( me: Binder<BnTest>, ) -> Option<binder::Strong<dyn IATest<P>>>327     fn try_into_local_async<P: binder::BinderAsyncPool + 'static>(
328         me: Binder<BnTest>,
329     ) -> Option<binder::Strong<dyn IATest<P>>> {
330         Some(binder::Strong::new(Box::new(me) as _))
331     }
332 }
333 
334 /// Trivial testing binder interface
335 pub trait ITestSameDescriptor: Interface {}
336 
337 declare_binder_interface! {
338     ITestSameDescriptor["android.os.ITest"] {
339         native: BnTestSameDescriptor(on_transact_same_descriptor),
340         proxy: BpTestSameDescriptor,
341     }
342 }
343 
on_transact_same_descriptor( _service: &dyn ITestSameDescriptor, _code: TransactionCode, _data: &BorrowedParcel<'_>, _reply: &mut BorrowedParcel<'_>, ) -> Result<(), StatusCode>344 fn on_transact_same_descriptor(
345     _service: &dyn ITestSameDescriptor,
346     _code: TransactionCode,
347     _data: &BorrowedParcel<'_>,
348     _reply: &mut BorrowedParcel<'_>,
349 ) -> Result<(), StatusCode> {
350     Ok(())
351 }
352 
353 impl ITestSameDescriptor for BpTestSameDescriptor {}
354 
355 impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
356 
357 declare_binder_enum! {
358     TestEnum : [i32; 3] {
359         FOO = 1,
360         BAR = 2,
361         BAZ = 3,
362     }
363 }
364 
365 declare_binder_enum! {
366     #[deprecated(since = "1.0.0")]
367     TestDeprecatedEnum : [i32; 3] {
368         FOO = 1,
369         BAR = 2,
370         BAZ = 3,
371     }
372 }
373 
374 #[cfg(test)]
375 mod tests {
376     use selinux_bindgen as selinux_sys;
377     use std::ffi::CStr;
378     use std::fs::File;
379     use std::process::{Child, Command};
380     use std::ptr;
381     use std::sync::atomic::{AtomicBool, Ordering};
382     use std::sync::Arc;
383     use std::thread;
384     use std::time::Duration;
385 
386     use binder::{
387         Accessor, AccessorProvider, BinderFeatures, DeathRecipient, FromIBinder, IBinder,
388         Interface, SpIBinder, StatusCode, Strong,
389     };
390     // Import from impl API for testing only, should not be necessary as long as
391     // you are using AIDL.
392     use binder::binder_impl::{Binder, IBinderInternal, TransactionCode};
393 
394     use binder_tokio::Tokio;
395 
396     use super::{BnTest, IATest, ITest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
397 
398     pub struct ScopedServiceProcess(Child);
399 
400     impl ScopedServiceProcess {
new(identifier: &str) -> Self401         pub fn new(identifier: &str) -> Self {
402             Self::new_internal(identifier, None)
403         }
404 
new_with_extension(identifier: &str, extension: &str) -> Self405         pub fn new_with_extension(identifier: &str, extension: &str) -> Self {
406             Self::new_internal(identifier, Some(extension))
407         }
408 
new_internal(identifier: &str, extension: Option<&str>) -> Self409         fn new_internal(identifier: &str, extension: Option<&str>) -> Self {
410             let mut binary_path =
411                 std::env::current_exe().expect("Could not retrieve current executable path");
412             binary_path.pop();
413             binary_path.push(RUST_SERVICE_BINARY);
414             let mut command = Command::new(&binary_path);
415             command.arg(identifier);
416             if let Some(ext) = extension {
417                 command.arg(ext);
418             }
419             let child = command.spawn().expect("Could not start service");
420             Self(child)
421         }
422     }
423 
424     impl Drop for ScopedServiceProcess {
drop(&mut self)425         fn drop(&mut self) {
426             self.0.kill().expect("Could not kill child process");
427             self.0.wait().expect("Could not wait for child process to die");
428         }
429     }
430 
431     #[test]
check_get_service()432     fn check_get_service() {
433         let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
434         assert!(sm.is_binder_alive());
435         assert!(sm.ping_binder().is_ok());
436 
437         assert!(binder::get_service("this_service_does_not_exist").is_none());
438         assert_eq!(
439             binder::get_interface::<dyn ITest>("this_service_does_not_exist").err(),
440             Some(StatusCode::NAME_NOT_FOUND)
441         );
442         assert_eq!(
443             binder::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
444             Some(StatusCode::NAME_NOT_FOUND)
445         );
446 
447         // The service manager service isn't an ITest, so this must fail.
448         assert_eq!(binder::get_interface::<dyn ITest>("manager").err(), Some(StatusCode::BAD_TYPE));
449         assert_eq!(
450             binder::get_interface::<dyn IATest<Tokio>>("manager").err(),
451             Some(StatusCode::BAD_TYPE)
452         );
453     }
454 
455     #[tokio::test]
check_get_service_async()456     async fn check_get_service_async() {
457         let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
458         assert!(sm.is_binder_alive());
459         assert!(sm.ping_binder().is_ok());
460 
461         assert!(binder::get_service("this_service_does_not_exist").is_none());
462         assert_eq!(
463             binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
464             Some(StatusCode::NAME_NOT_FOUND)
465         );
466         assert_eq!(
467             binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist")
468                 .await
469                 .err(),
470             Some(StatusCode::NAME_NOT_FOUND)
471         );
472 
473         // The service manager service isn't an ITest, so this must fail.
474         assert_eq!(
475             binder_tokio::get_interface::<dyn ITest>("manager").await.err(),
476             Some(StatusCode::BAD_TYPE)
477         );
478         assert_eq!(
479             binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(),
480             Some(StatusCode::BAD_TYPE)
481         );
482     }
483 
484     #[test]
check_check_service()485     fn check_check_service() {
486         let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
487         assert!(sm.is_binder_alive());
488         assert!(sm.ping_binder().is_ok());
489 
490         assert!(binder::check_service("this_service_does_not_exist").is_none());
491         assert_eq!(
492             binder::check_interface::<dyn ITest>("this_service_does_not_exist").err(),
493             Some(StatusCode::NAME_NOT_FOUND)
494         );
495         assert_eq!(
496             binder::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
497             Some(StatusCode::NAME_NOT_FOUND)
498         );
499 
500         // The service manager service isn't an ITest, so this must fail.
501         assert_eq!(
502             binder::check_interface::<dyn ITest>("manager").err(),
503             Some(StatusCode::BAD_TYPE)
504         );
505         assert_eq!(
506             binder::check_interface::<dyn IATest<Tokio>>("manager").err(),
507             Some(StatusCode::BAD_TYPE)
508         );
509     }
510 
511     #[tokio::test]
check_check_service_async()512     async fn check_check_service_async() {
513         let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
514         assert!(sm.is_binder_alive());
515         assert!(sm.ping_binder().is_ok());
516 
517         assert!(binder::check_service("this_service_does_not_exist").is_none());
518         assert_eq!(
519             binder_tokio::check_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
520             Some(StatusCode::NAME_NOT_FOUND)
521         );
522         assert_eq!(
523             binder_tokio::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist")
524                 .await
525                 .err(),
526             Some(StatusCode::NAME_NOT_FOUND)
527         );
528 
529         // The service manager service isn't an ITest, so this must fail.
530         assert_eq!(
531             binder_tokio::check_interface::<dyn ITest>("manager").await.err(),
532             Some(StatusCode::BAD_TYPE)
533         );
534         assert_eq!(
535             binder_tokio::check_interface::<dyn IATest<Tokio>>("manager").await.err(),
536             Some(StatusCode::BAD_TYPE)
537         );
538     }
539 
540     #[test]
check_wait_for_service()541     fn check_wait_for_service() {
542         let mut sm =
543             binder::wait_for_service("manager").expect("Did not get manager binder service");
544         assert!(sm.is_binder_alive());
545         assert!(sm.ping_binder().is_ok());
546 
547         // The service manager service isn't an ITest, so this must fail.
548         assert_eq!(
549             binder::wait_for_interface::<dyn ITest>("manager").err(),
550             Some(StatusCode::BAD_TYPE)
551         );
552         assert_eq!(
553             binder::wait_for_interface::<dyn IATest<Tokio>>("manager").err(),
554             Some(StatusCode::BAD_TYPE)
555         );
556     }
557 
558     #[test]
get_declared_instances()559     fn get_declared_instances() {
560         // At the time of writing this test, there is no good VINTF interface
561         // guaranteed to be on all devices. Cuttlefish has light, so this will
562         // generally test things.
563         let has_lights = binder::is_declared("android.hardware.light.ILights/default")
564             .expect("Could not check for declared interface");
565 
566         let instances = binder::get_declared_instances("android.hardware.light.ILights")
567             .expect("Could not get declared instances");
568 
569         let expected_defaults = usize::from(has_lights);
570         assert_eq!(expected_defaults, instances.iter().filter(|i| i.as_str() == "default").count());
571     }
572 
573     #[test]
trivial_client()574     fn trivial_client() {
575         let service_name = "trivial_client_test";
576         let _process = ScopedServiceProcess::new(service_name);
577         let test_client: Strong<dyn ITest> =
578             binder::get_interface(service_name).expect("Did not get manager binder service");
579         assert_eq!(test_client.test().unwrap(), "trivial_client_test");
580     }
581 
582     #[tokio::test]
trivial_client_async()583     async fn trivial_client_async() {
584         let service_name = "trivial_client_test";
585         let _process = ScopedServiceProcess::new(service_name);
586         let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
587             .await
588             .expect("Did not get manager binder service");
589         assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
590     }
591 
592     #[test]
wait_for_trivial_client()593     fn wait_for_trivial_client() {
594         let service_name = "wait_for_trivial_client_test";
595         let _process = ScopedServiceProcess::new(service_name);
596         let test_client: Strong<dyn ITest> =
597             binder::wait_for_interface(service_name).expect("Did not get manager binder service");
598         assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
599     }
600 
601     #[tokio::test]
wait_for_trivial_client_async()602     async fn wait_for_trivial_client_async() {
603         let service_name = "wait_for_trivial_client_test";
604         let _process = ScopedServiceProcess::new(service_name);
605         let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::wait_for_interface(service_name)
606             .await
607             .expect("Did not get manager binder service");
608         assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
609     }
610 
get_expected_selinux_context() -> &'static str611     fn get_expected_selinux_context() -> &'static str {
612         // SAFETY: The pointer we pass to `getcon` is valid because it comes from a reference, and
613         // `getcon` doesn't retain it after it returns. If `getcon` succeeds then `out_ptr` will
614         // point to a valid C string, otherwise it will remain null. We check for null, so the
615         // pointer we pass to `CStr::from_ptr` must be a valid pointer to a C string. There is a
616         // memory leak as we don't call `freecon`, but that's fine because this is just a test.
617         unsafe {
618             let mut out_ptr = ptr::null_mut();
619             assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
620             assert!(!out_ptr.is_null());
621             CStr::from_ptr(out_ptr).to_str().expect("context was invalid UTF-8")
622         }
623     }
624 
625     #[test]
get_selinux_context()626     fn get_selinux_context() {
627         let service_name = "get_selinux_context";
628         let _process = ScopedServiceProcess::new(service_name);
629         let test_client: Strong<dyn ITest> =
630             binder::get_interface(service_name).expect("Did not get manager binder service");
631         assert_eq!(test_client.get_selinux_context().unwrap(), get_expected_selinux_context());
632     }
633 
634     #[tokio::test]
get_selinux_context_async()635     async fn get_selinux_context_async() {
636         let service_name = "get_selinux_context_async";
637         let _process = ScopedServiceProcess::new(service_name);
638         let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
639             .await
640             .expect("Did not get manager binder service");
641         assert_eq!(
642             test_client.get_selinux_context().await.unwrap(),
643             get_expected_selinux_context()
644         );
645     }
646 
647     #[tokio::test]
get_selinux_context_sync_to_async()648     async fn get_selinux_context_sync_to_async() {
649         let service_name = "get_selinux_context";
650         let _process = ScopedServiceProcess::new(service_name);
651         let test_client: Strong<dyn ITest> =
652             binder::get_interface(service_name).expect("Did not get manager binder service");
653         let test_client = test_client.into_async::<Tokio>();
654         assert_eq!(
655             test_client.get_selinux_context().await.unwrap(),
656             get_expected_selinux_context()
657         );
658     }
659 
660     #[tokio::test]
get_selinux_context_async_to_sync()661     async fn get_selinux_context_async_to_sync() {
662         let service_name = "get_selinux_context";
663         let _process = ScopedServiceProcess::new(service_name);
664         let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
665             .await
666             .expect("Did not get manager binder service");
667         let test_client = test_client.into_sync();
668         assert_eq!(test_client.get_selinux_context().unwrap(), get_expected_selinux_context());
669     }
670 
671     struct Bools {
672         binder_died: Arc<AtomicBool>,
673         binder_dealloc: Arc<AtomicBool>,
674     }
675 
676     impl Bools {
is_dead(&self) -> bool677         fn is_dead(&self) -> bool {
678             self.binder_died.load(Ordering::Relaxed)
679         }
assert_died(&self)680         fn assert_died(&self) {
681             assert!(self.is_dead(), "Did not receive death notification");
682         }
assert_dropped(&self)683         fn assert_dropped(&self) {
684             assert!(
685                 self.binder_dealloc.load(Ordering::Relaxed),
686                 "Did not dealloc death notification"
687             );
688         }
assert_not_dropped(&self)689         fn assert_not_dropped(&self) {
690             assert!(
691                 !self.binder_dealloc.load(Ordering::Relaxed),
692                 "Dealloc death notification too early"
693             );
694         }
695     }
696 
register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient)697     fn register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient) {
698         let binder_died = Arc::new(AtomicBool::new(false));
699         let binder_dealloc = Arc::new(AtomicBool::new(false));
700 
701         struct SetOnDrop {
702             binder_dealloc: Arc<AtomicBool>,
703         }
704         impl Drop for SetOnDrop {
705             fn drop(&mut self) {
706                 self.binder_dealloc.store(true, Ordering::Relaxed);
707             }
708         }
709 
710         let mut death_recipient = {
711             let flag = binder_died.clone();
712             let set_on_drop = SetOnDrop { binder_dealloc: binder_dealloc.clone() };
713             DeathRecipient::new(move || {
714                 flag.store(true, Ordering::Relaxed);
715                 // Force the closure to take ownership of set_on_drop. When the closure is
716                 // dropped, the destructor of `set_on_drop` will run.
717                 let _ = &set_on_drop;
718             })
719         };
720 
721         binder.link_to_death(&mut death_recipient).expect("link_to_death failed");
722 
723         let bools = Bools { binder_died, binder_dealloc };
724 
725         (bools, death_recipient)
726     }
727 
728     /// Killing a remote service should unregister the service and trigger
729     /// death notifications.
730     #[test]
test_death_notifications()731     fn test_death_notifications() {
732         binder::ProcessState::start_thread_pool();
733 
734         let service_name = "test_death_notifications";
735         let service_process = ScopedServiceProcess::new(service_name);
736         let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
737 
738         let (bools, recipient) = register_death_notification(&mut remote);
739 
740         drop(service_process);
741         remote.ping_binder().expect_err("Service should have died already");
742 
743         // Pause to ensure any death notifications get delivered
744         thread::sleep(Duration::from_secs(1));
745 
746         bools.assert_died();
747         bools.assert_not_dropped();
748 
749         drop(recipient);
750 
751         bools.assert_dropped();
752     }
753 
754     /// Test unregistering death notifications.
755     #[test]
test_unregister_death_notifications()756     fn test_unregister_death_notifications() {
757         binder::ProcessState::start_thread_pool();
758 
759         let service_name = "test_unregister_death_notifications";
760         let service_process = ScopedServiceProcess::new(service_name);
761         let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
762 
763         let (bools, mut recipient) = register_death_notification(&mut remote);
764 
765         remote.unlink_to_death(&mut recipient).expect("Could not unlink death notifications");
766 
767         drop(service_process);
768         remote.ping_binder().expect_err("Service should have died already");
769 
770         // Pause to ensure any death notifications get delivered
771         thread::sleep(Duration::from_secs(1));
772 
773         assert!(!bools.is_dead(), "Received unexpected death notification after unlinking",);
774 
775         bools.assert_not_dropped();
776         drop(recipient);
777         bools.assert_dropped();
778     }
779 
780     /// Dropping a remote handle should unregister any death notifications.
781     #[test]
test_death_notification_registration_lifetime()782     fn test_death_notification_registration_lifetime() {
783         binder::ProcessState::start_thread_pool();
784 
785         let service_name = "test_death_notification_registration_lifetime";
786         let service_process = ScopedServiceProcess::new(service_name);
787         let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
788 
789         let (bools, recipient) = register_death_notification(&mut remote);
790 
791         // This should automatically unregister our death notification.
792         drop(remote);
793 
794         drop(service_process);
795 
796         // Pause to ensure any death notifications get delivered
797         thread::sleep(Duration::from_secs(1));
798 
799         // We dropped the remote handle, so we should not receive the death
800         // notification when the remote process dies here.
801         assert!(
802             !bools.is_dead(),
803             "Received unexpected death notification after dropping remote handle"
804         );
805 
806         bools.assert_not_dropped();
807         drop(recipient);
808         bools.assert_dropped();
809     }
810 
811     /// Test IBinder interface methods not exercised elsewhere.
812     #[test]
test_misc_ibinder()813     fn test_misc_ibinder() {
814         let service_name = "rust_test_ibinder";
815 
816         {
817             let _process = ScopedServiceProcess::new(service_name);
818 
819             let test_client: Strong<dyn ITest> =
820                 binder::get_interface(service_name).expect("Did not get test binder service");
821             let mut remote = test_client.as_binder();
822             assert!(remote.is_binder_alive());
823             remote.ping_binder().expect("Could not ping remote service");
824 
825             let dump_args = ["dump", "args", "for", "testing"];
826 
827             let null_out = File::open("/dev/null").expect("Could not open /dev/null");
828             remote.dump(&null_out, &dump_args).expect("Could not dump remote service");
829 
830             let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
831             assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
832         }
833 
834         // get/set_extensions is tested in test_extensions()
835 
836         // transact is tested everywhere else, and we can't make raw
837         // transactions outside the [FIRST_CALL_TRANSACTION,
838         // LAST_CALL_TRANSACTION] range from the NDK anyway.
839 
840         // link_to_death is tested in test_*_death_notification* tests.
841     }
842 
843     #[test]
test_extensions()844     fn test_extensions() {
845         let service_name = "rust_test_extensions";
846         let extension_name = "rust_test_extensions_ext";
847 
848         {
849             let _process = ScopedServiceProcess::new(service_name);
850 
851             let mut remote = binder::get_service(service_name);
852             assert!(remote.is_binder_alive());
853 
854             let extension = remote.get_extension().expect("Could not check for an extension");
855             assert!(extension.is_none());
856         }
857 
858         {
859             let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
860 
861             let mut remote = binder::get_service(service_name);
862             assert!(remote.is_binder_alive());
863 
864             let maybe_extension = remote.get_extension().expect("Could not check for an extension");
865 
866             let extension = maybe_extension.expect("Remote binder did not have an extension");
867 
868             let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
869                 .expect("Extension could not be converted to the expected interface");
870 
871             assert_eq!(extension.test().unwrap(), extension_name);
872         }
873     }
874 
875     /// Test re-associating a local binder object with a different class.
876     ///
877     /// This is needed because different binder service (e.g. NDK vs Rust)
878     /// implementations are incompatible and must not be interchanged. A local
879     /// service with the same descriptor string but a different class pointer
880     /// may have been created by an NDK service and is therefore incompatible
881     /// with the Rust service implementation. It must be treated as remote and
882     /// all API calls parceled and sent through transactions.
883     ///
884     /// Further tests of this behavior with the C NDK and Rust API are in
885     /// rust_ndk_interop.rs
886     #[test]
associate_existing_class()887     fn associate_existing_class() {
888         let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
889 
890         // This should succeed although we will have to treat the service as
891         // remote.
892         let _interface: Strong<dyn ITestSameDescriptor> =
893             FromIBinder::try_from(service.as_binder())
894                 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
895     }
896 
897     /// Test that we can round-trip a rust service through a generic IBinder
898     #[test]
reassociate_rust_binder()899     fn reassociate_rust_binder() {
900         let service_name = "testing_service";
901         let service_ibinder =
902             BnTest::new_binder(TestService::new(service_name), BinderFeatures::default())
903                 .as_binder();
904 
905         let service: Strong<dyn ITest> =
906             service_ibinder.into_interface().expect("Could not reassociate the generic ibinder");
907 
908         assert_eq!(service.test().unwrap(), service_name);
909     }
910 
911     struct ToBeDeleted {
912         deleted: Arc<AtomicBool>,
913     }
914 
915     impl Drop for ToBeDeleted {
drop(&mut self)916         fn drop(&mut self) {
917             assert!(!self.deleted.load(Ordering::Relaxed));
918             self.deleted.store(true, Ordering::Relaxed);
919         }
920     }
921 
922     #[test]
test_accessor_callback_destruction()923     fn test_accessor_callback_destruction() {
924         let deleted: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
925         {
926             let accessor: Accessor;
927             {
928                 let helper = ToBeDeleted { deleted: deleted.clone() };
929                 let get_connection_info = move |_instance: &str| {
930                     // Capture this object so we can see it get destructed
931                     // after the parent scope
932                     let _ = &helper;
933                     None
934                 };
935                 accessor = Accessor::new("foo.service", get_connection_info);
936             }
937 
938             match accessor.as_binder() {
939                 Some(_) => {
940                     assert!(!deleted.load(Ordering::Relaxed));
941                 }
942                 None => panic!("failed to get that accessor binder"),
943             }
944         }
945         assert!(deleted.load(Ordering::Relaxed));
946     }
947 
948     #[test]
test_accessor_delegator_new_each_time()949     fn test_accessor_delegator_new_each_time() {
950         let get_connection_info = move |_instance: &str| None;
951         let accessor = Accessor::new("foo.service", get_connection_info);
952         let delegator_binder =
953             binder::delegate_accessor("foo.service", accessor.as_binder().unwrap());
954         let delegator_binder2 =
955             binder::delegate_accessor("foo.service", accessor.as_binder().unwrap());
956 
957         // The delegate_accessor creates new delegators each time
958         assert!(delegator_binder != delegator_binder2);
959     }
960 
961     #[test]
test_accessor_delegate_the_delegator()962     fn test_accessor_delegate_the_delegator() {
963         let get_connection_info = move |_instance: &str| None;
964         let accessor = Accessor::new("foo.service", get_connection_info);
965         let delegator_binder =
966             binder::delegate_accessor("foo.service", accessor.as_binder().unwrap());
967         let delegator_binder2 =
968             binder::delegate_accessor("foo.service", delegator_binder.clone().unwrap());
969 
970         assert!(delegator_binder.clone() == delegator_binder);
971         // The delegate_accessor creates new delegators each time. Even when they are delegators
972         // of delegators.
973         assert!(delegator_binder != delegator_binder2);
974     }
975 
976     #[test]
test_accessor_delegator_wrong_name()977     fn test_accessor_delegator_wrong_name() {
978         let get_connection_info = move |_instance: &str| None;
979         let accessor = Accessor::new("foo.service", get_connection_info);
980         let delegator_binder =
981             binder::delegate_accessor("NOT.foo.service", accessor.as_binder().unwrap());
982         assert_eq!(delegator_binder, Err(StatusCode::NAME_NOT_FOUND));
983     }
984 
985     #[test]
test_accessor_provider_simple()986     fn test_accessor_provider_simple() {
987         let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
988         let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
989         assert!(accessor.is_some());
990     }
991 
992     #[test]
test_accessor_provider_no_instance()993     fn test_accessor_provider_no_instance() {
994         let instances: Vec<String> = vec![];
995         let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
996         assert!(accessor.is_none());
997     }
998 
999     #[test]
test_accessor_provider_double_register()1000     fn test_accessor_provider_double_register() {
1001         let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
1002         let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
1003         assert!(accessor.is_some());
1004         let accessor2 = AccessorProvider::new(&instances, move |_inst: &str| None);
1005         assert!(accessor2.is_none());
1006     }
1007 
1008     #[test]
test_accessor_provider_register_drop_register()1009     fn test_accessor_provider_register_drop_register() {
1010         let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
1011         {
1012             let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
1013             assert!(accessor.is_some());
1014             // accessor drops and unregisters the provider
1015         }
1016         {
1017             let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
1018             assert!(accessor.is_some());
1019         }
1020     }
1021 
1022     #[test]
test_accessor_provider_callback_destruction()1023     fn test_accessor_provider_callback_destruction() {
1024         let deleted: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
1025         let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
1026         {
1027             let accessor: Option<AccessorProvider>;
1028             {
1029                 let helper = ToBeDeleted { deleted: deleted.clone() };
1030                 accessor = AccessorProvider::new(&instances, move |_inst: &str| {
1031                     let _ = &helper;
1032                     None
1033                 });
1034             }
1035             assert!(accessor.is_some());
1036             assert!(!deleted.load(Ordering::Relaxed));
1037         }
1038         assert!(deleted.load(Ordering::Relaxed));
1039     }
1040 
1041     #[test]
test_accessor_from_accessor_binder()1042     fn test_accessor_from_accessor_binder() {
1043         let get_connection_info = move |_instance: &str| None;
1044         let accessor = Accessor::new("foo.service", get_connection_info);
1045         let accessor2 =
1046             Accessor::from_binder("foo.service", accessor.as_binder().unwrap()).unwrap();
1047         assert_eq!(accessor.as_binder(), accessor2.as_binder());
1048     }
1049 
1050     #[test]
test_accessor_from_non_accessor_binder()1051     fn test_accessor_from_non_accessor_binder() {
1052         let service_name = "rust_test_ibinder";
1053         let _process = ScopedServiceProcess::new(service_name);
1054         let binder = binder::get_service(service_name).unwrap();
1055         assert!(binder.is_binder_alive());
1056 
1057         let accessor = Accessor::from_binder("rust_test_ibinder", binder);
1058         assert!(accessor.is_none());
1059     }
1060 
1061     #[test]
test_accessor_from_wrong_accessor_binder()1062     fn test_accessor_from_wrong_accessor_binder() {
1063         let get_connection_info = move |_instance: &str| None;
1064         let accessor = Accessor::new("foo.service", get_connection_info);
1065         let accessor2 = Accessor::from_binder("NOT.foo.service", accessor.as_binder().unwrap());
1066         assert!(accessor2.is_none());
1067     }
1068 
1069     #[tokio::test]
reassociate_rust_binder_async()1070     async fn reassociate_rust_binder_async() {
1071         let service_name = "testing_service";
1072         let service_ibinder =
1073             BnTest::new_binder(TestService::new(service_name), BinderFeatures::default())
1074                 .as_binder();
1075 
1076         let service: Strong<dyn IATest<Tokio>> =
1077             service_ibinder.into_interface().expect("Could not reassociate the generic ibinder");
1078 
1079         assert_eq!(service.test().await.unwrap(), service_name);
1080     }
1081 
1082     #[test]
weak_binder_upgrade()1083     fn weak_binder_upgrade() {
1084         let service_name = "testing_service";
1085         let service = BnTest::new_binder(TestService::new(service_name), BinderFeatures::default());
1086 
1087         let weak = Strong::downgrade(&service);
1088 
1089         let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
1090 
1091         assert_eq!(service, upgraded);
1092     }
1093 
1094     #[test]
weak_binder_upgrade_dead()1095     fn weak_binder_upgrade_dead() {
1096         let service_name = "testing_service";
1097         let weak = {
1098             let service =
1099                 BnTest::new_binder(TestService::new(service_name), BinderFeatures::default());
1100 
1101             Strong::downgrade(&service)
1102         };
1103 
1104         assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
1105     }
1106 
1107     #[test]
weak_binder_clone()1108     fn weak_binder_clone() {
1109         let service_name = "testing_service";
1110         let service = BnTest::new_binder(TestService::new(service_name), BinderFeatures::default());
1111 
1112         let weak = Strong::downgrade(&service);
1113         let cloned = weak.clone();
1114         assert_eq!(weak, cloned);
1115 
1116         let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
1117         let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
1118 
1119         assert_eq!(service, upgraded);
1120         assert_eq!(service, clone_upgraded);
1121     }
1122 
1123     #[test]
1124     #[allow(clippy::eq_op)]
binder_ord()1125     fn binder_ord() {
1126         let service1 =
1127             BnTest::new_binder(TestService::new("testing_service1"), BinderFeatures::default());
1128         let service2 =
1129             BnTest::new_binder(TestService::new("testing_service2"), BinderFeatures::default());
1130 
1131         assert!((service1 >= service1));
1132         assert!((service1 <= service1));
1133         assert_eq!(service1 < service2, (service2 >= service1));
1134     }
1135 
1136     #[test]
binder_parcel_mixup()1137     fn binder_parcel_mixup() {
1138         let service1 =
1139             BnTest::new_binder(TestService::new("testing_service1"), BinderFeatures::default());
1140         let service2 =
1141             BnTest::new_binder(TestService::new("testing_service2"), BinderFeatures::default());
1142 
1143         let service1 = service1.as_binder();
1144         let service2 = service2.as_binder();
1145 
1146         let parcel = service1.prepare_transact().unwrap();
1147         let res = service2.submit_transact(
1148             super::TestTransactionCode::Test as TransactionCode,
1149             parcel,
1150             0,
1151         );
1152 
1153         match res {
1154             Ok(_) => panic!("submit_transact should fail"),
1155             Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
1156         }
1157     }
1158 
1159     #[test]
get_is_handling_transaction()1160     fn get_is_handling_transaction() {
1161         let service_name = "get_is_handling_transaction";
1162         let _process = ScopedServiceProcess::new(service_name);
1163         let test_client: Strong<dyn ITest> =
1164             binder::get_interface(service_name).expect("Did not get manager binder service");
1165         // Should be true externally.
1166         assert!(test_client.get_is_handling_transaction().unwrap());
1167 
1168         // Should be false locally.
1169         assert!(!binder::is_handling_transaction());
1170 
1171         // Should also be false in spawned thread.
1172         std::thread::spawn(|| {
1173             assert!(!binder::is_handling_transaction());
1174         })
1175         .join()
1176         .unwrap();
1177     }
1178 
1179     #[tokio::test]
get_is_handling_transaction_async()1180     async fn get_is_handling_transaction_async() {
1181         let service_name = "get_is_handling_transaction_async";
1182         let _process = ScopedServiceProcess::new(service_name);
1183         let test_client: Strong<dyn IATest<Tokio>> = binder_tokio::get_interface(service_name)
1184             .await
1185             .expect("Did not get manager binder service");
1186         // Should be true externally.
1187         assert!(test_client.get_is_handling_transaction().await.unwrap());
1188 
1189         // Should be false locally.
1190         assert!(!binder::is_handling_transaction());
1191 
1192         // Should also be false in spawned task.
1193         tokio::spawn(async {
1194             assert!(!binder::is_handling_transaction());
1195         })
1196         .await
1197         .unwrap();
1198 
1199         // And in spawn_blocking task.
1200         tokio::task::spawn_blocking(|| {
1201             assert!(!binder::is_handling_transaction());
1202         })
1203         .await
1204         .unwrap();
1205     }
1206 }
1207