blob: 3c2907393f44adb3743aa4efc6c3fe21e80eb3b2 [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
380 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000381 fn check_wait_for_service() {
382 let mut sm =
383 binder::wait_for_service("manager").expect("Did not get manager binder service");
384 assert!(sm.is_binder_alive());
385 assert!(sm.ping_binder().is_ok());
386
387 // The service manager service isn't an ITest, so this must fail.
388 assert_eq!(
389 binder::wait_for_interface::<dyn ITest>("manager").err(),
390 Some(StatusCode::BAD_TYPE)
391 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000392 assert_eq!(
393 binder::wait_for_interface::<dyn IATest<Tokio>>("manager").err(),
394 Some(StatusCode::BAD_TYPE)
395 );
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000396 }
397
398 #[test]
Stephen Crane2a3c2502020-06-16 17:48:35 -0700399 fn trivial_client() {
400 let service_name = "trivial_client_test";
401 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800402 let test_client: Strong<dyn ITest> =
Stephen Crane2a3c2502020-06-16 17:48:35 -0700403 binder::get_interface(service_name).expect("Did not get manager binder service");
404 assert_eq!(test_client.test().unwrap(), "trivial_client_test");
405 }
406
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000407 #[tokio::test]
408 async fn trivial_client_async() {
409 let service_name = "trivial_client_test";
410 let _process = ScopedServiceProcess::new(service_name);
411 let test_client: Strong<dyn IATest<Tokio>> =
412 binder::get_interface(service_name).expect("Did not get manager binder service");
413 assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
414 }
415
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700416 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000417 fn wait_for_trivial_client() {
418 let service_name = "wait_for_trivial_client_test";
419 let _process = ScopedServiceProcess::new(service_name);
420 let test_client: Strong<dyn ITest> =
421 binder::wait_for_interface(service_name).expect("Did not get manager binder service");
422 assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
423 }
424
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000425 #[tokio::test]
426 async fn wait_for_trivial_client_async() {
427 let service_name = "wait_for_trivial_client_test";
428 let _process = ScopedServiceProcess::new(service_name);
429 let test_client: Strong<dyn IATest<Tokio>> =
430 binder::wait_for_interface(service_name).expect("Did not get manager binder service");
431 assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
432 }
433
434 fn get_expected_selinux_context() -> &'static str {
435 unsafe {
436 let mut out_ptr = ptr::null_mut();
437 assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
438 assert!(!out_ptr.is_null());
439 CStr::from_ptr(out_ptr)
440 .to_str()
441 .expect("context was invalid UTF-8")
442 }
443 }
444
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000445 #[test]
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700446 fn get_selinux_context() {
447 let service_name = "get_selinux_context";
448 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800449 let test_client: Strong<dyn ITest> =
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700450 binder::get_interface(service_name).expect("Did not get manager binder service");
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700451 assert_eq!(
452 test_client.get_selinux_context().unwrap(),
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000453 get_expected_selinux_context()
454 );
455 }
456
457 #[tokio::test]
458 async fn get_selinux_context_async() {
459 let service_name = "get_selinux_context";
460 let _process = ScopedServiceProcess::new(service_name);
461 let test_client: Strong<dyn IATest<Tokio>> =
462 binder::get_interface(service_name).expect("Did not get manager binder service");
463 assert_eq!(
464 test_client.get_selinux_context().await.unwrap(),
465 get_expected_selinux_context()
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700466 );
467 }
468
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000469 struct Bools {
470 binder_died: Arc<AtomicBool>,
471 binder_dealloc: Arc<AtomicBool>,
472 }
473
474 impl Bools {
475 fn is_dead(&self) -> bool {
476 self.binder_died.load(Ordering::Relaxed)
477 }
478 fn assert_died(&self) {
479 assert!(
480 self.is_dead(),
481 "Did not receive death notification"
482 );
483 }
484 fn assert_dropped(&self) {
485 assert!(
486 self.binder_dealloc.load(Ordering::Relaxed),
487 "Did not dealloc death notification"
488 );
489 }
490 fn assert_not_dropped(&self) {
491 assert!(
492 !self.binder_dealloc.load(Ordering::Relaxed),
493 "Dealloc death notification too early"
494 );
495 }
496 }
497
498 fn register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient) {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700499 let binder_died = Arc::new(AtomicBool::new(false));
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000500 let binder_dealloc = Arc::new(AtomicBool::new(false));
501
502 struct SetOnDrop {
503 binder_dealloc: Arc<AtomicBool>,
504 }
505 impl Drop for SetOnDrop {
506 fn drop(&mut self) {
507 self.binder_dealloc.store(true, Ordering::Relaxed);
508 }
509 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700510
511 let mut death_recipient = {
512 let flag = binder_died.clone();
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000513 let set_on_drop = SetOnDrop {
514 binder_dealloc: binder_dealloc.clone(),
515 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700516 DeathRecipient::new(move || {
517 flag.store(true, Ordering::Relaxed);
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000518 // Force the closure to take ownership of set_on_drop. When the closure is
519 // dropped, the destructor of `set_on_drop` will run.
520 let _ = &set_on_drop;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700521 })
522 };
523
524 binder
525 .link_to_death(&mut death_recipient)
526 .expect("link_to_death failed");
527
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000528 let bools = Bools {
529 binder_died,
530 binder_dealloc,
531 };
532
533 (bools, death_recipient)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700534 }
535
536 /// Killing a remote service should unregister the service and trigger
537 /// death notifications.
538 #[test]
539 fn test_death_notifications() {
540 binder::ProcessState::start_thread_pool();
541
542 let service_name = "test_death_notifications";
543 let service_process = ScopedServiceProcess::new(service_name);
544 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
545
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000546 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700547
548 drop(service_process);
549 remote
550 .ping_binder()
551 .expect_err("Service should have died already");
552
553 // Pause to ensure any death notifications get delivered
554 thread::sleep(Duration::from_secs(1));
555
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000556 bools.assert_died();
557 bools.assert_not_dropped();
558
559 drop(recipient);
560
561 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700562 }
563
564 /// Test unregistering death notifications.
565 #[test]
566 fn test_unregister_death_notifications() {
567 binder::ProcessState::start_thread_pool();
568
569 let service_name = "test_unregister_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, mut recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700574
575 remote
576 .unlink_to_death(&mut recipient)
577 .expect("Could not unlink death notifications");
578
579 drop(service_process);
580 remote
581 .ping_binder()
582 .expect_err("Service should have died already");
583
584 // Pause to ensure any death notifications get delivered
585 thread::sleep(Duration::from_secs(1));
586
587 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000588 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700589 "Received unexpected death notification after unlinking",
590 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000591
592 bools.assert_not_dropped();
593 drop(recipient);
594 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700595 }
596
597 /// Dropping a remote handle should unregister any death notifications.
598 #[test]
599 fn test_death_notification_registration_lifetime() {
600 binder::ProcessState::start_thread_pool();
601
602 let service_name = "test_death_notification_registration_lifetime";
603 let service_process = ScopedServiceProcess::new(service_name);
604 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
605
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000606 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700607
608 // This should automatically unregister our death notification.
609 drop(remote);
610
611 drop(service_process);
612
613 // Pause to ensure any death notifications get delivered
614 thread::sleep(Duration::from_secs(1));
615
616 // We dropped the remote handle, so we should not receive the death
617 // notification when the remote process dies here.
618 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000619 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700620 "Received unexpected death notification after dropping remote handle"
621 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000622
623 bools.assert_not_dropped();
624 drop(recipient);
625 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700626 }
627
628 /// Test IBinder interface methods not exercised elsewhere.
629 #[test]
630 fn test_misc_ibinder() {
631 let service_name = "rust_test_ibinder";
632
633 {
634 let _process = ScopedServiceProcess::new(service_name);
635
Stephen Crane2a3297f2021-06-11 16:48:10 -0700636 let test_client: Strong<dyn ITest> =
637 binder::get_interface(service_name)
638 .expect("Did not get test binder service");
639 let mut remote = test_client.as_binder();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700640 assert!(remote.is_binder_alive());
641 remote.ping_binder().expect("Could not ping remote service");
642
Stephen Crane2a3297f2021-06-11 16:48:10 -0700643 let dump_args = ["dump", "args", "for", "testing"];
644
Stephen Crane2a3c2502020-06-16 17:48:35 -0700645 let null_out = File::open("/dev/null").expect("Could not open /dev/null");
646 remote
Stephen Crane2a3297f2021-06-11 16:48:10 -0700647 .dump(&null_out, &dump_args)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700648 .expect("Could not dump remote service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700649
650 let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
651 assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
Stephen Crane2a3c2502020-06-16 17:48:35 -0700652 }
653
654 // get/set_extensions is tested in test_extensions()
655
656 // transact is tested everywhere else, and we can't make raw
657 // transactions outside the [FIRST_CALL_TRANSACTION,
658 // LAST_CALL_TRANSACTION] range from the NDK anyway.
659
660 // link_to_death is tested in test_*_death_notification* tests.
661 }
662
663 #[test]
664 fn test_extensions() {
665 let service_name = "rust_test_extensions";
666 let extension_name = "rust_test_extensions_ext";
667
668 {
669 let _process = ScopedServiceProcess::new(service_name);
670
671 let mut remote = binder::get_service(service_name);
672 assert!(remote.is_binder_alive());
673
674 let extension = remote
675 .get_extension()
676 .expect("Could not check for an extension");
677 assert!(extension.is_none());
678 }
679
680 {
681 let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
682
683 let mut remote = binder::get_service(service_name);
684 assert!(remote.is_binder_alive());
685
686 let maybe_extension = remote
687 .get_extension()
688 .expect("Could not check for an extension");
689
690 let extension = maybe_extension.expect("Remote binder did not have an extension");
691
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800692 let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700693 .expect("Extension could not be converted to the expected interface");
694
695 assert_eq!(extension.test().unwrap(), extension_name);
696 }
697 }
Stephen Crane669deb62020-09-10 17:31:39 -0700698
699 /// Test re-associating a local binder object with a different class.
700 ///
701 /// This is needed because different binder service (e.g. NDK vs Rust)
702 /// implementations are incompatible and must not be interchanged. A local
703 /// service with the same descriptor string but a different class pointer
704 /// may have been created by an NDK service and is therefore incompatible
705 /// with the Rust service implementation. It must be treated as remote and
706 /// all API calls parceled and sent through transactions.
707 ///
708 /// Further tests of this behavior with the C NDK and Rust API are in
709 /// rust_ndk_interop.rs
710 #[test]
711 fn associate_existing_class() {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700712 let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
Stephen Crane669deb62020-09-10 17:31:39 -0700713
714 // This should succeed although we will have to treat the service as
715 // remote.
Andrew Walbran12400d82021-03-04 17:04:34 +0000716 let _interface: Strong<dyn ITestSameDescriptor> =
717 FromIBinder::try_from(service.as_binder())
718 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
Stephen Crane669deb62020-09-10 17:31:39 -0700719 }
720
721 /// Test that we can round-trip a rust service through a generic IBinder
722 #[test]
723 fn reassociate_rust_binder() {
724 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000725 let service_ibinder = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700726 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000727 BinderFeatures::default(),
728 )
Andrew Walbran12400d82021-03-04 17:04:34 +0000729 .as_binder();
Stephen Crane669deb62020-09-10 17:31:39 -0700730
Andrew Walbran12400d82021-03-04 17:04:34 +0000731 let service: Strong<dyn ITest> = service_ibinder
732 .into_interface()
Stephen Crane669deb62020-09-10 17:31:39 -0700733 .expect("Could not reassociate the generic ibinder");
734
735 assert_eq!(service.test().unwrap(), service_name);
736 }
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800737
738 #[test]
739 fn weak_binder_upgrade() {
740 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000741 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700742 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000743 BinderFeatures::default(),
744 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800745
746 let weak = Strong::downgrade(&service);
747
748 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
749
750 assert_eq!(service, upgraded);
751 }
752
753 #[test]
754 fn weak_binder_upgrade_dead() {
755 let service_name = "testing_service";
756 let weak = {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000757 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700758 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000759 BinderFeatures::default(),
760 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800761
762 Strong::downgrade(&service)
763 };
764
765 assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
766 }
767
768 #[test]
769 fn weak_binder_clone() {
770 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000771 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700772 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000773 BinderFeatures::default(),
774 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800775
776 let weak = Strong::downgrade(&service);
777 let cloned = weak.clone();
778 assert_eq!(weak, cloned);
779
780 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
781 let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
782
783 assert_eq!(service, upgraded);
784 assert_eq!(service, clone_upgraded);
785 }
786
787 #[test]
788 #[allow(clippy::eq_op)]
789 fn binder_ord() {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000790 let service1 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700791 TestService::new("testing_service1"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000792 BinderFeatures::default(),
793 );
794 let service2 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700795 TestService::new("testing_service2"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000796 BinderFeatures::default(),
797 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800798
799 assert!(!(service1 < service1));
800 assert!(!(service1 > service1));
801 assert_eq!(service1 < service2, !(service2 < service1));
802 }
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000803
804 #[test]
805 fn binder_parcel_mixup() {
806 let service1 = BnTest::new_binder(
807 TestService::new("testing_service1"),
808 BinderFeatures::default(),
809 );
810 let service2 = BnTest::new_binder(
811 TestService::new("testing_service2"),
812 BinderFeatures::default(),
813 );
814
815 let service1 = service1.as_binder();
816 let service2 = service2.as_binder();
817
818 let parcel = service1.prepare_transact().unwrap();
819 let res = service2.submit_transact(super::TestTransactionCode::Test as binder::TransactionCode, parcel, 0);
820
821 match res {
822 Ok(_) => panic!("submit_transact should fail"),
823 Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
824 }
825 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700826}