blob: 80dc47682c3fa5c0379b8b5b9de261374b611eab [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};
Stephen Crane214307b2022-01-19 00:05:11 +000020use binder::parcel::BorrowedParcel;
21use binder::{
22 Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
23 FIRST_CALL_TRANSACTION,
Andrew Walbran12400d82021-03-04 17:04:34 +000024};
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,
Alice Ryhl29a50262021-12-10 11:14:32 +0000103 GetIsHandlingTransaction,
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700104}
105
106impl TryFrom<u32> for TestTransactionCode {
107 type Error = StatusCode;
108
109 fn try_from(c: u32) -> Result<Self, Self::Error> {
110 match c {
111 _ if c == TestTransactionCode::Test as u32 => Ok(TestTransactionCode::Test),
Stephen Crane2a3297f2021-06-11 16:48:10 -0700112 _ if c == TestTransactionCode::GetDumpArgs as u32 => Ok(TestTransactionCode::GetDumpArgs),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700113 _ if c == TestTransactionCode::GetSelinuxContext as u32 => {
114 Ok(TestTransactionCode::GetSelinuxContext)
115 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000116 _ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => Ok(TestTransactionCode::GetIsHandlingTransaction),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700117 _ => Err(StatusCode::UNKNOWN_TRANSACTION),
118 }
119 }
120}
121
Stephen Crane2a3297f2021-06-11 16:48:10 -0700122impl Interface for TestService {
Stephen Crane214307b2022-01-19 00:05:11 +0000123 fn dump(&self, _file: &File, args: &[&CStr]) -> binder::Result<()> {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700124 let mut dump_args = self.dump_args.lock().unwrap();
125 dump_args.extend(args.iter().map(|s| s.to_str().unwrap().to_owned()));
126 Ok(())
127 }
128}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700129
130impl ITest for TestService {
Stephen Crane214307b2022-01-19 00:05:11 +0000131 fn test(&self) -> binder::Result<String> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700132 Ok(self.s.clone())
133 }
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700134
Stephen Crane214307b2022-01-19 00:05:11 +0000135 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700136 let args = self.dump_args.lock().unwrap().clone();
137 Ok(args)
138 }
139
Stephen Crane214307b2022-01-19 00:05:11 +0000140 fn get_selinux_context(&self) -> binder::Result<String> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700141 let sid =
142 ThreadState::with_calling_sid(|sid| sid.map(|s| s.to_string_lossy().into_owned()));
143 sid.ok_or(StatusCode::UNEXPECTED_NULL)
144 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000145
Stephen Crane214307b2022-01-19 00:05:11 +0000146 fn get_is_handling_transaction(&self) -> binder::Result<bool> {
Alice Ryhl29a50262021-12-10 11:14:32 +0000147 Ok(binder::is_handling_transaction())
148 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700149}
150
151/// Trivial testing binder interface
152pub trait ITest: Interface {
153 /// Returns a test string
Stephen Crane214307b2022-01-19 00:05:11 +0000154 fn test(&self) -> binder::Result<String>;
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700155
Stephen Crane2a3297f2021-06-11 16:48:10 -0700156 /// Return the arguments sent via dump
Stephen Crane214307b2022-01-19 00:05:11 +0000157 fn get_dump_args(&self) -> binder::Result<Vec<String>>;
Stephen Crane2a3297f2021-06-11 16:48:10 -0700158
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700159 /// Returns the caller's SELinux context
Stephen Crane214307b2022-01-19 00:05:11 +0000160 fn get_selinux_context(&self) -> binder::Result<String>;
Alice Ryhl29a50262021-12-10 11:14:32 +0000161
162 /// Returns the value of calling `is_handling_transaction`.
Stephen Crane214307b2022-01-19 00:05:11 +0000163 fn get_is_handling_transaction(&self) -> binder::Result<bool>;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700164}
165
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000166/// Async trivial testing binder interface
167pub trait IATest<P>: Interface {
168 /// Returns a test string
Stephen Crane214307b2022-01-19 00:05:11 +0000169 fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000170
171 /// Return the arguments sent via dump
Stephen Crane214307b2022-01-19 00:05:11 +0000172 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>>;
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000173
174 /// Returns the caller's SELinux context
Stephen Crane214307b2022-01-19 00:05:11 +0000175 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
Alice Ryhl29a50262021-12-10 11:14:32 +0000176
177 /// Returns the value of calling `is_handling_transaction`.
Stephen Crane214307b2022-01-19 00:05:11 +0000178 fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>>;
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000179}
180
Stephen Crane2a3c2502020-06-16 17:48:35 -0700181declare_binder_interface! {
182 ITest["android.os.ITest"] {
183 native: BnTest(on_transact),
184 proxy: BpTest {
185 x: i32 = 100
186 },
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000187 async: IATest,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700188 }
189}
190
191fn on_transact(
192 service: &dyn ITest,
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700193 code: TransactionCode,
Alice Ryhl8618c482021-11-09 15:35:35 +0000194 _data: &BorrowedParcel<'_>,
195 reply: &mut BorrowedParcel<'_>,
Stephen Crane214307b2022-01-19 00:05:11 +0000196) -> binder::Result<()> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700197 match code.try_into()? {
198 TestTransactionCode::Test => reply.write(&service.test()?),
Stephen Crane2a3297f2021-06-11 16:48:10 -0700199 TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700200 TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
Alice Ryhl29a50262021-12-10 11:14:32 +0000201 TestTransactionCode::GetIsHandlingTransaction => reply.write(&service.get_is_handling_transaction()?),
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700202 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700203}
204
205impl ITest for BpTest {
Stephen Crane214307b2022-01-19 00:05:11 +0000206 fn test(&self) -> binder::Result<String> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700207 let reply =
208 self.binder
209 .transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(()))?;
210 reply.read()
211 }
212
Stephen Crane214307b2022-01-19 00:05:11 +0000213 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700214 let reply =
215 self.binder
216 .transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(()))?;
217 reply.read()
218 }
219
Stephen Crane214307b2022-01-19 00:05:11 +0000220 fn get_selinux_context(&self) -> binder::Result<String> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700221 let reply = self.binder.transact(
222 TestTransactionCode::GetSelinuxContext as TransactionCode,
223 0,
224 |_| Ok(()),
225 )?;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700226 reply.read()
227 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000228
Stephen Crane214307b2022-01-19 00:05:11 +0000229 fn get_is_handling_transaction(&self) -> binder::Result<bool> {
Alice Ryhl29a50262021-12-10 11:14:32 +0000230 let reply = self.binder.transact(
231 TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
232 0,
233 |_| Ok(()),
234 )?;
235 reply.read()
236 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700237}
238
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000239impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
Stephen Crane214307b2022-01-19 00:05:11 +0000240 fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000241 let binder = self.binder.clone();
242 P::spawn(
Alice Ryhl8618c482021-11-09 15:35:35 +0000243 move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())),
244 |reply| async move { reply?.read() }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000245 )
246 }
247
Stephen Crane214307b2022-01-19 00:05:11 +0000248 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000249 let binder = self.binder.clone();
250 P::spawn(
Alice Ryhl8618c482021-11-09 15:35:35 +0000251 move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())),
252 |reply| async move { reply?.read() }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000253 )
254 }
255
Stephen Crane214307b2022-01-19 00:05:11 +0000256 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000257 let binder = self.binder.clone();
258 P::spawn(
Alice Ryhl8618c482021-11-09 15:35:35 +0000259 move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())),
260 |reply| async move { reply?.read() }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000261 )
262 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000263
Stephen Crane214307b2022-01-19 00:05:11 +0000264 fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
Alice Ryhl29a50262021-12-10 11:14:32 +0000265 let binder = self.binder.clone();
266 P::spawn(
267 move || binder.transact(TestTransactionCode::GetIsHandlingTransaction as TransactionCode, 0, |_| Ok(())),
268 |reply| async move { reply?.read() }
269 )
270 }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000271}
272
Stephen Crane2a3c2502020-06-16 17:48:35 -0700273impl ITest for Binder<BnTest> {
Stephen Crane214307b2022-01-19 00:05:11 +0000274 fn test(&self) -> binder::Result<String> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700275 self.0.test()
276 }
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700277
Stephen Crane214307b2022-01-19 00:05:11 +0000278 fn get_dump_args(&self) -> binder::Result<Vec<String>> {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700279 self.0.get_dump_args()
280 }
281
Stephen Crane214307b2022-01-19 00:05:11 +0000282 fn get_selinux_context(&self) -> binder::Result<String> {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700283 self.0.get_selinux_context()
284 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000285
Stephen Crane214307b2022-01-19 00:05:11 +0000286 fn get_is_handling_transaction(&self) -> binder::Result<bool> {
Alice Ryhl29a50262021-12-10 11:14:32 +0000287 self.0.get_is_handling_transaction()
288 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700289}
290
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000291impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
Stephen Crane214307b2022-01-19 00:05:11 +0000292 fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000293 let res = self.0.test();
294 Box::pin(async move { res })
295 }
296
Stephen Crane214307b2022-01-19 00:05:11 +0000297 fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000298 let res = self.0.get_dump_args();
299 Box::pin(async move { res })
300 }
301
Stephen Crane214307b2022-01-19 00:05:11 +0000302 fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000303 let res = self.0.get_selinux_context();
304 Box::pin(async move { res })
305 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000306
Stephen Crane214307b2022-01-19 00:05:11 +0000307 fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
Alice Ryhl29a50262021-12-10 11:14:32 +0000308 let res = self.0.get_is_handling_transaction();
309 Box::pin(async move { res })
310 }
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000311}
312
Stephen Crane669deb62020-09-10 17:31:39 -0700313/// Trivial testing binder interface
314pub trait ITestSameDescriptor: Interface {}
315
316declare_binder_interface! {
317 ITestSameDescriptor["android.os.ITest"] {
318 native: BnTestSameDescriptor(on_transact_same_descriptor),
319 proxy: BpTestSameDescriptor,
320 }
321}
322
323fn on_transact_same_descriptor(
324 _service: &dyn ITestSameDescriptor,
325 _code: TransactionCode,
Alice Ryhl8618c482021-11-09 15:35:35 +0000326 _data: &BorrowedParcel<'_>,
327 _reply: &mut BorrowedParcel<'_>,
Stephen Crane214307b2022-01-19 00:05:11 +0000328) -> binder::Result<()> {
Stephen Crane669deb62020-09-10 17:31:39 -0700329 Ok(())
330}
331
332impl ITestSameDescriptor for BpTestSameDescriptor {}
333
334impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
335
Stephen Crane7bca1052021-10-25 17:52:51 -0700336declare_binder_enum! {
337 TestEnum : [i32; 3] {
338 FOO = 1,
339 BAR = 2,
340 BAZ = 3,
341 }
342}
343
344declare_binder_enum! {
345 #[deprecated(since = "1.0.0")]
346 TestDeprecatedEnum : [i32; 3] {
347 FOO = 1,
348 BAR = 2,
349 BAZ = 3,
350 }
351}
352
Stephen Crane2a3c2502020-06-16 17:48:35 -0700353#[cfg(test)]
354mod tests {
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700355 use selinux_bindgen as selinux_sys;
356 use std::ffi::CStr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700357 use std::fs::File;
358 use std::process::{Child, Command};
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700359 use std::ptr;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700360 use std::sync::atomic::{AtomicBool, Ordering};
361 use std::sync::Arc;
362 use std::thread;
363 use std::time::Duration;
364
Andrew Walbran12400d82021-03-04 17:04:34 +0000365 use binder::{
Stephen Crane214307b2022-01-19 00:05:11 +0000366 Binder, BinderFeatures, DeathRecipient, FromIBinder, IBinder, IBinderInternal, Interface,
367 SpIBinder, StatusCode, Strong,
Andrew Walbran12400d82021-03-04 17:04:34 +0000368 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700369
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000370 use binder_tokio::Tokio;
371
372 use super::{BnTest, ITest, IATest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
Stephen Crane2a3c2502020-06-16 17:48:35 -0700373
374 pub struct ScopedServiceProcess(Child);
375
376 impl ScopedServiceProcess {
377 pub fn new(identifier: &str) -> Self {
378 Self::new_internal(identifier, None)
379 }
380
381 pub fn new_with_extension(identifier: &str, extension: &str) -> Self {
382 Self::new_internal(identifier, Some(extension))
383 }
384
385 fn new_internal(identifier: &str, extension: Option<&str>) -> Self {
386 let mut binary_path =
387 std::env::current_exe().expect("Could not retrieve current executable path");
388 binary_path.pop();
389 binary_path.push(RUST_SERVICE_BINARY);
390 let mut command = Command::new(&binary_path);
391 command.arg(identifier);
392 if let Some(ext) = extension {
393 command.arg(ext);
394 }
395 let child = command.spawn().expect("Could not start service");
396 Self(child)
397 }
398 }
399
400 impl Drop for ScopedServiceProcess {
401 fn drop(&mut self) {
402 self.0.kill().expect("Could not kill child process");
403 self.0
404 .wait()
405 .expect("Could not wait for child process to die");
406 }
407 }
408
409 #[test]
410 fn check_services() {
411 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
412 assert!(sm.is_binder_alive());
413 assert!(sm.ping_binder().is_ok());
414
415 assert!(binder::get_service("this_service_does_not_exist").is_none());
416 assert_eq!(
417 binder::get_interface::<dyn ITest>("this_service_does_not_exist").err(),
418 Some(StatusCode::NAME_NOT_FOUND)
419 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000420 assert_eq!(
421 binder::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
422 Some(StatusCode::NAME_NOT_FOUND)
423 );
Stephen Crane2a3c2502020-06-16 17:48:35 -0700424
425 // The service manager service isn't an ITest, so this must fail.
426 assert_eq!(
427 binder::get_interface::<dyn ITest>("manager").err(),
428 Some(StatusCode::BAD_TYPE)
429 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000430 assert_eq!(
431 binder::get_interface::<dyn IATest<Tokio>>("manager").err(),
432 Some(StatusCode::BAD_TYPE)
433 );
Stephen Crane2a3c2502020-06-16 17:48:35 -0700434 }
435
Alice Ryhl929804f2021-11-02 12:04:39 +0000436 #[tokio::test]
437 async fn check_services_async() {
438 let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
439 assert!(sm.is_binder_alive());
440 assert!(sm.ping_binder().is_ok());
441
442 assert!(binder::get_service("this_service_does_not_exist").is_none());
443 assert_eq!(
444 binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
445 Some(StatusCode::NAME_NOT_FOUND)
446 );
447 assert_eq!(
448 binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").await.err(),
449 Some(StatusCode::NAME_NOT_FOUND)
450 );
451
452 // The service manager service isn't an ITest, so this must fail.
453 assert_eq!(
454 binder_tokio::get_interface::<dyn ITest>("manager").await.err(),
455 Some(StatusCode::BAD_TYPE)
456 );
457 assert_eq!(
458 binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(),
459 Some(StatusCode::BAD_TYPE)
460 );
461 }
462
Stephen Crane2a3c2502020-06-16 17:48:35 -0700463 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000464 fn check_wait_for_service() {
465 let mut sm =
466 binder::wait_for_service("manager").expect("Did not get manager binder service");
467 assert!(sm.is_binder_alive());
468 assert!(sm.ping_binder().is_ok());
469
470 // The service manager service isn't an ITest, so this must fail.
471 assert_eq!(
472 binder::wait_for_interface::<dyn ITest>("manager").err(),
473 Some(StatusCode::BAD_TYPE)
474 );
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000475 assert_eq!(
476 binder::wait_for_interface::<dyn IATest<Tokio>>("manager").err(),
477 Some(StatusCode::BAD_TYPE)
478 );
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000479 }
480
481 #[test]
Stephen Crane2a3c2502020-06-16 17:48:35 -0700482 fn trivial_client() {
483 let service_name = "trivial_client_test";
484 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800485 let test_client: Strong<dyn ITest> =
Stephen Crane2a3c2502020-06-16 17:48:35 -0700486 binder::get_interface(service_name).expect("Did not get manager binder service");
487 assert_eq!(test_client.test().unwrap(), "trivial_client_test");
488 }
489
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000490 #[tokio::test]
491 async fn trivial_client_async() {
492 let service_name = "trivial_client_test";
493 let _process = ScopedServiceProcess::new(service_name);
494 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000495 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000496 assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
497 }
498
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700499 #[test]
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000500 fn wait_for_trivial_client() {
501 let service_name = "wait_for_trivial_client_test";
502 let _process = ScopedServiceProcess::new(service_name);
503 let test_client: Strong<dyn ITest> =
504 binder::wait_for_interface(service_name).expect("Did not get manager binder service");
505 assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
506 }
507
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000508 #[tokio::test]
509 async fn wait_for_trivial_client_async() {
510 let service_name = "wait_for_trivial_client_test";
511 let _process = ScopedServiceProcess::new(service_name);
512 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000513 binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000514 assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
515 }
516
517 fn get_expected_selinux_context() -> &'static str {
518 unsafe {
519 let mut out_ptr = ptr::null_mut();
520 assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
521 assert!(!out_ptr.is_null());
522 CStr::from_ptr(out_ptr)
523 .to_str()
524 .expect("context was invalid UTF-8")
525 }
526 }
527
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000528 #[test]
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700529 fn get_selinux_context() {
530 let service_name = "get_selinux_context";
531 let _process = ScopedServiceProcess::new(service_name);
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800532 let test_client: Strong<dyn ITest> =
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700533 binder::get_interface(service_name).expect("Did not get manager binder service");
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700534 assert_eq!(
535 test_client.get_selinux_context().unwrap(),
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000536 get_expected_selinux_context()
537 );
538 }
539
540 #[tokio::test]
541 async fn get_selinux_context_async() {
Alice Ryhl29a50262021-12-10 11:14:32 +0000542 let service_name = "get_selinux_context_async";
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000543 let _process = ScopedServiceProcess::new(service_name);
544 let test_client: Strong<dyn IATest<Tokio>> =
Alice Ryhl929804f2021-11-02 12:04:39 +0000545 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
Alice Ryhl05f5a2c2021-09-15 12:56:10 +0000546 assert_eq!(
547 test_client.get_selinux_context().await.unwrap(),
548 get_expected_selinux_context()
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700549 );
550 }
551
Alice Ryhlc1736842021-11-23 12:38:51 +0000552 #[tokio::test]
553 async fn get_selinux_context_sync_to_async() {
554 let service_name = "get_selinux_context";
555 let _process = ScopedServiceProcess::new(service_name);
556 let test_client: Strong<dyn ITest> =
557 binder::get_interface(service_name).expect("Did not get manager binder service");
558 let test_client = test_client.into_async::<Tokio>();
559 assert_eq!(
560 test_client.get_selinux_context().await.unwrap(),
561 get_expected_selinux_context()
562 );
563 }
564
565 #[tokio::test]
566 async fn get_selinux_context_async_to_sync() {
567 let service_name = "get_selinux_context";
568 let _process = ScopedServiceProcess::new(service_name);
569 let test_client: Strong<dyn IATest<Tokio>> =
570 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
571 let test_client = test_client.into_sync();
572 assert_eq!(
573 test_client.get_selinux_context().unwrap(),
574 get_expected_selinux_context()
575 );
576 }
577
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000578 struct Bools {
579 binder_died: Arc<AtomicBool>,
580 binder_dealloc: Arc<AtomicBool>,
581 }
582
583 impl Bools {
584 fn is_dead(&self) -> bool {
585 self.binder_died.load(Ordering::Relaxed)
586 }
587 fn assert_died(&self) {
588 assert!(
589 self.is_dead(),
590 "Did not receive death notification"
591 );
592 }
593 fn assert_dropped(&self) {
594 assert!(
595 self.binder_dealloc.load(Ordering::Relaxed),
596 "Did not dealloc death notification"
597 );
598 }
599 fn assert_not_dropped(&self) {
600 assert!(
601 !self.binder_dealloc.load(Ordering::Relaxed),
602 "Dealloc death notification too early"
603 );
604 }
605 }
606
607 fn register_death_notification(binder: &mut SpIBinder) -> (Bools, DeathRecipient) {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700608 let binder_died = Arc::new(AtomicBool::new(false));
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000609 let binder_dealloc = Arc::new(AtomicBool::new(false));
610
611 struct SetOnDrop {
612 binder_dealloc: Arc<AtomicBool>,
613 }
614 impl Drop for SetOnDrop {
615 fn drop(&mut self) {
616 self.binder_dealloc.store(true, Ordering::Relaxed);
617 }
618 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700619
620 let mut death_recipient = {
621 let flag = binder_died.clone();
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000622 let set_on_drop = SetOnDrop {
623 binder_dealloc: binder_dealloc.clone(),
624 };
Stephen Crane2a3c2502020-06-16 17:48:35 -0700625 DeathRecipient::new(move || {
626 flag.store(true, Ordering::Relaxed);
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000627 // Force the closure to take ownership of set_on_drop. When the closure is
628 // dropped, the destructor of `set_on_drop` will run.
629 let _ = &set_on_drop;
Stephen Crane2a3c2502020-06-16 17:48:35 -0700630 })
631 };
632
633 binder
634 .link_to_death(&mut death_recipient)
635 .expect("link_to_death failed");
636
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000637 let bools = Bools {
638 binder_died,
639 binder_dealloc,
640 };
641
642 (bools, death_recipient)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700643 }
644
645 /// Killing a remote service should unregister the service and trigger
646 /// death notifications.
647 #[test]
648 fn test_death_notifications() {
649 binder::ProcessState::start_thread_pool();
650
651 let service_name = "test_death_notifications";
652 let service_process = ScopedServiceProcess::new(service_name);
653 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
654
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000655 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700656
657 drop(service_process);
658 remote
659 .ping_binder()
660 .expect_err("Service should have died already");
661
662 // Pause to ensure any death notifications get delivered
663 thread::sleep(Duration::from_secs(1));
664
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000665 bools.assert_died();
666 bools.assert_not_dropped();
667
668 drop(recipient);
669
670 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700671 }
672
673 /// Test unregistering death notifications.
674 #[test]
675 fn test_unregister_death_notifications() {
676 binder::ProcessState::start_thread_pool();
677
678 let service_name = "test_unregister_death_notifications";
679 let service_process = ScopedServiceProcess::new(service_name);
680 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
681
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000682 let (bools, mut recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700683
684 remote
685 .unlink_to_death(&mut recipient)
686 .expect("Could not unlink death notifications");
687
688 drop(service_process);
689 remote
690 .ping_binder()
691 .expect_err("Service should have died already");
692
693 // Pause to ensure any death notifications get delivered
694 thread::sleep(Duration::from_secs(1));
695
696 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000697 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700698 "Received unexpected death notification after unlinking",
699 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000700
701 bools.assert_not_dropped();
702 drop(recipient);
703 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700704 }
705
706 /// Dropping a remote handle should unregister any death notifications.
707 #[test]
708 fn test_death_notification_registration_lifetime() {
709 binder::ProcessState::start_thread_pool();
710
711 let service_name = "test_death_notification_registration_lifetime";
712 let service_process = ScopedServiceProcess::new(service_name);
713 let mut remote = binder::get_service(service_name).expect("Could not retrieve service");
714
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000715 let (bools, recipient) = register_death_notification(&mut remote);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700716
717 // This should automatically unregister our death notification.
718 drop(remote);
719
720 drop(service_process);
721
722 // Pause to ensure any death notifications get delivered
723 thread::sleep(Duration::from_secs(1));
724
725 // We dropped the remote handle, so we should not receive the death
726 // notification when the remote process dies here.
727 assert!(
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000728 !bools.is_dead(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700729 "Received unexpected death notification after dropping remote handle"
730 );
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000731
732 bools.assert_not_dropped();
733 drop(recipient);
734 bools.assert_dropped();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700735 }
736
737 /// Test IBinder interface methods not exercised elsewhere.
738 #[test]
739 fn test_misc_ibinder() {
740 let service_name = "rust_test_ibinder";
741
742 {
743 let _process = ScopedServiceProcess::new(service_name);
744
Stephen Crane2a3297f2021-06-11 16:48:10 -0700745 let test_client: Strong<dyn ITest> =
Stephen Crane214307b2022-01-19 00:05:11 +0000746 binder::get_interface(service_name)
747 .expect("Did not get test binder service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700748 let mut remote = test_client.as_binder();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700749 assert!(remote.is_binder_alive());
750 remote.ping_binder().expect("Could not ping remote service");
751
Stephen Crane2a3297f2021-06-11 16:48:10 -0700752 let dump_args = ["dump", "args", "for", "testing"];
753
Stephen Crane2a3c2502020-06-16 17:48:35 -0700754 let null_out = File::open("/dev/null").expect("Could not open /dev/null");
755 remote
Stephen Crane2a3297f2021-06-11 16:48:10 -0700756 .dump(&null_out, &dump_args)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700757 .expect("Could not dump remote service");
Stephen Crane2a3297f2021-06-11 16:48:10 -0700758
759 let remote_args = test_client.get_dump_args().expect("Could not fetched dumped args");
760 assert_eq!(dump_args, remote_args[..], "Remote args don't match call to dump");
Stephen Crane2a3c2502020-06-16 17:48:35 -0700761 }
762
763 // get/set_extensions is tested in test_extensions()
764
765 // transact is tested everywhere else, and we can't make raw
766 // transactions outside the [FIRST_CALL_TRANSACTION,
767 // LAST_CALL_TRANSACTION] range from the NDK anyway.
768
769 // link_to_death is tested in test_*_death_notification* tests.
770 }
771
772 #[test]
773 fn test_extensions() {
774 let service_name = "rust_test_extensions";
775 let extension_name = "rust_test_extensions_ext";
776
777 {
778 let _process = ScopedServiceProcess::new(service_name);
779
780 let mut remote = binder::get_service(service_name);
781 assert!(remote.is_binder_alive());
782
783 let extension = remote
784 .get_extension()
785 .expect("Could not check for an extension");
786 assert!(extension.is_none());
787 }
788
789 {
790 let _process = ScopedServiceProcess::new_with_extension(service_name, extension_name);
791
792 let mut remote = binder::get_service(service_name);
793 assert!(remote.is_binder_alive());
794
795 let maybe_extension = remote
796 .get_extension()
797 .expect("Could not check for an extension");
798
799 let extension = maybe_extension.expect("Remote binder did not have an extension");
800
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800801 let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700802 .expect("Extension could not be converted to the expected interface");
803
804 assert_eq!(extension.test().unwrap(), extension_name);
805 }
806 }
Stephen Crane669deb62020-09-10 17:31:39 -0700807
808 /// Test re-associating a local binder object with a different class.
809 ///
810 /// This is needed because different binder service (e.g. NDK vs Rust)
811 /// implementations are incompatible and must not be interchanged. A local
812 /// service with the same descriptor string but a different class pointer
813 /// may have been created by an NDK service and is therefore incompatible
814 /// with the Rust service implementation. It must be treated as remote and
815 /// all API calls parceled and sent through transactions.
816 ///
817 /// Further tests of this behavior with the C NDK and Rust API are in
818 /// rust_ndk_interop.rs
819 #[test]
820 fn associate_existing_class() {
Stephen Crane2a3297f2021-06-11 16:48:10 -0700821 let service = Binder::new(BnTest(Box::new(TestService::new("testing_service"))));
Stephen Crane669deb62020-09-10 17:31:39 -0700822
823 // This should succeed although we will have to treat the service as
824 // remote.
Andrew Walbran12400d82021-03-04 17:04:34 +0000825 let _interface: Strong<dyn ITestSameDescriptor> =
826 FromIBinder::try_from(service.as_binder())
827 .expect("Could not re-interpret service as the ITestSameDescriptor interface");
Stephen Crane669deb62020-09-10 17:31:39 -0700828 }
829
830 /// Test that we can round-trip a rust service through a generic IBinder
831 #[test]
832 fn reassociate_rust_binder() {
833 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000834 let service_ibinder = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700835 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000836 BinderFeatures::default(),
837 )
Andrew Walbran12400d82021-03-04 17:04:34 +0000838 .as_binder();
Stephen Crane669deb62020-09-10 17:31:39 -0700839
Andrew Walbran12400d82021-03-04 17:04:34 +0000840 let service: Strong<dyn ITest> = service_ibinder
841 .into_interface()
Stephen Crane669deb62020-09-10 17:31:39 -0700842 .expect("Could not reassociate the generic ibinder");
843
844 assert_eq!(service.test().unwrap(), service_name);
845 }
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800846
847 #[test]
848 fn weak_binder_upgrade() {
849 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000850 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700851 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000852 BinderFeatures::default(),
853 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800854
855 let weak = Strong::downgrade(&service);
856
857 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
858
859 assert_eq!(service, upgraded);
860 }
861
862 #[test]
863 fn weak_binder_upgrade_dead() {
864 let service_name = "testing_service";
865 let weak = {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000866 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700867 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000868 BinderFeatures::default(),
869 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800870
871 Strong::downgrade(&service)
872 };
873
874 assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
875 }
876
877 #[test]
878 fn weak_binder_clone() {
879 let service_name = "testing_service";
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000880 let service = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700881 TestService::new(service_name),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000882 BinderFeatures::default(),
883 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800884
885 let weak = Strong::downgrade(&service);
886 let cloned = weak.clone();
887 assert_eq!(weak, cloned);
888
889 let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
890 let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
891
892 assert_eq!(service, upgraded);
893 assert_eq!(service, clone_upgraded);
894 }
895
896 #[test]
897 #[allow(clippy::eq_op)]
898 fn binder_ord() {
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000899 let service1 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700900 TestService::new("testing_service1"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000901 BinderFeatures::default(),
902 );
903 let service2 = BnTest::new_binder(
Stephen Crane2a3297f2021-06-11 16:48:10 -0700904 TestService::new("testing_service2"),
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000905 BinderFeatures::default(),
906 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800907
908 assert!(!(service1 < service1));
909 assert!(!(service1 > service1));
910 assert_eq!(service1 < service2, !(service2 < service1));
911 }
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000912
913 #[test]
914 fn binder_parcel_mixup() {
915 let service1 = BnTest::new_binder(
916 TestService::new("testing_service1"),
917 BinderFeatures::default(),
918 );
919 let service2 = BnTest::new_binder(
920 TestService::new("testing_service2"),
921 BinderFeatures::default(),
922 );
923
924 let service1 = service1.as_binder();
925 let service2 = service2.as_binder();
926
927 let parcel = service1.prepare_transact().unwrap();
Stephen Crane214307b2022-01-19 00:05:11 +0000928 let res = service2.submit_transact(super::TestTransactionCode::Test as binder::TransactionCode, parcel, 0);
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000929
930 match res {
931 Ok(_) => panic!("submit_transact should fail"),
932 Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
933 }
934 }
Alice Ryhl29a50262021-12-10 11:14:32 +0000935
936 #[test]
937 fn get_is_handling_transaction() {
938 let service_name = "get_is_handling_transaction";
939 let _process = ScopedServiceProcess::new(service_name);
940 let test_client: Strong<dyn ITest> =
941 binder::get_interface(service_name).expect("Did not get manager binder service");
942 // Should be true externally.
943 assert!(test_client.get_is_handling_transaction().unwrap());
944
945 // Should be false locally.
946 assert!(!binder::is_handling_transaction());
947
948 // Should also be false in spawned thread.
949 std::thread::spawn(|| {
950 assert!(!binder::is_handling_transaction());
951 }).join().unwrap();
952 }
953
954 #[tokio::test]
955 async fn get_is_handling_transaction_async() {
956 let service_name = "get_is_handling_transaction_async";
957 let _process = ScopedServiceProcess::new(service_name);
958 let test_client: Strong<dyn IATest<Tokio>> =
959 binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
960 // Should be true externally.
961 assert!(test_client.get_is_handling_transaction().await.unwrap());
962
963 // Should be false locally.
964 assert!(!binder::is_handling_transaction());
965
966 // Should also be false in spawned task.
967 tokio::spawn(async {
968 assert!(!binder::is_handling_transaction());
969 }).await.unwrap();
970
971 // And in spawn_blocking task.
972 tokio::task::spawn_blocking(|| {
973 assert!(!binder::is_handling_transaction());
974 }).await.unwrap();
975 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700976}