blob: f8bc5acd4fd52e77f38421dc3fee6a5e29a86762 [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
Stephen Crane7bca1052021-10-25 17:52:51 -070019use binder::{declare_binder_enum, declare_binder_interface};
Alice Ryhl8618c482021-11-09 15:35:35 +000020use binder::parcel::BorrowedParcel;
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,
Alice Ryhl8618c482021-11-09 15:35:35 +0000182 _data: &BorrowedParcel<'_>,
183 reply: &mut BorrowedParcel<'_>,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700184) -> 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(
Alice Ryhl8618c482021-11-09 15:35:35 +0000221 move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())),
222 |reply| async move { reply?.read() }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000223 )
224 }
225
226 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
227 let binder = self.binder.clone();
228 P::spawn(
Alice Ryhl8618c482021-11-09 15:35:35 +0000229 move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())),
230 |reply| async move { reply?.read() }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000231 )
232 }
233
234 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
235 let binder = self.binder.clone();
236 P::spawn(
Alice Ryhl8618c482021-11-09 15:35:35 +0000237 move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())),
238 |reply| async move { reply?.read() }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000239 )
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,
Alice Ryhl8618c482021-11-09 15:35:35 +0000287 _data: &BorrowedParcel<'_>,
288 _reply: &mut BorrowedParcel<'_>,
Stephen Crane669deb62020-09-10 17:31:39 -0700289) -> binder::Result<()> {
290 Ok(())
291}
292
293impl ITestSameDescriptor for BpTestSameDescriptor {}
294
295impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
296
Stephen Crane7bca1052021-10-25 17:52:51 -0700297declare_binder_enum! {
298 TestEnum : [i32; 3] {
299 FOO = 1,
300 BAR = 2,
301 BAZ = 3,
302 }
303}
304
305declare_binder_enum! {
306 #[deprecated(since = "1.0.0")]
307 TestDeprecatedEnum : [i32; 3] {
308 FOO = 1,
309 BAR = 2,
310 BAZ = 3,
311 }
312}
313
Stephen Crane2a3c2502020-06-16 17:48:35 -0700314#[cfg(test)]
315mod tests {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700316 use selinux_bindgen as selinux_sys;
317 use std::ffi::CStr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700318 use std::fs::File;
319 use std::process::{Child, Command};
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700320 use std::ptr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700321 use std::sync::atomic::{AtomicBool, Ordering};
322 use std::sync::Arc;
323 use std::thread;
324 use std::time::Duration;
325
Andrew Walbran12400d82021-03-04 17:04:34 +0000326 use binder::{
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000327 Binder, BinderFeatures, DeathRecipient, FromIBinder, IBinder, IBinderInternal, Interface,
328 SpIBinder, StatusCode, Strong,
Andrew Walbran12400d82021-03-04 17:04:34 +0000329 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700330
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000331 use binder_tokio::Tokio;
332
333 use super::{BnTest, ITest, IATest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
Stephen Crane2a3c2502020-06-16 17:48:35 -0700334
335 pub struct ScopedServiceProcess(Child);
336
337 impl ScopedServiceProcess {
338 pub fn new(identifier: &str) -> Self {
339 Self::new_internal(identifier, None)
340 }
341
342 pub fn new_with_extension(identifier: &str, extension: &str) -> Self {
343 Self::new_internal(identifier, Some(extension))
344 }
345
346 fn new_internal(identifier: &str, extension: Option<&str>) -> Self {
347 let mut binary_path =
348 std::env::current_exe().expect("Could not retrieve current executable path");
349 binary_path.pop();
350 binary_path.push(RUST_SERVICE_BINARY);
351 let mut command = Command::new(&binary_path);
352 command.arg(identifier);
353 if let Some(ext) = extension {
354 command.arg(ext);
355 }
356 let child = command.spawn().expect("Could not start service");
357 Self(child)
358 }
359 }
360
361 impl Drop for ScopedServiceProcess {
362 fn drop(&mut self) {
363 self.0.kill().expect("Could not kill child process");
364 self.0
365 .wait()
366 .expect("Could not wait for child process to die");
367 }
368 }
369
370 #[test]
371 fn check_services() {
372 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
373 assert!(sm.is_binder_alive());
374 assert!(sm.ping_binder().is_ok());
375
376 assert!(binder::get_service("this_service_does_not_exist").is_none());
377 assert_eq!(
378 binder::get_interface::<dyn ITest>("this_service_does_not_exist").err(),
379 Some(StatusCode::NAME_NOT_FOUND)
380 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000381 assert_eq!(
382 binder::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
383 Some(StatusCode::NAME_NOT_FOUND)
384 );
Stephen Crane2a3c2502020-06-16 17:48:35 -0700385
386 // The service manager service isn't an ITest, so this must fail.
387 assert_eq!(
388 binder::get_interface::<dyn ITest>("manager").err(),
389 Some(StatusCode::BAD_TYPE)
390 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000391 assert_eq!(
392 binder::get_interface::<dyn IATest<Tokio>>("manager").err(),
393 Some(StatusCode::BAD_TYPE)
394 );
Stephen Crane2a3c2502020-06-16 17:48:35 -0700395 }
396
Alice Ryhl929804f2021-11-02 12:04:39 +0000397 #[tokio::test]
398 async fn check_services_async() {
399 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
400 assert!(sm.is_binder_alive());
401 assert!(sm.ping_binder().is_ok());
402
403 assert!(binder::get_service("this_service_does_not_exist").is_none());
404 assert_eq!(
405 binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
406 Some(StatusCode::NAME_NOT_FOUND)
407 );
408 assert_eq!(
409 binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").await.err(),
410 Some(StatusCode::NAME_NOT_FOUND)
411 );
412
413 // The service manager service isn't an ITest, so this must fail.
414 assert_eq!(
415 binder_tokio::get_interface::<dyn ITest>("manager").await.err(),
416 Some(StatusCode::BAD_TYPE)
417 );
418 assert_eq!(
419 binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(),
420 Some(StatusCode::BAD_TYPE)
421 );
422 }
423
Stephen Crane2a3c2502020-06-16 17:48:35 -0700424 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000425 fn check_wait_for_service() {
426 let mut sm =
427 binder::wait_for_service("manager").expect("Did not get manager binder service");
428 assert!(sm.is_binder_alive());
429 assert!(sm.ping_binder().is_ok());
430
431 // The service manager service isn't an ITest, so this must fail.
432 assert_eq!(
433 binder::wait_for_interface::<dyn ITest>("manager").err(),
434 Some(StatusCode::BAD_TYPE)
435 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000436 assert_eq!(
437 binder::wait_for_interface::<dyn IATest<Tokio>>("manager").err(),
438 Some(StatusCode::BAD_TYPE)
439 );
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000440 }
441
442 #[test]
Stephen Crane2a3c2502020-06-16 17:48:35 -0700443 fn trivial_client() {
444 let service_name = "trivial_client_test";
445 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800446 let test_client: Strong<dyn ITest> =
Stephen Crane2a3c2502020-06-16 17:48:35 -0700447 binder::get_interface(service_name).expect("Did not get manager binder service");
448 assert_eq!(test_client.test().unwrap(), "trivial_client_test");
449 }
450
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000451 #[tokio::test]
452 async fn trivial_client_async() {
453 let service_name = "trivial_client_test";
454 let _process = ScopedServiceProcess::new(service_name);
455 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000456 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000457 assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
458 }
459
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700460 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000461 fn wait_for_trivial_client() {
462 let service_name = "wait_for_trivial_client_test";
463 let _process = ScopedServiceProcess::new(service_name);
464 let test_client: Strong<dyn ITest> =
465 binder::wait_for_interface(service_name).expect("Did not get manager binder service");
466 assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
467 }
468
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000469 #[tokio::test]
470 async fn wait_for_trivial_client_async() {
471 let service_name = "wait_for_trivial_client_test";
472 let _process = ScopedServiceProcess::new(service_name);
473 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000474 binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000475 assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
476 }
477
478 fn get_expected_selinux_context() -> &'static str {
479 unsafe {
480 let mut out_ptr = ptr::null_mut();
481 assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
482 assert!(!out_ptr.is_null());
483 CStr::from_ptr(out_ptr)
484 .to_str()
485 .expect("context was invalid UTF-8")
486 }
487 }
488
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000489 #[test]
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700490 fn get_selinux_context() {
491 let service_name = "get_selinux_context";
492 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800493 let test_client: Strong<dyn ITest> =
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700494 binder::get_interface(service_name).expect("Did not get manager binder service");
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700495 assert_eq!(
496 test_client.get_selinux_context().unwrap(),
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000497 get_expected_selinux_context()
498 );
499 }
500
501 #[tokio::test]
502 async fn get_selinux_context_async() {
503 let service_name = "get_selinux_context";
504 let _process = ScopedServiceProcess::new(service_name);
505 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000506 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000507 assert_eq!(
508 test_client.get_selinux_context().await.unwrap(),
509 get_expected_selinux_context()
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700510 );
511 }
512
Alice Ryhlc1736842021-11-23 12:38:51 +0000513 #[tokio::test]
514 async fn get_selinux_context_sync_to_async() {
515 let service_name = "get_selinux_context";
516 let _process = ScopedServiceProcess::new(service_name);
517 let test_client: Strong<dyn ITest> =
518 binder::get_interface(service_name).expect("Did not get manager binder service");
519 let test_client = test_client.into_async::<Tokio>();
520 assert_eq!(
521 test_client.get_selinux_context().await.unwrap(),
522 get_expected_selinux_context()
523 );
524 }
525
526 #[tokio::test]
527 async fn get_selinux_context_async_to_sync() {
528 let service_name = "get_selinux_context";
529 let _process = ScopedServiceProcess::new(service_name);
530 let test_client: Strong<dyn IATest<Tokio>> =
531 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
532 let test_client = test_client.into_sync();
533 assert_eq!(
534 test_client.get_selinux_context().unwrap(),
535 get_expected_selinux_context()
536 );
537 }
538
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000539 struct Bools {
540 binder_died: Arc<AtomicBool>,
541 binder_dealloc: Arc<AtomicBool>,
542 }
543
544 impl Bools {
545 fn is_dead(&self) -> bool {
546 self.binder_died.load(Ordering::Relaxed)
547 }
548 fn assert_died(&self) {
549 assert!(
550 self.is_dead(),
551 "Did not receive death notification"
552 );
553 }
554 fn assert_dropped(&self) {
555 assert!(
556 self.binder_dealloc.load(Ordering::Relaxed),
557 "Did not dealloc death notification"
558 );
559 }
560 fn assert_not_dropped(&self) {
561 assert!(
562 !self.binder_dealloc.load(Ordering::Relaxed),
563 "Dealloc death notification too early"
564 );
565 }
566 }
567
568 fn register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient) {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700569 let binder_died = Arc::new(AtomicBool::new(false));
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000570 let binder_dealloc = Arc::new(AtomicBool::new(false));
571
572 struct SetOnDrop {
573 binder_dealloc: Arc<AtomicBool>,
574 }
575 impl Drop for SetOnDrop {
576 fn drop(&mut self) {
577 self.binder_dealloc.store(true, Ordering::Relaxed);
578 }
579 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700580
581 let mut death_recipient = {
582 let flag = binder_died.clone();
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000583 let set_on_drop = SetOnDrop {
584 binder_dealloc: binder_dealloc.clone(),
585 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700586 DeathRecipient::new(move || {
587 flag.store(true, Ordering::Relaxed);
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000588 // Force the closure to take ownership of set_on_drop. When the closure is
589 // dropped, the destructor of `set_on_drop` will run.
590 let _ = &set_on_drop;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700591 })
592 };
593
594 binder
595 .link_to_death(&mut death_recipient)
596 .expect("link_to_death failed");
597
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000598 let bools = Bools {
599 binder_died,
600 binder_dealloc,
601 };
602
603 (bools, death_recipient)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700604 }
605
606 /// Killing a remote service should unregister the service and trigger
607 /// death notifications.
608 #[test]
609 fn test_death_notifications() {
610 binder::ProcessState::start_thread_pool();
611
612 let service_name = "test_death_notifications";
613 let service_process = ScopedServiceProcess::new(service_name);
614 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
615
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000616 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700617
618 drop(service_process);
619 remote
620 .ping_binder()
621 .expect_err("Service should have died already");
622
623 // Pause to ensure any death notifications get delivered
624 thread::sleep(Duration::from_secs(1));
625
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000626 bools.assert_died();
627 bools.assert_not_dropped();
628
629 drop(recipient);
630
631 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700632 }
633
634 /// Test unregistering death notifications.
635 #[test]
636 fn test_unregister_death_notifications() {
637 binder::ProcessState::start_thread_pool();
638
639 let service_name = "test_unregister_death_notifications";
640 let service_process = ScopedServiceProcess::new(service_name);
641 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
642
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000643 let (bools, mut recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700644
645 remote
646 .unlink_to_death(&mut recipient)
647 .expect("Could not unlink death notifications");
648
649 drop(service_process);
650 remote
651 .ping_binder()
652 .expect_err("Service should have died already");
653
654 // Pause to ensure any death notifications get delivered
655 thread::sleep(Duration::from_secs(1));
656
657 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000658 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700659 "Received unexpected death notification after unlinking",
660 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000661
662 bools.assert_not_dropped();
663 drop(recipient);
664 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700665 }
666
667 /// Dropping a remote handle should unregister any death notifications.
668 #[test]
669 fn test_death_notification_registration_lifetime() {
670 binder::ProcessState::start_thread_pool();
671
672 let service_name = "test_death_notification_registration_lifetime";
673 let service_process = ScopedServiceProcess::new(service_name);
674 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
675
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000676 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700677
678 // This should automatically unregister our death notification.
679 drop(remote);
680
681 drop(service_process);
682
683 // Pause to ensure any death notifications get delivered
684 thread::sleep(Duration::from_secs(1));
685
686 // We dropped the remote handle, so we should not receive the death
687 // notification when the remote process dies here.
688 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000689 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700690 "Received unexpected death notification after dropping remote handle"
691 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000692
693 bools.assert_not_dropped();
694 drop(recipient);
695 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700696 }
697
698 /// Test IBinder interface methods not exercised elsewhere.
699 #[test]
700 fn test_misc_ibinder() {
701 let service_name = "rust_test_ibinder";
702
703 {
704 let _process = ScopedServiceProcess::new(service_name);
705
Stephen Crane2a3297f2021-06-11 16:48:10 -0700706 let test_client: Strong<dyn ITest> =
707 binder::get_interface(service_name)
708 .expect("Did not get test binder service");
709 let mut remote = test_client.as_binder();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700710 assert!(remote.is_binder_alive());
711 remote.ping_binder().expect("Could not ping remote service");
712
Stephen Crane2a3297f2021-06-11 16:48:10 -0700713 let dump_args = ["dump", "args", "for", "testing"];
714
Stephen Crane2a3c2502020-06-16 17:48:35 -0700715 let null_out = File::open("/dev/null").expect("Could not open /dev/null");
716 remote
Stephen Crane2a3297f2021-06-11 16:48:10 -0700717 .dump(&null_out, &dump_args)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700718 .expect("Could not dump remote service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700719
720 let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
721 assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
Stephen Crane2a3c2502020-06-16 17:48:35 -0700722 }
723
724 // get/set_extensions is tested in test_extensions()
725
726 // transact is tested everywhere else, and we can't make raw
727 // transactions outside the [FIRST_CALL_TRANSACTION,
728 // LAST_CALL_TRANSACTION] range from the NDK anyway.
729
730 // link_to_death is tested in test_*_death_notification* tests.
731 }
732
733 #[test]
734 fn test_extensions() {
735 let service_name = "rust_test_extensions";
736 let extension_name = "rust_test_extensions_ext";
737
738 {
739 let _process = ScopedServiceProcess::new(service_name);
740
741 let mut remote = binder::get_service(service_name);
742 assert!(remote.is_binder_alive());
743
744 let extension = remote
745 .get_extension()
746 .expect("Could not check for an extension");
747 assert!(extension.is_none());
748 }
749
750 {
751 let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
752
753 let mut remote = binder::get_service(service_name);
754 assert!(remote.is_binder_alive());
755
756 let maybe_extension = remote
757 .get_extension()
758 .expect("Could not check for an extension");
759
760 let extension = maybe_extension.expect("Remote binder did not have an extension");
761
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800762 let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700763 .expect("Extension could not be converted to the expected interface");
764
765 assert_eq!(extension.test().unwrap(), extension_name);
766 }
767 }
Stephen Crane669deb62020-09-10 17:31:39 -0700768
769 /// Test re-associating a local binder object with a different class.
770 ///
771 /// This is needed because different binder service (e.g. NDK vs Rust)
772 /// implementations are incompatible and must not be interchanged. A local
773 /// service with the same descriptor string but a different class pointer
774 /// may have been created by an NDK service and is therefore incompatible
775 /// with the Rust service implementation. It must be treated as remote and
776 /// all API calls parceled and sent through transactions.
777 ///
778 /// Further tests of this behavior with the C NDK and Rust API are in
779 /// rust_ndk_interop.rs
780 #[test]
781 fn associate_existing_class() {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700782 let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
Stephen Crane669deb62020-09-10 17:31:39 -0700783
784 // This should succeed although we will have to treat the service as
785 // remote.
Andrew Walbran12400d82021-03-04 17:04:34 +0000786 let _interface: Strong<dyn ITestSameDescriptor> =
787 FromIBinder::try_from(service.as_binder())
788 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
Stephen Crane669deb62020-09-10 17:31:39 -0700789 }
790
791 /// Test that we can round-trip a rust service through a generic IBinder
792 #[test]
793 fn reassociate_rust_binder() {
794 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000795 let service_ibinder = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700796 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000797 BinderFeatures::default(),
798 )
Andrew Walbran12400d82021-03-04 17:04:34 +0000799 .as_binder();
Stephen Crane669deb62020-09-10 17:31:39 -0700800
Andrew Walbran12400d82021-03-04 17:04:34 +0000801 let service: Strong<dyn ITest> = service_ibinder
802 .into_interface()
Stephen Crane669deb62020-09-10 17:31:39 -0700803 .expect("Could not reassociate the generic ibinder");
804
805 assert_eq!(service.test().unwrap(), service_name);
806 }
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800807
808 #[test]
809 fn weak_binder_upgrade() {
810 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000811 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700812 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000813 BinderFeatures::default(),
814 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800815
816 let weak = Strong::downgrade(&service);
817
818 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
819
820 assert_eq!(service, upgraded);
821 }
822
823 #[test]
824 fn weak_binder_upgrade_dead() {
825 let service_name = "testing_service";
826 let weak = {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000827 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700828 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000829 BinderFeatures::default(),
830 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800831
832 Strong::downgrade(&service)
833 };
834
835 assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
836 }
837
838 #[test]
839 fn weak_binder_clone() {
840 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000841 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700842 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000843 BinderFeatures::default(),
844 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800845
846 let weak = Strong::downgrade(&service);
847 let cloned = weak.clone();
848 assert_eq!(weak, cloned);
849
850 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
851 let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
852
853 assert_eq!(service, upgraded);
854 assert_eq!(service, clone_upgraded);
855 }
856
857 #[test]
858 #[allow(clippy::eq_op)]
859 fn binder_ord() {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000860 let service1 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700861 TestService::new("testing_service1"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000862 BinderFeatures::default(),
863 );
864 let service2 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700865 TestService::new("testing_service2"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000866 BinderFeatures::default(),
867 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800868
869 assert!(!(service1 < service1));
870 assert!(!(service1 > service1));
871 assert_eq!(service1 < service2, !(service2 < service1));
872 }
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000873
874 #[test]
875 fn binder_parcel_mixup() {
876 let service1 = BnTest::new_binder(
877 TestService::new("testing_service1"),
878 BinderFeatures::default(),
879 );
880 let service2 = BnTest::new_binder(
881 TestService::new("testing_service2"),
882 BinderFeatures::default(),
883 );
884
885 let service1 = service1.as_binder();
886 let service2 = service2.as_binder();
887
888 let parcel = service1.prepare_transact().unwrap();
889 let res = service2.submit_transact(super::TestTransactionCode::Test as binder::TransactionCode, parcel, 0);
890
891 match res {
892 Ok(_) => panic!("submit_transact should fail"),
893 Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
894 }
895 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700896}