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