blob: ebfe879f4935d96c88251ee33ed4fede23418023 [file] [log] [blame]
Stephen Crane2a3c2502020-06-16 17:48:35 -07001/*
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
19use binder::declare_binder_interface;
Alice Ryhl05f5a2c2021-09-15 12:56:10 +000020use binder::parcel::{Parcel, OwnedParcel};
Andrew Walbran12400d82021-03-04 17:04:34 +000021use binder::{
Andrew Walbran88eca4f2021-04-13 14:26:01 +000022 Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
Andrew Walbran12400d82021-03-04 17:04:34 +000023 FIRST_CALL_TRANSACTION,
24};
Janis Danisevskis798a09a2020-08-18 08:35:38 -070025use std::convert::{TryFrom, TryInto};
Stephen Crane2a3297f2021-06-11 16:48:10 -070026use std::ffi::CStr;
27use std::fs::File;
28use std::sync::Mutex;
Stephen Crane2a3c2502020-06-16 17:48:35 -070029
30/// Name of service runner.
31///
32/// Must match the binary name in Android.bp
33const RUST_SERVICE_BINARY: &str = "rustBinderTestService";
34
35/// Binary to run a test service.
36///
37/// This needs to be in a separate process from the tests, so we spawn this
38/// binary as a child, providing the service name as an argument.
39fn main() -> Result<(), &'static str> {
40 // Ensure that we can handle all transactions on the main thread.
41 binder::ProcessState::set_thread_pool_max_thread_count(0);
42 binder::ProcessState::start_thread_pool();
43
44 let mut args = std::env::args().skip(1);
45 if args.len() < 1 || args.len() > 2 {
46 print_usage();
47 return Err("");
48 }
49 let service_name = args.next().ok_or_else(|| {
50 print_usage();
51 "Missing SERVICE_NAME argument"
52 })?;
53 let extension_name = args.next();
54
55 {
Stephen Crane2a3297f2021-06-11 16:48:10 -070056 let mut service = Binder::new(BnTest(Box::new(TestService::new(&service_name))));
Janis Danisevskis798a09a2020-08-18 08:35:38 -070057 service.set_requesting_sid(true);
Stephen Crane2a3c2502020-06-16 17:48:35 -070058 if let Some(extension_name) = extension_name {
Andrew Walbran88eca4f2021-04-13 14:26:01 +000059 let extension =
Stephen Crane2a3297f2021-06-11 16:48:10 -070060 BnTest::new_binder(TestService::new(&extension_name), BinderFeatures::default());
Stephen Crane2a3c2502020-06-16 17:48:35 -070061 service
62 .set_extension(&mut extension.as_binder())
63 .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
73fn print_usage() {
74 eprintln!(
75 "Usage: {} SERVICE_NAME [EXTENSION_NAME]",
76 RUST_SERVICE_BINARY
77 );
78 eprintln!(concat!(
79 "Spawn a Binder test service identified by SERVICE_NAME,",
80 " optionally with an extesion named EXTENSION_NAME",
81 ));
82}
83
Stephen Crane2a3c2502020-06-16 17:48:35 -070084struct TestService {
85 s: String,
Stephen Crane2a3297f2021-06-11 16:48:10 -070086 dump_args: Mutex<Vec<String>>,
87}
88
89impl TestService {
90 fn new(s: &str) -> Self {
91 Self {
92 s: s.to_string(),
93 dump_args: Mutex::new(Vec::new()),
94 }
95 }
Stephen Crane2a3c2502020-06-16 17:48:35 -070096}
97
Janis Danisevskis798a09a2020-08-18 08:35:38 -070098#[repr(u32)]
99enum TestTransactionCode {
Andrew Walbran12400d82021-03-04 17:04:34 +0000100 Test = FIRST_CALL_TRANSACTION,
Stephen Crane2a3297f2021-06-11 16:48:10 -0700101 GetDumpArgs,
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700102 GetSelinuxContext,
103}
104
105impl TryFrom<u32> for TestTransactionCode {
106 type Error = StatusCode;
107
108 fn try_from(c: u32) -> Result<Self, Self::Error> {
109 match c {
110 _ if c == TestTransactionCode::Test as u32 => Ok(TestTransactionCode::Test),
Stephen Crane2a3297f2021-06-11 16:48:10 -0700111 _ if c == TestTransactionCode::GetDumpArgs as u32 => Ok(TestTransactionCode::GetDumpArgs),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700112 _ if c == TestTransactionCode::GetSelinuxContext as u32 => {
113 Ok(TestTransactionCode::GetSelinuxContext)
114 }
115 _ => Err(StatusCode::UNKNOWN_TRANSACTION),
116 }
117 }
118}
119
Stephen Crane2a3297f2021-06-11 16:48:10 -0700120impl Interface for TestService {
121 fn dump(&self, _file: &File, args: &[&CStr]) -> binder::Result<()> {
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}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700127
128impl ITest for TestService {
129 fn test(&self) -> binder::Result<String> {
130 Ok(self.s.clone())
131 }
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700132
Stephen Crane2a3297f2021-06-11 16:48:10 -0700133 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
134 let args = self.dump_args.lock().unwrap().clone();
135 Ok(args)
136 }
137
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700138 fn get_selinux_context(&self) -> binder::Result<String> {
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 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700143}
144
145/// Trivial testing binder interface
146pub trait ITest: Interface {
147 /// Returns a test string
148 fn test(&self) -> binder::Result<String>;
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700149
Stephen Crane2a3297f2021-06-11 16:48:10 -0700150 /// Return the arguments sent via dump
151 fn get_dump_args(&self) -> binder::Result<Vec<String>>;
152
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700153 /// Returns the caller's SELinux context
154 fn get_selinux_context(&self) -> binder::Result<String>;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700155}
156
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000157/// Async trivial testing binder interface
158pub trait IATest<P>: Interface {
159 /// Returns a test string
160 fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
161
162 /// Return the arguments sent via dump
163 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>>;
164
165 /// Returns the caller's SELinux context
166 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
167}
168
Stephen Crane2a3c2502020-06-16 17:48:35 -0700169declare_binder_interface! {
170 ITest["android.os.ITest"] {
171 native: BnTest(on_transact),
172 proxy: BpTest {
173 x: i32 = 100
174 },
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000175 async: IATest,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700176 }
177}
178
179fn on_transact(
180 service: &dyn ITest,
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700181 code: TransactionCode,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700182 _data: &Parcel,
183 reply: &mut Parcel,
184) -> binder::Result<()> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700185 match code.try_into()? {
186 TestTransactionCode::Test => reply.write(&service.test()?),
Stephen Crane2a3297f2021-06-11 16:48:10 -0700187 TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700188 TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
189 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700190}
191
192impl ITest for BpTest {
193 fn test(&self) -> binder::Result<String> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700194 let reply =
195 self.binder
196 .transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(()))?;
197 reply.read()
198 }
199
Stephen Crane2a3297f2021-06-11 16:48:10 -0700200 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
201 let reply =
202 self.binder
203 .transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(()))?;
204 reply.read()
205 }
206
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700207 fn get_selinux_context(&self) -> binder::Result<String> {
208 let reply = self.binder.transact(
209 TestTransactionCode::GetSelinuxContext as TransactionCode,
210 0,
211 |_| Ok(()),
212 )?;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700213 reply.read()
214 }
215}
216
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000217impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
218 fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
219 let binder = self.binder.clone();
220 P::spawn(
221 move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
222 |reply| async move { reply?.into_parcel().read() }
223 )
224 }
225
226 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
227 let binder = self.binder.clone();
228 P::spawn(
229 move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
230 |reply| async move { reply?.into_parcel().read() }
231 )
232 }
233
234 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
235 let binder = self.binder.clone();
236 P::spawn(
237 move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
238 |reply| async move { reply?.into_parcel().read() }
239 )
240 }
241}
242
Stephen Crane2a3c2502020-06-16 17:48:35 -0700243impl ITest for Binder<BnTest> {
244 fn test(&self) -> binder::Result<String> {
245 self.0.test()
246 }
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700247
Stephen Crane2a3297f2021-06-11 16:48:10 -0700248 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
249 self.0.get_dump_args()
250 }
251
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700252 fn get_selinux_context(&self) -> binder::Result<String> {
253 self.0.get_selinux_context()
254 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700255}
256
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000257impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
258 fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
259 let res = self.0.test();
260 Box::pin(async move { res })
261 }
262
263 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
264 let res = self.0.get_dump_args();
265 Box::pin(async move { res })
266 }
267
268 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
269 let res = self.0.get_selinux_context();
270 Box::pin(async move { res })
271 }
272}
273
Stephen Crane669deb62020-09-10 17:31:39 -0700274/// Trivial testing binder interface
275pub trait ITestSameDescriptor: Interface {}
276
277declare_binder_interface! {
278 ITestSameDescriptor["android.os.ITest"] {
279 native: BnTestSameDescriptor(on_transact_same_descriptor),
280 proxy: BpTestSameDescriptor,
281 }
282}
283
284fn on_transact_same_descriptor(
285 _service: &dyn ITestSameDescriptor,
286 _code: TransactionCode,
287 _data: &Parcel,
288 _reply: &mut Parcel,
289) -> binder::Result<()> {
290 Ok(())
291}
292
293impl ITestSameDescriptor for BpTestSameDescriptor {}
294
295impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
296
Stephen Crane2a3c2502020-06-16 17:48:35 -0700297#[cfg(test)]
298mod tests {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700299 use selinux_bindgen as selinux_sys;
300 use std::ffi::CStr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700301 use std::fs::File;
302 use std::process::{Child, Command};
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700303 use std::ptr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700304 use std::sync::atomic::{AtomicBool, Ordering};
305 use std::sync::Arc;
306 use std::thread;
307 use std::time::Duration;
308
Andrew Walbran12400d82021-03-04 17:04:34 +0000309 use binder::{
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000310 Binder, BinderFeatures, DeathRecipient, FromIBinder, IBinder, IBinderInternal, Interface,
311 SpIBinder, StatusCode, Strong,
Andrew Walbran12400d82021-03-04 17:04:34 +0000312 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700313
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000314 use binder_tokio::Tokio;
315
316 use super::{BnTest, ITest, IATest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
Stephen Crane2a3c2502020-06-16 17:48:35 -0700317
318 pub struct ScopedServiceProcess(Child);
319
320 impl ScopedServiceProcess {
321 pub fn new(identifier: &str) -> Self {
322 Self::new_internal(identifier, None)
323 }
324
325 pub fn new_with_extension(identifier: &str, extension: &str) -> Self {
326 Self::new_internal(identifier, Some(extension))
327 }
328
329 fn new_internal(identifier: &str, extension: Option<&str>) -> Self {
330 let mut binary_path =
331 std::env::current_exe().expect("Could not retrieve current executable path");
332 binary_path.pop();
333 binary_path.push(RUST_SERVICE_BINARY);
334 let mut command = Command::new(&binary_path);
335 command.arg(identifier);
336 if let Some(ext) = extension {
337 command.arg(ext);
338 }
339 let child = command.spawn().expect("Could not start service");
340 Self(child)
341 }
342 }
343
344 impl Drop for ScopedServiceProcess {
345 fn drop(&mut self) {
346 self.0.kill().expect("Could not kill child process");
347 self.0
348 .wait()
349 .expect("Could not wait for child process to die");
350 }
351 }
352
353 #[test]
354 fn check_services() {
355 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
356 assert!(sm.is_binder_alive());
357 assert!(sm.ping_binder().is_ok());
358
359 assert!(binder::get_service("this_service_does_not_exist").is_none());
360 assert_eq!(
361 binder::get_interface::<dyn ITest>("this_service_does_not_exist").err(),
362 Some(StatusCode::NAME_NOT_FOUND)
363 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000364 assert_eq!(
365 binder::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
366 Some(StatusCode::NAME_NOT_FOUND)
367 );
Stephen Crane2a3c2502020-06-16 17:48:35 -0700368
369 // The service manager service isn't an ITest, so this must fail.
370 assert_eq!(
371 binder::get_interface::<dyn ITest>("manager").err(),
372 Some(StatusCode::BAD_TYPE)
373 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000374 assert_eq!(
375 binder::get_interface::<dyn IATest<Tokio>>("manager").err(),
376 Some(StatusCode::BAD_TYPE)
377 );
Stephen Crane2a3c2502020-06-16 17:48:35 -0700378 }
379
Alice Ryhl929804f2021-11-02 12:04:39 +0000380 #[tokio::test]
381 async fn check_services_async() {
382 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
383 assert!(sm.is_binder_alive());
384 assert!(sm.ping_binder().is_ok());
385
386 assert!(binder::get_service("this_service_does_not_exist").is_none());
387 assert_eq!(
388 binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
389 Some(StatusCode::NAME_NOT_FOUND)
390 );
391 assert_eq!(
392 binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").await.err(),
393 Some(StatusCode::NAME_NOT_FOUND)
394 );
395
396 // The service manager service isn't an ITest, so this must fail.
397 assert_eq!(
398 binder_tokio::get_interface::<dyn ITest>("manager").await.err(),
399 Some(StatusCode::BAD_TYPE)
400 );
401 assert_eq!(
402 binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(),
403 Some(StatusCode::BAD_TYPE)
404 );
405 }
406
Stephen Crane2a3c2502020-06-16 17:48:35 -0700407 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000408 fn check_wait_for_service() {
409 let mut sm =
410 binder::wait_for_service("manager").expect("Did not get manager binder service");
411 assert!(sm.is_binder_alive());
412 assert!(sm.ping_binder().is_ok());
413
414 // The service manager service isn't an ITest, so this must fail.
415 assert_eq!(
416 binder::wait_for_interface::<dyn ITest>("manager").err(),
417 Some(StatusCode::BAD_TYPE)
418 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000419 assert_eq!(
420 binder::wait_for_interface::<dyn IATest<Tokio>>("manager").err(),
421 Some(StatusCode::BAD_TYPE)
422 );
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000423 }
424
425 #[test]
Stephen Crane2a3c2502020-06-16 17:48:35 -0700426 fn trivial_client() {
427 let service_name = "trivial_client_test";
428 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800429 let test_client: Strong<dyn ITest> =
Stephen Crane2a3c2502020-06-16 17:48:35 -0700430 binder::get_interface(service_name).expect("Did not get manager binder service");
431 assert_eq!(test_client.test().unwrap(), "trivial_client_test");
432 }
433
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000434 #[tokio::test]
435 async fn trivial_client_async() {
436 let service_name = "trivial_client_test";
437 let _process = ScopedServiceProcess::new(service_name);
438 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000439 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000440 assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
441 }
442
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700443 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000444 fn wait_for_trivial_client() {
445 let service_name = "wait_for_trivial_client_test";
446 let _process = ScopedServiceProcess::new(service_name);
447 let test_client: Strong<dyn ITest> =
448 binder::wait_for_interface(service_name).expect("Did not get manager binder service");
449 assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
450 }
451
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000452 #[tokio::test]
453 async fn wait_for_trivial_client_async() {
454 let service_name = "wait_for_trivial_client_test";
455 let _process = ScopedServiceProcess::new(service_name);
456 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000457 binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000458 assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
459 }
460
461 fn get_expected_selinux_context() -> &'static str {
462 unsafe {
463 let mut out_ptr = ptr::null_mut();
464 assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
465 assert!(!out_ptr.is_null());
466 CStr::from_ptr(out_ptr)
467 .to_str()
468 .expect("context was invalid UTF-8")
469 }
470 }
471
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000472 #[test]
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700473 fn get_selinux_context() {
474 let service_name = "get_selinux_context";
475 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800476 let test_client: Strong<dyn ITest> =
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700477 binder::get_interface(service_name).expect("Did not get manager binder service");
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700478 assert_eq!(
479 test_client.get_selinux_context().unwrap(),
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000480 get_expected_selinux_context()
481 );
482 }
483
484 #[tokio::test]
485 async fn get_selinux_context_async() {
486 let service_name = "get_selinux_context";
487 let _process = ScopedServiceProcess::new(service_name);
488 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000489 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000490 assert_eq!(
491 test_client.get_selinux_context().await.unwrap(),
492 get_expected_selinux_context()
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700493 );
494 }
495
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000496 struct Bools {
497 binder_died: Arc<AtomicBool>,
498 binder_dealloc: Arc<AtomicBool>,
499 }
500
501 impl Bools {
502 fn is_dead(&self) -> bool {
503 self.binder_died.load(Ordering::Relaxed)
504 }
505 fn assert_died(&self) {
506 assert!(
507 self.is_dead(),
508 "Did not receive death notification"
509 );
510 }
511 fn assert_dropped(&self) {
512 assert!(
513 self.binder_dealloc.load(Ordering::Relaxed),
514 "Did not dealloc death notification"
515 );
516 }
517 fn assert_not_dropped(&self) {
518 assert!(
519 !self.binder_dealloc.load(Ordering::Relaxed),
520 "Dealloc death notification too early"
521 );
522 }
523 }
524
525 fn register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient) {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700526 let binder_died = Arc::new(AtomicBool::new(false));
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000527 let binder_dealloc = Arc::new(AtomicBool::new(false));
528
529 struct SetOnDrop {
530 binder_dealloc: Arc<AtomicBool>,
531 }
532 impl Drop for SetOnDrop {
533 fn drop(&mut self) {
534 self.binder_dealloc.store(true, Ordering::Relaxed);
535 }
536 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700537
538 let mut death_recipient = {
539 let flag = binder_died.clone();
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000540 let set_on_drop = SetOnDrop {
541 binder_dealloc: binder_dealloc.clone(),
542 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700543 DeathRecipient::new(move || {
544 flag.store(true, Ordering::Relaxed);
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000545 // Force the closure to take ownership of set_on_drop. When the closure is
546 // dropped, the destructor of `set_on_drop` will run.
547 let _ = &set_on_drop;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700548 })
549 };
550
551 binder
552 .link_to_death(&mut death_recipient)
553 .expect("link_to_death failed");
554
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000555 let bools = Bools {
556 binder_died,
557 binder_dealloc,
558 };
559
560 (bools, death_recipient)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700561 }
562
563 /// Killing a remote service should unregister the service and trigger
564 /// death notifications.
565 #[test]
566 fn test_death_notifications() {
567 binder::ProcessState::start_thread_pool();
568
569 let service_name = "test_death_notifications";
570 let service_process = ScopedServiceProcess::new(service_name);
571 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
572
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000573 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700574
575 drop(service_process);
576 remote
577 .ping_binder()
578 .expect_err("Service should have died already");
579
580 // Pause to ensure any death notifications get delivered
581 thread::sleep(Duration::from_secs(1));
582
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000583 bools.assert_died();
584 bools.assert_not_dropped();
585
586 drop(recipient);
587
588 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700589 }
590
591 /// Test unregistering death notifications.
592 #[test]
593 fn test_unregister_death_notifications() {
594 binder::ProcessState::start_thread_pool();
595
596 let service_name = "test_unregister_death_notifications";
597 let service_process = ScopedServiceProcess::new(service_name);
598 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
599
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000600 let (bools, mut recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700601
602 remote
603 .unlink_to_death(&mut recipient)
604 .expect("Could not unlink death notifications");
605
606 drop(service_process);
607 remote
608 .ping_binder()
609 .expect_err("Service should have died already");
610
611 // Pause to ensure any death notifications get delivered
612 thread::sleep(Duration::from_secs(1));
613
614 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000615 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700616 "Received unexpected death notification after unlinking",
617 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000618
619 bools.assert_not_dropped();
620 drop(recipient);
621 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700622 }
623
624 /// Dropping a remote handle should unregister any death notifications.
625 #[test]
626 fn test_death_notification_registration_lifetime() {
627 binder::ProcessState::start_thread_pool();
628
629 let service_name = "test_death_notification_registration_lifetime";
630 let service_process = ScopedServiceProcess::new(service_name);
631 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
632
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000633 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700634
635 // This should automatically unregister our death notification.
636 drop(remote);
637
638 drop(service_process);
639
640 // Pause to ensure any death notifications get delivered
641 thread::sleep(Duration::from_secs(1));
642
643 // We dropped the remote handle, so we should not receive the death
644 // notification when the remote process dies here.
645 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000646 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700647 "Received unexpected death notification after dropping remote handle"
648 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000649
650 bools.assert_not_dropped();
651 drop(recipient);
652 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700653 }
654
655 /// Test IBinder interface methods not exercised elsewhere.
656 #[test]
657 fn test_misc_ibinder() {
658 let service_name = "rust_test_ibinder";
659
660 {
661 let _process = ScopedServiceProcess::new(service_name);
662
Stephen Crane2a3297f2021-06-11 16:48:10 -0700663 let test_client: Strong<dyn ITest> =
664 binder::get_interface(service_name)
665 .expect("Did not get test binder service");
666 let mut remote = test_client.as_binder();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700667 assert!(remote.is_binder_alive());
668 remote.ping_binder().expect("Could not ping remote service");
669
Stephen Crane2a3297f2021-06-11 16:48:10 -0700670 let dump_args = ["dump", "args", "for", "testing"];
671
Stephen Crane2a3c2502020-06-16 17:48:35 -0700672 let null_out = File::open("/dev/null").expect("Could not open /dev/null");
673 remote
Stephen Crane2a3297f2021-06-11 16:48:10 -0700674 .dump(&null_out, &dump_args)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700675 .expect("Could not dump remote service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700676
677 let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
678 assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
Stephen Crane2a3c2502020-06-16 17:48:35 -0700679 }
680
681 // get/set_extensions is tested in test_extensions()
682
683 // transact is tested everywhere else, and we can't make raw
684 // transactions outside the [FIRST_CALL_TRANSACTION,
685 // LAST_CALL_TRANSACTION] range from the NDK anyway.
686
687 // link_to_death is tested in test_*_death_notification* tests.
688 }
689
690 #[test]
691 fn test_extensions() {
692 let service_name = "rust_test_extensions";
693 let extension_name = "rust_test_extensions_ext";
694
695 {
696 let _process = ScopedServiceProcess::new(service_name);
697
698 let mut remote = binder::get_service(service_name);
699 assert!(remote.is_binder_alive());
700
701 let extension = remote
702 .get_extension()
703 .expect("Could not check for an extension");
704 assert!(extension.is_none());
705 }
706
707 {
708 let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
709
710 let mut remote = binder::get_service(service_name);
711 assert!(remote.is_binder_alive());
712
713 let maybe_extension = remote
714 .get_extension()
715 .expect("Could not check for an extension");
716
717 let extension = maybe_extension.expect("Remote binder did not have an extension");
718
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800719 let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700720 .expect("Extension could not be converted to the expected interface");
721
722 assert_eq!(extension.test().unwrap(), extension_name);
723 }
724 }
Stephen Crane669deb62020-09-10 17:31:39 -0700725
726 /// Test re-associating a local binder object with a different class.
727 ///
728 /// This is needed because different binder service (e.g. NDK vs Rust)
729 /// implementations are incompatible and must not be interchanged. A local
730 /// service with the same descriptor string but a different class pointer
731 /// may have been created by an NDK service and is therefore incompatible
732 /// with the Rust service implementation. It must be treated as remote and
733 /// all API calls parceled and sent through transactions.
734 ///
735 /// Further tests of this behavior with the C NDK and Rust API are in
736 /// rust_ndk_interop.rs
737 #[test]
738 fn associate_existing_class() {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700739 let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
Stephen Crane669deb62020-09-10 17:31:39 -0700740
741 // This should succeed although we will have to treat the service as
742 // remote.
Andrew Walbran12400d82021-03-04 17:04:34 +0000743 let _interface: Strong<dyn ITestSameDescriptor> =
744 FromIBinder::try_from(service.as_binder())
745 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
Stephen Crane669deb62020-09-10 17:31:39 -0700746 }
747
748 /// Test that we can round-trip a rust service through a generic IBinder
749 #[test]
750 fn reassociate_rust_binder() {
751 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000752 let service_ibinder = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700753 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000754 BinderFeatures::default(),
755 )
Andrew Walbran12400d82021-03-04 17:04:34 +0000756 .as_binder();
Stephen Crane669deb62020-09-10 17:31:39 -0700757
Andrew Walbran12400d82021-03-04 17:04:34 +0000758 let service: Strong<dyn ITest> = service_ibinder
759 .into_interface()
Stephen Crane669deb62020-09-10 17:31:39 -0700760 .expect("Could not reassociate the generic ibinder");
761
762 assert_eq!(service.test().unwrap(), service_name);
763 }
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800764
765 #[test]
766 fn weak_binder_upgrade() {
767 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000768 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700769 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000770 BinderFeatures::default(),
771 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800772
773 let weak = Strong::downgrade(&service);
774
775 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
776
777 assert_eq!(service, upgraded);
778 }
779
780 #[test]
781 fn weak_binder_upgrade_dead() {
782 let service_name = "testing_service";
783 let weak = {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000784 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700785 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000786 BinderFeatures::default(),
787 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800788
789 Strong::downgrade(&service)
790 };
791
792 assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
793 }
794
795 #[test]
796 fn weak_binder_clone() {
797 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000798 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700799 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000800 BinderFeatures::default(),
801 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800802
803 let weak = Strong::downgrade(&service);
804 let cloned = weak.clone();
805 assert_eq!(weak, cloned);
806
807 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
808 let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
809
810 assert_eq!(service, upgraded);
811 assert_eq!(service, clone_upgraded);
812 }
813
814 #[test]
815 #[allow(clippy::eq_op)]
816 fn binder_ord() {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000817 let service1 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700818 TestService::new("testing_service1"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000819 BinderFeatures::default(),
820 );
821 let service2 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700822 TestService::new("testing_service2"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000823 BinderFeatures::default(),
824 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800825
826 assert!(!(service1 < service1));
827 assert!(!(service1 > service1));
828 assert_eq!(service1 < service2, !(service2 < service1));
829 }
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000830
831 #[test]
832 fn binder_parcel_mixup() {
833 let service1 = BnTest::new_binder(
834 TestService::new("testing_service1"),
835 BinderFeatures::default(),
836 );
837 let service2 = BnTest::new_binder(
838 TestService::new("testing_service2"),
839 BinderFeatures::default(),
840 );
841
842 let service1 = service1.as_binder();
843 let service2 = service2.as_binder();
844
845 let parcel = service1.prepare_transact().unwrap();
846 let res = service2.submit_transact(super::TestTransactionCode::Test as binder::TransactionCode, parcel, 0);
847
848 match res {
849 Ok(_) => panic!("submit_transact should fail"),
850 Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
851 }
852 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700853}