blob: ac9eed2d5e8f1b43bbddfa0d4511b1ca72e8825c [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;
20use binder::parcel::Parcel;
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
157declare_binder_interface! {
158 ITest["android.os.ITest"] {
159 native: BnTest(on_transact),
160 proxy: BpTest {
161 x: i32 = 100
162 },
163 }
164}
165
166fn on_transact(
167 service: &dyn ITest,
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700168 code: TransactionCode,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700169 _data: &Parcel,
170 reply: &mut Parcel,
171) -> binder::Result<()> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700172 match code.try_into()? {
173 TestTransactionCode::Test => reply.write(&service.test()?),
Stephen Crane2a3297f2021-06-11 16:48:10 -0700174 TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700175 TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
176 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700177}
178
179impl ITest for BpTest {
180 fn test(&self) -> binder::Result<String> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700181 let reply =
182 self.binder
183 .transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(()))?;
184 reply.read()
185 }
186
Stephen Crane2a3297f2021-06-11 16:48:10 -0700187 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
188 let reply =
189 self.binder
190 .transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(()))?;
191 reply.read()
192 }
193
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700194 fn get_selinux_context(&self) -> binder::Result<String> {
195 let reply = self.binder.transact(
196 TestTransactionCode::GetSelinuxContext as TransactionCode,
197 0,
198 |_| Ok(()),
199 )?;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700200 reply.read()
201 }
202}
203
204impl ITest for Binder<BnTest> {
205 fn test(&self) -> binder::Result<String> {
206 self.0.test()
207 }
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700208
Stephen Crane2a3297f2021-06-11 16:48:10 -0700209 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
210 self.0.get_dump_args()
211 }
212
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700213 fn get_selinux_context(&self) -> binder::Result<String> {
214 self.0.get_selinux_context()
215 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700216}
217
Stephen Crane669deb62020-09-10 17:31:39 -0700218/// Trivial testing binder interface
219pub trait ITestSameDescriptor: Interface {}
220
221declare_binder_interface! {
222 ITestSameDescriptor["android.os.ITest"] {
223 native: BnTestSameDescriptor(on_transact_same_descriptor),
224 proxy: BpTestSameDescriptor,
225 }
226}
227
228fn on_transact_same_descriptor(
229 _service: &dyn ITestSameDescriptor,
230 _code: TransactionCode,
231 _data: &Parcel,
232 _reply: &mut Parcel,
233) -> binder::Result<()> {
234 Ok(())
235}
236
237impl ITestSameDescriptor for BpTestSameDescriptor {}
238
239impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
240
Stephen Crane2a3c2502020-06-16 17:48:35 -0700241#[cfg(test)]
242mod tests {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700243 use selinux_bindgen as selinux_sys;
244 use std::ffi::CStr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700245 use std::fs::File;
246 use std::process::{Child, Command};
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700247 use std::ptr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700248 use std::sync::atomic::{AtomicBool, Ordering};
249 use std::sync::Arc;
250 use std::thread;
251 use std::time::Duration;
252
Andrew Walbran12400d82021-03-04 17:04:34 +0000253 use binder::{
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000254 Binder, BinderFeatures, DeathRecipient, FromIBinder, IBinder, IBinderInternal, Interface,
255 SpIBinder, StatusCode, Strong,
Andrew Walbran12400d82021-03-04 17:04:34 +0000256 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700257
Andrew Walbran12400d82021-03-04 17:04:34 +0000258 use super::{BnTest, ITest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
Stephen Crane2a3c2502020-06-16 17:48:35 -0700259
260 pub struct ScopedServiceProcess(Child);
261
262 impl ScopedServiceProcess {
263 pub fn new(identifier: &str) -> Self {
264 Self::new_internal(identifier, None)
265 }
266
267 pub fn new_with_extension(identifier: &str, extension: &str) -> Self {
268 Self::new_internal(identifier, Some(extension))
269 }
270
271 fn new_internal(identifier: &str, extension: Option<&str>) -> Self {
272 let mut binary_path =
273 std::env::current_exe().expect("Could not retrieve current executable path");
274 binary_path.pop();
275 binary_path.push(RUST_SERVICE_BINARY);
276 let mut command = Command::new(&binary_path);
277 command.arg(identifier);
278 if let Some(ext) = extension {
279 command.arg(ext);
280 }
281 let child = command.spawn().expect("Could not start service");
282 Self(child)
283 }
284 }
285
286 impl Drop for ScopedServiceProcess {
287 fn drop(&mut self) {
288 self.0.kill().expect("Could not kill child process");
289 self.0
290 .wait()
291 .expect("Could not wait for child process to die");
292 }
293 }
294
295 #[test]
296 fn check_services() {
297 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
298 assert!(sm.is_binder_alive());
299 assert!(sm.ping_binder().is_ok());
300
301 assert!(binder::get_service("this_service_does_not_exist").is_none());
302 assert_eq!(
303 binder::get_interface::<dyn ITest>("this_service_does_not_exist").err(),
304 Some(StatusCode::NAME_NOT_FOUND)
305 );
306
307 // The service manager service isn't an ITest, so this must fail.
308 assert_eq!(
309 binder::get_interface::<dyn ITest>("manager").err(),
310 Some(StatusCode::BAD_TYPE)
311 );
312 }
313
314 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000315 fn check_wait_for_service() {
316 let mut sm =
317 binder::wait_for_service("manager").expect("Did not get manager binder service");
318 assert!(sm.is_binder_alive());
319 assert!(sm.ping_binder().is_ok());
320
321 // The service manager service isn't an ITest, so this must fail.
322 assert_eq!(
323 binder::wait_for_interface::<dyn ITest>("manager").err(),
324 Some(StatusCode::BAD_TYPE)
325 );
326 }
327
328 #[test]
Stephen Crane2a3c2502020-06-16 17:48:35 -0700329 fn trivial_client() {
330 let service_name = "trivial_client_test";
331 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800332 let test_client: Strong<dyn ITest> =
Stephen Crane2a3c2502020-06-16 17:48:35 -0700333 binder::get_interface(service_name).expect("Did not get manager binder service");
334 assert_eq!(test_client.test().unwrap(), "trivial_client_test");
335 }
336
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700337 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000338 fn wait_for_trivial_client() {
339 let service_name = "wait_for_trivial_client_test";
340 let _process = ScopedServiceProcess::new(service_name);
341 let test_client: Strong<dyn ITest> =
342 binder::wait_for_interface(service_name).expect("Did not get manager binder service");
343 assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
344 }
345
346 #[test]
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700347 fn get_selinux_context() {
348 let service_name = "get_selinux_context";
349 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800350 let test_client: Strong<dyn ITest> =
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700351 binder::get_interface(service_name).expect("Did not get manager binder service");
352 let expected_context = unsafe {
353 let mut out_ptr = ptr::null_mut();
354 assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
355 assert!(!out_ptr.is_null());
356 CStr::from_ptr(out_ptr)
357 };
358 assert_eq!(
359 test_client.get_selinux_context().unwrap(),
Andrew Walbran12400d82021-03-04 17:04:34 +0000360 expected_context
361 .to_str()
362 .expect("context was invalid UTF-8"),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700363 );
364 }
365
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000366 struct Bools {
367 binder_died: Arc<AtomicBool>,
368 binder_dealloc: Arc<AtomicBool>,
369 }
370
371 impl Bools {
372 fn is_dead(&self) -> bool {
373 self.binder_died.load(Ordering::Relaxed)
374 }
375 fn assert_died(&self) {
376 assert!(
377 self.is_dead(),
378 "Did not receive death notification"
379 );
380 }
381 fn assert_dropped(&self) {
382 assert!(
383 self.binder_dealloc.load(Ordering::Relaxed),
384 "Did not dealloc death notification"
385 );
386 }
387 fn assert_not_dropped(&self) {
388 assert!(
389 !self.binder_dealloc.load(Ordering::Relaxed),
390 "Dealloc death notification too early"
391 );
392 }
393 }
394
395 fn register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient) {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700396 let binder_died = Arc::new(AtomicBool::new(false));
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000397 let binder_dealloc = Arc::new(AtomicBool::new(false));
398
399 struct SetOnDrop {
400 binder_dealloc: Arc<AtomicBool>,
401 }
402 impl Drop for SetOnDrop {
403 fn drop(&mut self) {
404 self.binder_dealloc.store(true, Ordering::Relaxed);
405 }
406 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700407
408 let mut death_recipient = {
409 let flag = binder_died.clone();
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000410 let set_on_drop = SetOnDrop {
411 binder_dealloc: binder_dealloc.clone(),
412 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700413 DeathRecipient::new(move || {
414 flag.store(true, Ordering::Relaxed);
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000415 // Force the closure to take ownership of set_on_drop. When the closure is
416 // dropped, the destructor of `set_on_drop` will run.
417 let _ = &set_on_drop;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700418 })
419 };
420
421 binder
422 .link_to_death(&mut death_recipient)
423 .expect("link_to_death failed");
424
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000425 let bools = Bools {
426 binder_died,
427 binder_dealloc,
428 };
429
430 (bools, death_recipient)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700431 }
432
433 /// Killing a remote service should unregister the service and trigger
434 /// death notifications.
435 #[test]
436 fn test_death_notifications() {
437 binder::ProcessState::start_thread_pool();
438
439 let service_name = "test_death_notifications";
440 let service_process = ScopedServiceProcess::new(service_name);
441 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
442
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000443 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700444
445 drop(service_process);
446 remote
447 .ping_binder()
448 .expect_err("Service should have died already");
449
450 // Pause to ensure any death notifications get delivered
451 thread::sleep(Duration::from_secs(1));
452
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000453 bools.assert_died();
454 bools.assert_not_dropped();
455
456 drop(recipient);
457
458 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700459 }
460
461 /// Test unregistering death notifications.
462 #[test]
463 fn test_unregister_death_notifications() {
464 binder::ProcessState::start_thread_pool();
465
466 let service_name = "test_unregister_death_notifications";
467 let service_process = ScopedServiceProcess::new(service_name);
468 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
469
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000470 let (bools, mut recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700471
472 remote
473 .unlink_to_death(&mut recipient)
474 .expect("Could not unlink death notifications");
475
476 drop(service_process);
477 remote
478 .ping_binder()
479 .expect_err("Service should have died already");
480
481 // Pause to ensure any death notifications get delivered
482 thread::sleep(Duration::from_secs(1));
483
484 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000485 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700486 "Received unexpected death notification after unlinking",
487 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000488
489 bools.assert_not_dropped();
490 drop(recipient);
491 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700492 }
493
494 /// Dropping a remote handle should unregister any death notifications.
495 #[test]
496 fn test_death_notification_registration_lifetime() {
497 binder::ProcessState::start_thread_pool();
498
499 let service_name = "test_death_notification_registration_lifetime";
500 let service_process = ScopedServiceProcess::new(service_name);
501 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
502
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000503 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700504
505 // This should automatically unregister our death notification.
506 drop(remote);
507
508 drop(service_process);
509
510 // Pause to ensure any death notifications get delivered
511 thread::sleep(Duration::from_secs(1));
512
513 // We dropped the remote handle, so we should not receive the death
514 // notification when the remote process dies here.
515 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000516 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700517 "Received unexpected death notification after dropping remote handle"
518 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000519
520 bools.assert_not_dropped();
521 drop(recipient);
522 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700523 }
524
525 /// Test IBinder interface methods not exercised elsewhere.
526 #[test]
527 fn test_misc_ibinder() {
528 let service_name = "rust_test_ibinder";
529
530 {
531 let _process = ScopedServiceProcess::new(service_name);
532
Stephen Crane2a3297f2021-06-11 16:48:10 -0700533 let test_client: Strong<dyn ITest> =
534 binder::get_interface(service_name)
535 .expect("Did not get test binder service");
536 let mut remote = test_client.as_binder();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700537 assert!(remote.is_binder_alive());
538 remote.ping_binder().expect("Could not ping remote service");
539
Stephen Crane2a3297f2021-06-11 16:48:10 -0700540 let dump_args = ["dump", "args", "for", "testing"];
541
Stephen Crane2a3c2502020-06-16 17:48:35 -0700542 let null_out = File::open("/dev/null").expect("Could not open /dev/null");
543 remote
Stephen Crane2a3297f2021-06-11 16:48:10 -0700544 .dump(&null_out, &dump_args)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700545 .expect("Could not dump remote service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700546
547 let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
548 assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
Stephen Crane2a3c2502020-06-16 17:48:35 -0700549 }
550
551 // get/set_extensions is tested in test_extensions()
552
553 // transact is tested everywhere else, and we can't make raw
554 // transactions outside the [FIRST_CALL_TRANSACTION,
555 // LAST_CALL_TRANSACTION] range from the NDK anyway.
556
557 // link_to_death is tested in test_*_death_notification* tests.
558 }
559
560 #[test]
561 fn test_extensions() {
562 let service_name = "rust_test_extensions";
563 let extension_name = "rust_test_extensions_ext";
564
565 {
566 let _process = ScopedServiceProcess::new(service_name);
567
568 let mut remote = binder::get_service(service_name);
569 assert!(remote.is_binder_alive());
570
571 let extension = remote
572 .get_extension()
573 .expect("Could not check for an extension");
574 assert!(extension.is_none());
575 }
576
577 {
578 let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
579
580 let mut remote = binder::get_service(service_name);
581 assert!(remote.is_binder_alive());
582
583 let maybe_extension = remote
584 .get_extension()
585 .expect("Could not check for an extension");
586
587 let extension = maybe_extension.expect("Remote binder did not have an extension");
588
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800589 let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700590 .expect("Extension could not be converted to the expected interface");
591
592 assert_eq!(extension.test().unwrap(), extension_name);
593 }
594 }
Stephen Crane669deb62020-09-10 17:31:39 -0700595
596 /// Test re-associating a local binder object with a different class.
597 ///
598 /// This is needed because different binder service (e.g. NDK vs Rust)
599 /// implementations are incompatible and must not be interchanged. A local
600 /// service with the same descriptor string but a different class pointer
601 /// may have been created by an NDK service and is therefore incompatible
602 /// with the Rust service implementation. It must be treated as remote and
603 /// all API calls parceled and sent through transactions.
604 ///
605 /// Further tests of this behavior with the C NDK and Rust API are in
606 /// rust_ndk_interop.rs
607 #[test]
608 fn associate_existing_class() {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700609 let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
Stephen Crane669deb62020-09-10 17:31:39 -0700610
611 // This should succeed although we will have to treat the service as
612 // remote.
Andrew Walbran12400d82021-03-04 17:04:34 +0000613 let _interface: Strong<dyn ITestSameDescriptor> =
614 FromIBinder::try_from(service.as_binder())
615 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
Stephen Crane669deb62020-09-10 17:31:39 -0700616 }
617
618 /// Test that we can round-trip a rust service through a generic IBinder
619 #[test]
620 fn reassociate_rust_binder() {
621 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000622 let service_ibinder = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700623 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000624 BinderFeatures::default(),
625 )
Andrew Walbran12400d82021-03-04 17:04:34 +0000626 .as_binder();
Stephen Crane669deb62020-09-10 17:31:39 -0700627
Andrew Walbran12400d82021-03-04 17:04:34 +0000628 let service: Strong<dyn ITest> = service_ibinder
629 .into_interface()
Stephen Crane669deb62020-09-10 17:31:39 -0700630 .expect("Could not reassociate the generic ibinder");
631
632 assert_eq!(service.test().unwrap(), service_name);
633 }
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800634
635 #[test]
636 fn weak_binder_upgrade() {
637 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000638 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700639 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000640 BinderFeatures::default(),
641 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800642
643 let weak = Strong::downgrade(&service);
644
645 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
646
647 assert_eq!(service, upgraded);
648 }
649
650 #[test]
651 fn weak_binder_upgrade_dead() {
652 let service_name = "testing_service";
653 let weak = {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000654 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700655 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000656 BinderFeatures::default(),
657 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800658
659 Strong::downgrade(&service)
660 };
661
662 assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
663 }
664
665 #[test]
666 fn weak_binder_clone() {
667 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000668 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700669 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000670 BinderFeatures::default(),
671 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800672
673 let weak = Strong::downgrade(&service);
674 let cloned = weak.clone();
675 assert_eq!(weak, cloned);
676
677 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
678 let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
679
680 assert_eq!(service, upgraded);
681 assert_eq!(service, clone_upgraded);
682 }
683
684 #[test]
685 #[allow(clippy::eq_op)]
686 fn binder_ord() {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000687 let service1 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700688 TestService::new("testing_service1"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000689 BinderFeatures::default(),
690 );
691 let service2 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700692 TestService::new("testing_service2"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000693 BinderFeatures::default(),
694 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800695
696 assert!(!(service1 < service1));
697 assert!(!(service1 > service1));
698 assert_eq!(service1 < service2, !(service2 < service1));
699 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700700}