blob: cfc0f285c8af306ee3b37ce16d8d75abda1a8556 [file] [log] [blame]
/*
* 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, ConstantExpressionEnum::ConstantExpressionEnum,
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<String> {
Ok(self.0.clone())
}
}
struct OldName;
impl Interface for OldName {}
#[async_trait]
impl IOldName::IOldNameAsyncServer for OldName {
async fn RealName(&self) -> binder::Result<String> {
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<String> {
Ok("NewName".into())
}
}
#[derive(Default)]
struct TestService {
service_map: Mutex<HashMap<String, binder::Strong<dyn INamedCallback::INamedCallback>>>,
}
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<Box<dyn std::future::Future<Output = T> + 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<Vec<$type>>>
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<Option<Vec<$type>>>>
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<i32> {
// 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<String> {
Ok(input.into())
}
async fn RepeatUtf8CppString(&self, input: &str) -> binder::Result<String> {
Ok(input.into())
}
async fn GetOtherTestService(
&self,
name: &str,
) -> binder::Result<binder::Strong<dyn INamedCallback::INamedCallback>> {
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 VerifyName(
&self,
service: &binder::Strong<dyn INamedCallback::INamedCallback>,
name: &str,
) -> binder::Result<bool> {
service.GetName().map(|found_name| found_name == name)
}
async fn GetInterfaceArray(
&self,
names: &[String],
) -> binder::Result<Vec<binder::Strong<dyn INamedCallback::INamedCallback>>> {
let mut res = Vec::new();
for name in names {
res.push(self.GetOtherTestService(name).await?);
}
Ok(res)
}
async fn VerifyNamesWithInterfaceArray(
&self,
services: &[binder::Strong<dyn INamedCallback::INamedCallback>],
names: &[String],
) -> binder::Result<bool> {
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<String>]>,
) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
{
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<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
names: Option<&[Option<String>]>,
) -> binder::Result<bool> {
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<String>]>,
) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
{
self.GetNullableInterfaceArray(names).await
}
async fn VerifyNamesWithInterfaceList(
&self,
services: Option<&[Option<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
names: Option<&[Option<String>]>,
) -> binder::Result<bool> {
self.VerifyNamesWithNullableInterfaceArray(services, names).await
}
async fn RepeatParcelFileDescriptor(
&self,
read: &ParcelFileDescriptor,
) -> binder::Result<ParcelFileDescriptor> {
Ok(dup_fd(read))
}
async fn ReverseParcelFileDescriptorArray(
&self,
input: &[ParcelFileDescriptor],
repeated: &mut Vec<Option<ParcelFileDescriptor>>,
) -> binder::Result<Vec<ParcelFileDescriptor>> {
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<String>}
async fn RepeatNullableString(&self, input: Option<&str>) -> binder::Result<Option<String>> {
Ok(input.map(String::from))
}
async fn RepeatNullableUtf8CppString(
&self,
input: Option<&str>,
) -> binder::Result<Option<String>> {
Ok(input.map(String::from))
}
async fn RepeatNullableParcelable(
&self,
input: Option<&Empty>,
) -> binder::Result<Option<Empty>> {
Ok(input.cloned())
}
impl_repeat_nullable! {RepeatNullableParcelableArray, Option<Empty>}
impl_repeat_nullable! {RepeatNullableParcelableList, Option<Empty>}
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<SpIBinder>]>,
) -> binder::Result<()> {
Ok(())
}
async fn ReverseNullableUtf8CppString(
&self,
input: Option<&[Option<String>]>,
repeated: &mut Option<Vec<Option<String>>>,
) -> binder::Result<Option<Vec<Option<String>>>> {
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<String>]>,
repeated: &mut Option<Vec<Option<String>>>,
) -> binder::Result<Option<Vec<Option<String>>>> {
self.ReverseNullableUtf8CppString(input, repeated).await
}
async fn GetCallback(
&self,
return_null: bool,
) -> binder::Result<Option<binder::Strong<dyn INamedCallback::INamedCallback>>> {
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::<MyExt>()?;
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<RecursiveList> {
let mut reversed: Option<RecursiveList> = 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<Option<SpIBinder>>,
) -> binder::Result<Vec<SpIBinder>> {
*repeated = input.iter().cloned().map(Some).collect();
Ok(input.iter().rev().cloned().collect())
}
async fn ReverseNullableIBinderArray(
&self,
input: Option<&[Option<SpIBinder>]>,
repeated: &mut Option<Vec<Option<SpIBinder>>>,
) -> binder::Result<Option<Vec<Option<SpIBinder>>>> {
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<binder::Strong<dyn IOldName::IOldName>> {
Ok(IOldName::BnOldName::new_async_binder(OldName, rt(), BinderFeatures::default()))
}
async fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn INewName::INewName>> {
Ok(INewName::BnNewName::new_async_binder(NewName, rt(), BinderFeatures::default()))
}
async fn GetUnionTags(&self, input: &[Union::Union]) -> binder::Result<Vec<Union::Tag::Tag>> {
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::<Vec<_>>())
}
async fn GetCppJavaTests(&self) -> binder::Result<Option<SpIBinder>> {
Ok(None)
}
async fn getBackendType(&self) -> binder::Result<BackendType> {
Ok(BackendType::RUST)
}
}
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<String> {
match u {
BazUnion::IntNum(n) => Ok(n.to_string()),
}
}
async fn returnsLengthOfFooArray(&self, foos: &[Foo]) -> binder::Result<i32> {
Ok(foos.len() as i32)
}
async fn ignoreParcelablesAndRepeatInt(
&self,
_in_foo: &Foo,
_inout_foo: &mut Foo,
_out_foo: &mut Foo,
value: i32,
) -> binder::Result<i32> {
Ok(value)
}
}
struct NestedService;
impl Interface for NestedService {}
#[async_trait]
impl INestedService::INestedServiceAsyncServer for NestedService {
async fn flipStatus(
&self,
p: &ParcelableWithNested::ParcelableWithNested,
) -> binder::Result<INestedService::Result::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<dyn INestedService::ICallback::ICallback>,
) -> 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<tokio::runtime::Runtime> {
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 = <BpTestService as ITestService::ITestService>::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 = <BpFooInterface as IFooInterface::IFooInterface>::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 =
<INestedService::BpNestedService as INestedService::INestedService>::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();
}