blob: 777bd6ba2c02f2ef83e2ecc5dcf19114e1884532 [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
Stephen Crane2a3c2502020-06-16 17:48:35 -0700366 fn register_death_notification(binder: &mut SpIBinder) -> (Arc<AtomicBool>, DeathRecipient) {
367 let binder_died = Arc::new(AtomicBool::new(false));
368
369 let mut death_recipient = {
370 let flag = binder_died.clone();
371 DeathRecipient::new(move || {
372 flag.store(true, Ordering::Relaxed);
373 })
374 };
375
376 binder
377 .link_to_death(&mut death_recipient)
378 .expect("link_to_death failed");
379
380 (binder_died, death_recipient)
381 }
382
383 /// Killing a remote service should unregister the service and trigger
384 /// death notifications.
385 #[test]
386 fn test_death_notifications() {
387 binder::ProcessState::start_thread_pool();
388
389 let service_name = "test_death_notifications";
390 let service_process = ScopedServiceProcess::new(service_name);
391 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
392
393 let (binder_died, _recipient) = register_death_notification(&mut remote);
394
395 drop(service_process);
396 remote
397 .ping_binder()
398 .expect_err("Service should have died already");
399
400 // Pause to ensure any death notifications get delivered
401 thread::sleep(Duration::from_secs(1));
402
403 assert!(
404 binder_died.load(Ordering::Relaxed),
405 "Did not receive death notification"
406 );
407 }
408
409 /// Test unregistering death notifications.
410 #[test]
411 fn test_unregister_death_notifications() {
412 binder::ProcessState::start_thread_pool();
413
414 let service_name = "test_unregister_death_notifications";
415 let service_process = ScopedServiceProcess::new(service_name);
416 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
417
418 let (binder_died, mut recipient) = register_death_notification(&mut remote);
419
420 remote
421 .unlink_to_death(&mut recipient)
422 .expect("Could not unlink death notifications");
423
424 drop(service_process);
425 remote
426 .ping_binder()
427 .expect_err("Service should have died already");
428
429 // Pause to ensure any death notifications get delivered
430 thread::sleep(Duration::from_secs(1));
431
432 assert!(
433 !binder_died.load(Ordering::Relaxed),
434 "Received unexpected death notification after unlinking",
435 );
436 }
437
438 /// Dropping a remote handle should unregister any death notifications.
439 #[test]
440 fn test_death_notification_registration_lifetime() {
441 binder::ProcessState::start_thread_pool();
442
443 let service_name = "test_death_notification_registration_lifetime";
444 let service_process = ScopedServiceProcess::new(service_name);
445 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
446
447 let (binder_died, _recipient) = register_death_notification(&mut remote);
448
449 // This should automatically unregister our death notification.
450 drop(remote);
451
452 drop(service_process);
453
454 // Pause to ensure any death notifications get delivered
455 thread::sleep(Duration::from_secs(1));
456
457 // We dropped the remote handle, so we should not receive the death
458 // notification when the remote process dies here.
459 assert!(
460 !binder_died.load(Ordering::Relaxed),
461 "Received unexpected death notification after dropping remote handle"
462 );
463 }
464
465 /// Test IBinder interface methods not exercised elsewhere.
466 #[test]
467 fn test_misc_ibinder() {
468 let service_name = "rust_test_ibinder";
469
470 {
471 let _process = ScopedServiceProcess::new(service_name);
472
Stephen Crane2a3297f2021-06-11 16:48:10 -0700473 let test_client: Strong<dyn ITest> =
474 binder::get_interface(service_name)
475 .expect("Did not get test binder service");
476 let mut remote = test_client.as_binder();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700477 assert!(remote.is_binder_alive());
478 remote.ping_binder().expect("Could not ping remote service");
479
Stephen Crane2a3297f2021-06-11 16:48:10 -0700480 let dump_args = ["dump", "args", "for", "testing"];
481
Stephen Crane2a3c2502020-06-16 17:48:35 -0700482 let null_out = File::open("/dev/null").expect("Could not open /dev/null");
483 remote
Stephen Crane2a3297f2021-06-11 16:48:10 -0700484 .dump(&null_out, &dump_args)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700485 .expect("Could not dump remote service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700486
487 let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
488 assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
Stephen Crane2a3c2502020-06-16 17:48:35 -0700489 }
490
491 // get/set_extensions is tested in test_extensions()
492
493 // transact is tested everywhere else, and we can't make raw
494 // transactions outside the [FIRST_CALL_TRANSACTION,
495 // LAST_CALL_TRANSACTION] range from the NDK anyway.
496
497 // link_to_death is tested in test_*_death_notification* tests.
498 }
499
500 #[test]
501 fn test_extensions() {
502 let service_name = "rust_test_extensions";
503 let extension_name = "rust_test_extensions_ext";
504
505 {
506 let _process = ScopedServiceProcess::new(service_name);
507
508 let mut remote = binder::get_service(service_name);
509 assert!(remote.is_binder_alive());
510
511 let extension = remote
512 .get_extension()
513 .expect("Could not check for an extension");
514 assert!(extension.is_none());
515 }
516
517 {
518 let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
519
520 let mut remote = binder::get_service(service_name);
521 assert!(remote.is_binder_alive());
522
523 let maybe_extension = remote
524 .get_extension()
525 .expect("Could not check for an extension");
526
527 let extension = maybe_extension.expect("Remote binder did not have an extension");
528
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800529 let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700530 .expect("Extension could not be converted to the expected interface");
531
532 assert_eq!(extension.test().unwrap(), extension_name);
533 }
534 }
Stephen Crane669deb62020-09-10 17:31:39 -0700535
536 /// Test re-associating a local binder object with a different class.
537 ///
538 /// This is needed because different binder service (e.g. NDK vs Rust)
539 /// implementations are incompatible and must not be interchanged. A local
540 /// service with the same descriptor string but a different class pointer
541 /// may have been created by an NDK service and is therefore incompatible
542 /// with the Rust service implementation. It must be treated as remote and
543 /// all API calls parceled and sent through transactions.
544 ///
545 /// Further tests of this behavior with the C NDK and Rust API are in
546 /// rust_ndk_interop.rs
547 #[test]
548 fn associate_existing_class() {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700549 let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
Stephen Crane669deb62020-09-10 17:31:39 -0700550
551 // This should succeed although we will have to treat the service as
552 // remote.
Andrew Walbran12400d82021-03-04 17:04:34 +0000553 let _interface: Strong<dyn ITestSameDescriptor> =
554 FromIBinder::try_from(service.as_binder())
555 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
Stephen Crane669deb62020-09-10 17:31:39 -0700556 }
557
558 /// Test that we can round-trip a rust service through a generic IBinder
559 #[test]
560 fn reassociate_rust_binder() {
561 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000562 let service_ibinder = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700563 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000564 BinderFeatures::default(),
565 )
Andrew Walbran12400d82021-03-04 17:04:34 +0000566 .as_binder();
Stephen Crane669deb62020-09-10 17:31:39 -0700567
Andrew Walbran12400d82021-03-04 17:04:34 +0000568 let service: Strong<dyn ITest> = service_ibinder
569 .into_interface()
Stephen Crane669deb62020-09-10 17:31:39 -0700570 .expect("Could not reassociate the generic ibinder");
571
572 assert_eq!(service.test().unwrap(), service_name);
573 }
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800574
575 #[test]
576 fn weak_binder_upgrade() {
577 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000578 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700579 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000580 BinderFeatures::default(),
581 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800582
583 let weak = Strong::downgrade(&service);
584
585 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
586
587 assert_eq!(service, upgraded);
588 }
589
590 #[test]
591 fn weak_binder_upgrade_dead() {
592 let service_name = "testing_service";
593 let weak = {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000594 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700595 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000596 BinderFeatures::default(),
597 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800598
599 Strong::downgrade(&service)
600 };
601
602 assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
603 }
604
605 #[test]
606 fn weak_binder_clone() {
607 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000608 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700609 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000610 BinderFeatures::default(),
611 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800612
613 let weak = Strong::downgrade(&service);
614 let cloned = weak.clone();
615 assert_eq!(weak, cloned);
616
617 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
618 let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
619
620 assert_eq!(service, upgraded);
621 assert_eq!(service, clone_upgraded);
622 }
623
624 #[test]
625 #[allow(clippy::eq_op)]
626 fn binder_ord() {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000627 let service1 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700628 TestService::new("testing_service1"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000629 BinderFeatures::default(),
630 );
631 let service2 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700632 TestService::new("testing_service2"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000633 BinderFeatures::default(),
634 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800635
636 assert!(!(service1 < service1));
637 assert!(!(service1 > service1));
638 assert_eq!(service1 < service2, !(service2 < service1));
639 }
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000640
641 #[test]
642 fn binder_parcel_mixup() {
643 let service1 = BnTest::new_binder(
644 TestService::new("testing_service1"),
645 BinderFeatures::default(),
646 );
647 let service2 = BnTest::new_binder(
648 TestService::new("testing_service2"),
649 BinderFeatures::default(),
650 );
651
652 let service1 = service1.as_binder();
653 let service2 = service2.as_binder();
654
655 let parcel = service1.prepare_transact().unwrap();
656 let res = service2.submit_transact(super::TestTransactionCode::Test as binder::TransactionCode, parcel, 0);
657
658 match res {
659 Ok(_) => panic!("submit_transact should fail"),
660 Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
661 }
662 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700663}