/* * Copyright (C) 2022, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //! Test Rust service for the AIDL compiler. use aidl_test_interface::aidl::android::aidl::tests::nested::{ INestedService, ParcelableWithNested, }; use aidl_test_interface::aidl::android::aidl::tests::ITestService::{ self, BnTestService, BpTestService, Empty::Empty, }; use aidl_test_interface::aidl::android::aidl::tests::{ extension::ExtendableParcelable::ExtendableParcelable, extension::MyExt::MyExt, BackendType::BackendType, ByteEnum::ByteEnum, CircularParcelable::CircularParcelable, ConstantExpressionEnum::ConstantExpressionEnum, ICircular, INamedCallback, INewName, IOldName, IntEnum::IntEnum, LongEnum::LongEnum, RecursiveList::RecursiveList, StructuredParcelable, Union, }; use aidl_test_interface::binder::{ self, BinderFeatures, Interface, ParcelFileDescriptor, SpIBinder, }; use aidl_test_versioned_interface::aidl::android::aidl::versioned::tests::{ BazUnion::BazUnion, Foo::Foo, IFooInterface, IFooInterface::BnFooInterface, IFooInterface::BpFooInterface, }; use std::collections::HashMap; use std::sync::Mutex; use async_trait::async_trait; fn dup_fd(fd: &ParcelFileDescriptor) -> ParcelFileDescriptor { ParcelFileDescriptor::new(fd.as_ref().try_clone().unwrap()) } struct NamedCallback(String); impl Interface for NamedCallback {} #[async_trait] impl INamedCallback::INamedCallbackAsyncServer for NamedCallback { async fn GetName(&self) -> binder::Result { Ok(self.0.clone()) } } struct OldName; impl Interface for OldName {} #[async_trait] impl IOldName::IOldNameAsyncServer for OldName { async fn RealName(&self) -> binder::Result { Ok("OldName".into()) } } #[derive(Debug, Default)] struct NewName; impl Interface for NewName {} #[async_trait] impl INewName::INewNameAsyncServer for NewName { async fn RealName(&self) -> binder::Result { Ok("NewName".into()) } } #[derive(Debug, Default)] struct Circular; impl Interface for Circular {} #[async_trait] impl ICircular::ICircularAsyncServer for Circular { async fn GetTestService( &self, ) -> binder::Result>> { Ok(None) } } #[derive(Default)] struct TestService { service_map: Mutex>>, } impl Interface for TestService {} // Macros are expanded in the wrong order, so async_trait does not apply to // functions defined by declarative macros. type BoxFuture<'a, T> = std::pin::Pin + Send + 'a>>; macro_rules! impl_repeat { ($repeat_name:ident, $type:ty) => { fn $repeat_name<'a, 'b>(&'a self, token: $type) -> BoxFuture<'b, binder::Result<$type>> where 'a: 'b, Self: 'b, { Box::pin(async move { Ok(token) }) } }; } macro_rules! impl_reverse { ($reverse_name:ident, $type:ty) => { fn $reverse_name<'a, 'b, 'c, 'd>( &'a self, input: &'b [$type], repeated: &'c mut Vec<$type>, ) -> BoxFuture<'d, binder::Result>> where 'a: 'd, 'b: 'd, 'c: 'd, Self: 'd, { Box::pin(async move { repeated.clear(); repeated.extend_from_slice(input); Ok(input.iter().rev().cloned().collect()) }) } }; } macro_rules! impl_repeat_reverse { ($repeat_name:ident, $reverse_name:ident, $type:ty) => { impl_repeat! {$repeat_name, $type} impl_reverse! {$reverse_name, $type} }; } macro_rules! impl_repeat_nullable { ($repeat_nullable_name:ident, $type:ty) => { fn $repeat_nullable_name<'a, 'b, 'c>( &'a self, input: Option<&'b [$type]>, ) -> BoxFuture<'c, binder::Result>>> where 'a: 'c, 'b: 'c, Self: 'c, { Box::pin(async move { Ok(input.map(<[$type]>::to_vec)) }) } }; } #[async_trait] impl ITestService::ITestServiceAsyncServer for TestService { impl_repeat! {RepeatByte, i8} impl_reverse! {ReverseByte, u8} async fn UnimplementedMethod(&self, _: i32) -> binder::Result { // Pretend this method hasn't been implemented Err(binder::StatusCode::UNKNOWN_TRANSACTION.into()) } async fn TestOneway(&self) -> binder::Result<()> { Err(binder::StatusCode::UNKNOWN_ERROR.into()) } async fn Deprecated(&self) -> binder::Result<()> { Ok(()) } impl_repeat_reverse! {RepeatBoolean, ReverseBoolean, bool} impl_repeat_reverse! {RepeatChar, ReverseChar, u16} impl_repeat_reverse! {RepeatInt, ReverseInt, i32} impl_repeat_reverse! {RepeatLong, ReverseLong, i64} impl_repeat_reverse! {RepeatFloat, ReverseFloat, f32} impl_repeat_reverse! {RepeatDouble, ReverseDouble, f64} impl_repeat_reverse! {RepeatByteEnum, ReverseByteEnum, ByteEnum} impl_repeat_reverse! {RepeatIntEnum, ReverseIntEnum, IntEnum} impl_repeat_reverse! {RepeatLongEnum, ReverseLongEnum, LongEnum} impl_reverse! {ReverseString, String} impl_reverse! {ReverseStringList, String} impl_reverse! {ReverseUtf8CppString, String} async fn RepeatString(&self, input: &str) -> binder::Result { Ok(input.into()) } async fn RepeatUtf8CppString(&self, input: &str) -> binder::Result { Ok(input.into()) } async fn GetOtherTestService( &self, name: &str, ) -> binder::Result> { let mut service_map = self.service_map.lock().unwrap(); let other_service = service_map.entry(name.into()).or_insert_with(|| { let named_callback = NamedCallback(name.into()); INamedCallback::BnNamedCallback::new_async_binder( named_callback, rt(), BinderFeatures::default(), ) }); Ok(other_service.to_owned()) } async fn SetOtherTestService( &self, name: &str, service: &binder::Strong, ) -> binder::Result { let mut service_map = self.service_map.lock().unwrap(); if let Some(existing_service) = service_map.get(name) { if existing_service == service { return Ok(true); } } service_map.insert(name.into(), service.clone()); Ok(false) } async fn VerifyName( &self, service: &binder::Strong, name: &str, ) -> binder::Result { service.GetName().map(|found_name| found_name == name) } async fn GetInterfaceArray( &self, names: &[String], ) -> binder::Result>> { let mut res = Vec::new(); for name in names { res.push(self.GetOtherTestService(name).await?); } Ok(res) } async fn VerifyNamesWithInterfaceArray( &self, services: &[binder::Strong], names: &[String], ) -> binder::Result { if services.len() == names.len() { for (s, n) in services.iter().zip(names) { if !self.VerifyName(s, n).await? { return Ok(false); } } Ok(true) } else { Ok(false) } } async fn GetNullableInterfaceArray( &self, names: Option<&[Option]>, ) -> binder::Result>>>> { if let Some(names) = names { let mut services = vec![]; for name in names { if let Some(name) = name { services.push(Some(self.GetOtherTestService(name).await?)); } else { services.push(None); } } Ok(Some(services)) } else { Ok(None) } } async fn VerifyNamesWithNullableInterfaceArray( &self, services: Option<&[Option>]>, names: Option<&[Option]>, ) -> binder::Result { if let (Some(services), Some(names)) = (services, names) { for (s, n) in services.iter().zip(names) { if let (Some(s), Some(n)) = (s, n) { if !self.VerifyName(s, n).await? { return Ok(false); } } else if s.is_some() || n.is_some() { return Ok(false); } } Ok(true) } else { Ok(services.is_none() && names.is_none()) } } async fn GetInterfaceList( &self, names: Option<&[Option]>, ) -> binder::Result>>>> { self.GetNullableInterfaceArray(names).await } async fn VerifyNamesWithInterfaceList( &self, services: Option<&[Option>]>, names: Option<&[Option]>, ) -> binder::Result { self.VerifyNamesWithNullableInterfaceArray(services, names).await } async fn RepeatParcelFileDescriptor( &self, read: &ParcelFileDescriptor, ) -> binder::Result { Ok(dup_fd(read)) } async fn ReverseParcelFileDescriptorArray( &self, input: &[ParcelFileDescriptor], repeated: &mut Vec>, ) -> binder::Result> { repeated.clear(); repeated.extend(input.iter().map(dup_fd).map(Some)); Ok(input.iter().rev().map(dup_fd).collect()) } async fn ThrowServiceException(&self, code: i32) -> binder::Result<()> { Err(binder::Status::new_service_specific_error(code, None)) } impl_repeat_nullable! {RepeatNullableIntArray, i32} impl_repeat_nullable! {RepeatNullableByteEnumArray, ByteEnum} impl_repeat_nullable! {RepeatNullableIntEnumArray, IntEnum} impl_repeat_nullable! {RepeatNullableLongEnumArray, LongEnum} impl_repeat_nullable! {RepeatNullableStringList, Option} async fn RepeatNullableString(&self, input: Option<&str>) -> binder::Result> { Ok(input.map(String::from)) } async fn RepeatNullableUtf8CppString( &self, input: Option<&str>, ) -> binder::Result> { Ok(input.map(String::from)) } async fn RepeatNullableParcelable( &self, input: Option<&Empty>, ) -> binder::Result> { Ok(input.cloned()) } impl_repeat_nullable! {RepeatNullableParcelableArray, Option} impl_repeat_nullable! {RepeatNullableParcelableList, Option} async fn TakesAnIBinder(&self, _: &SpIBinder) -> binder::Result<()> { Ok(()) } async fn TakesANullableIBinder(&self, _: Option<&SpIBinder>) -> binder::Result<()> { Ok(()) } async fn TakesAnIBinderList(&self, _: &[SpIBinder]) -> binder::Result<()> { Ok(()) } async fn TakesANullableIBinderList( &self, _: Option<&[Option]>, ) -> binder::Result<()> { Ok(()) } async fn ReverseNullableUtf8CppString( &self, input: Option<&[Option]>, repeated: &mut Option>>, ) -> binder::Result>>> { if let Some(input) = input { *repeated = Some(input.to_vec()); Ok(Some(input.iter().rev().cloned().collect())) } else { // We don't touch `repeated` here, since // the C++ test service doesn't either Ok(None) } } async fn ReverseUtf8CppStringList( &self, input: Option<&[Option]>, repeated: &mut Option>>, ) -> binder::Result>>> { self.ReverseNullableUtf8CppString(input, repeated).await } async fn GetCallback( &self, return_null: bool, ) -> binder::Result>> { if return_null { Ok(None) } else { self.GetOtherTestService("ABT: always be testing").await.map(Some) } } async fn FillOutStructuredParcelable( &self, parcelable: &mut StructuredParcelable::StructuredParcelable, ) -> binder::Result<()> { parcelable.shouldBeJerry = "Jerry".into(); parcelable.shouldContainThreeFs = vec![parcelable.f, parcelable.f, parcelable.f]; parcelable.shouldBeByteBar = ByteEnum::BAR; parcelable.shouldBeIntBar = IntEnum::BAR; parcelable.shouldBeLongBar = LongEnum::BAR; parcelable.shouldContainTwoByteFoos = vec![ByteEnum::FOO, ByteEnum::FOO]; parcelable.shouldContainTwoIntFoos = vec![IntEnum::FOO, IntEnum::FOO]; parcelable.shouldContainTwoLongFoos = vec![LongEnum::FOO, LongEnum::FOO]; parcelable.const_exprs_1 = ConstantExpressionEnum::decInt32_1; parcelable.const_exprs_2 = ConstantExpressionEnum::decInt32_2; parcelable.const_exprs_3 = ConstantExpressionEnum::decInt64_1; parcelable.const_exprs_4 = ConstantExpressionEnum::decInt64_2; parcelable.const_exprs_5 = ConstantExpressionEnum::decInt64_3; parcelable.const_exprs_6 = ConstantExpressionEnum::decInt64_4; parcelable.const_exprs_7 = ConstantExpressionEnum::hexInt32_1; parcelable.const_exprs_8 = ConstantExpressionEnum::hexInt32_2; parcelable.const_exprs_9 = ConstantExpressionEnum::hexInt32_3; parcelable.const_exprs_10 = ConstantExpressionEnum::hexInt64_1; parcelable.shouldSetBit0AndBit2 = StructuredParcelable::BIT0 | StructuredParcelable::BIT2; parcelable.u = Some(Union::Union::Ns(vec![1, 2, 3])); parcelable.shouldBeConstS1 = Some(Union::Union::S(Union::S1.to_string())); Ok(()) } async fn RepeatExtendableParcelable( &self, ep: &ExtendableParcelable, ep2: &mut ExtendableParcelable, ) -> binder::Result<()> { ep2.a = ep.a; ep2.b = ep.b.clone(); let my_ext = ep.ext.get_parcelable::()?; if let Some(my_ext) = my_ext { ep2.ext.set_parcelable(my_ext)?; } else { ep2.ext.reset(); } Ok(()) } async fn ReverseList(&self, list: &RecursiveList) -> binder::Result { let mut reversed: Option = None; let mut cur: Option<&RecursiveList> = Some(list); while let Some(node) = cur { reversed = Some(RecursiveList { value: node.value, next: reversed.map(Box::new) }); cur = node.next.as_ref().map(|n| n.as_ref()); } // `list` is always not empty, so is `reversed`. Ok(reversed.unwrap()) } async fn ReverseIBinderArray( &self, input: &[SpIBinder], repeated: &mut Vec>, ) -> binder::Result> { *repeated = input.iter().cloned().map(Some).collect(); Ok(input.iter().rev().cloned().collect()) } async fn ReverseNullableIBinderArray( &self, input: Option<&[Option]>, repeated: &mut Option>>, ) -> binder::Result>>> { let input = input.expect("input is null"); *repeated = Some(input.to_vec()); Ok(Some(input.iter().rev().cloned().collect())) } async fn GetOldNameInterface(&self) -> binder::Result> { Ok(IOldName::BnOldName::new_async_binder(OldName, rt(), BinderFeatures::default())) } async fn GetNewNameInterface(&self) -> binder::Result> { Ok(INewName::BnNewName::new_async_binder(NewName, rt(), BinderFeatures::default())) } async fn GetUnionTags(&self, input: &[Union::Union]) -> binder::Result> { Ok(input .iter() .map(|u| match u { Union::Union::Ns(_) => Union::Tag::Tag::ns, Union::Union::N(_) => Union::Tag::Tag::n, Union::Union::M(_) => Union::Tag::Tag::m, Union::Union::S(_) => Union::Tag::Tag::s, Union::Union::Ibinder(_) => Union::Tag::Tag::ibinder, Union::Union::Ss(_) => Union::Tag::Tag::ss, Union::Union::Be(_) => Union::Tag::Tag::be, }) .collect::>()) } async fn GetCppJavaTests(&self) -> binder::Result> { Ok(None) } async fn getBackendType(&self) -> binder::Result { Ok(BackendType::RUST) } async fn GetCircular( &self, _: &mut CircularParcelable, ) -> binder::Result> { Ok(ICircular::BnCircular::new_async_binder(Circular, rt(), BinderFeatures::default())) } } struct FooInterface; impl Interface for FooInterface {} #[async_trait] impl IFooInterface::IFooInterfaceAsyncServer for FooInterface { async fn originalApi(&self) -> binder::Result<()> { Ok(()) } async fn acceptUnionAndReturnString(&self, u: &BazUnion) -> binder::Result { match u { BazUnion::IntNum(n) => Ok(n.to_string()), } } async fn returnsLengthOfFooArray(&self, foos: &[Foo]) -> binder::Result { Ok(foos.len() as i32) } async fn ignoreParcelablesAndRepeatInt( &self, _in_foo: &Foo, _inout_foo: &mut Foo, _out_foo: &mut Foo, value: i32, ) -> binder::Result { Ok(value) } } struct NestedService; impl Interface for NestedService {} #[async_trait] impl INestedService::INestedServiceAsyncServer for NestedService { async fn flipStatus( &self, p: &ParcelableWithNested::ParcelableWithNested, ) -> binder::Result { if p.status == ParcelableWithNested::Status::Status::OK { Ok(INestedService::Result::Result { status: ParcelableWithNested::Status::Status::NOT_OK, }) } else { Ok(INestedService::Result::Result { status: ParcelableWithNested::Status::Status::OK }) } } async fn flipStatusWithCallback( &self, st: ParcelableWithNested::Status::Status, cb: &binder::Strong, ) -> binder::Result<()> { if st == ParcelableWithNested::Status::Status::OK { cb.done(ParcelableWithNested::Status::Status::NOT_OK) } else { cb.done(ParcelableWithNested::Status::Status::OK) } } } fn rt() -> binder_tokio::TokioRuntime { let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); binder_tokio::TokioRuntime(rt) } fn main() { binder::ProcessState::set_thread_pool_max_thread_count(0); binder::ProcessState::start_thread_pool(); let service_name = ::get_descriptor(); let service = BnTestService::new_async_binder(TestService::default(), rt(), BinderFeatures::default()); binder::add_service(service_name, service.as_binder()).expect("Could not register service"); let versioned_service_name = ::get_descriptor(); let versioned_service = BnFooInterface::new_async_binder(FooInterface, rt(), BinderFeatures::default()); binder::add_service(versioned_service_name, versioned_service.as_binder()) .expect("Could not register service"); let nested_service_name = ::get_descriptor(); let nested_service = INestedService::BnNestedService::new_async_binder( NestedService, rt(), BinderFeatures::default(), ); binder::add_service(nested_service_name, nested_service.as_binder()) .expect("Could not register service"); binder::ProcessState::join_thread_pool(); }