blob: 3a5c09c70e84d99bfafcefbe4c7ca7389aeec16d [file] [log] [blame]
/*
* Copyright (C) 2020, 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_fixedsizearray::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::{
IRepeatFixedSizeArray, IntParcelable::IntParcelable,
};
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;
fn dup_fd(fd: &ParcelFileDescriptor) -> ParcelFileDescriptor {
ParcelFileDescriptor::new(fd.as_ref().try_clone().unwrap())
}
struct NamedCallback(String);
impl Interface for NamedCallback {}
impl INamedCallback::INamedCallback for NamedCallback {
fn GetName(&self) -> binder::Result<String> {
Ok(self.0.clone())
}
}
struct OldName;
impl Interface for OldName {}
impl IOldName::IOldName for OldName {
fn RealName(&self) -> binder::Result<String> {
Ok("OldName".into())
}
}
#[derive(Debug, Default)]
struct NewName;
impl Interface for NewName {}
impl INewName::INewName for NewName {
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 {}
macro_rules! impl_repeat {
($repeat_name:ident, $type:ty) => {
fn $repeat_name(&self, token: $type) -> binder::Result<$type> {
Ok(token)
}
};
}
macro_rules! impl_reverse {
($reverse_name:ident, $type:ty) => {
fn $reverse_name(
&self,
input: &[$type],
repeated: &mut Vec<$type>,
) -> binder::Result<Vec<$type>> {
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(
&self,
input: Option<&[$type]>,
) -> binder::Result<Option<Vec<$type>>> {
Ok(input.map(<[$type]>::to_vec))
}
};
}
impl ITestService::ITestService for TestService {
impl_repeat! {RepeatByte, i8}
impl_reverse! {ReverseByte, u8}
fn UnimplementedMethod(&self, _: i32) -> binder::Result<i32> {
// Pretend this method hasn't been implemented
Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
}
fn TestOneway(&self) -> binder::Result<()> {
Err(binder::StatusCode::UNKNOWN_ERROR.into())
}
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}
fn RepeatString(&self, input: &str) -> binder::Result<String> {
Ok(input.into())
}
fn RepeatUtf8CppString(&self, input: &str) -> binder::Result<String> {
Ok(input.into())
}
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_binder(named_callback, BinderFeatures::default())
});
Ok(other_service.to_owned())
}
fn VerifyName(
&self,
service: &binder::Strong<dyn INamedCallback::INamedCallback>,
name: &str,
) -> binder::Result<bool> {
service.GetName().map(|found_name| found_name == name)
}
fn GetInterfaceArray(
&self,
names: &[String],
) -> binder::Result<Vec<binder::Strong<dyn INamedCallback::INamedCallback>>> {
names.iter().map(|name| self.GetOtherTestService(name)).collect()
}
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)? {
return Ok(false);
}
}
Ok(true)
} else {
Ok(false)
}
}
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)?));
} else {
services.push(None);
}
}
Ok(Some(services))
} else {
Ok(None)
}
}
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)? {
return Ok(false);
}
} else if s.is_some() || n.is_some() {
return Ok(false);
}
}
Ok(true)
} else {
Ok(services.is_none() && names.is_none())
}
}
fn GetInterfaceList(
&self,
names: Option<&[Option<String>]>,
) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
{
self.GetNullableInterfaceArray(names)
}
fn VerifyNamesWithInterfaceList(
&self,
services: Option<&[Option<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
names: Option<&[Option<String>]>,
) -> binder::Result<bool> {
self.VerifyNamesWithNullableInterfaceArray(services, names)
}
fn RepeatParcelFileDescriptor(
&self,
read: &ParcelFileDescriptor,
) -> binder::Result<ParcelFileDescriptor> {
Ok(dup_fd(read))
}
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())
}
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>}
fn RepeatNullableString(&self, input: Option<&str>) -> binder::Result<Option<String>> {
Ok(input.map(String::from))
}
fn RepeatNullableUtf8CppString(&self, input: Option<&str>) -> binder::Result<Option<String>> {
Ok(input.map(String::from))
}
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>}
fn TakesAnIBinder(&self, _: &SpIBinder) -> binder::Result<()> {
Ok(())
}
fn TakesANullableIBinder(&self, _: Option<&SpIBinder>) -> binder::Result<()> {
Ok(())
}
fn TakesAnIBinderList(&self, _: &[SpIBinder]) -> binder::Result<()> {
Ok(())
}
fn TakesANullableIBinderList(&self, _: Option<&[Option<SpIBinder>]>) -> binder::Result<()> {
Ok(())
}
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)
}
}
fn ReverseUtf8CppStringList(
&self,
input: Option<&[Option<String>]>,
repeated: &mut Option<Vec<Option<String>>>,
) -> binder::Result<Option<Vec<Option<String>>>> {
self.ReverseNullableUtf8CppString(input, repeated)
}
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").map(Some)
}
}
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(())
}
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(())
}
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())
}
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())
}
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()))
}
fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn IOldName::IOldName>> {
Ok(IOldName::BnOldName::new_binder(OldName, BinderFeatures::default()))
}
fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn INewName::INewName>> {
Ok(INewName::BnNewName::new_binder(NewName, BinderFeatures::default()))
}
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<_>>())
}
fn GetCppJavaTests(&self) -> binder::Result<Option<SpIBinder>> {
Ok(None)
}
fn getBackendType(&self) -> binder::Result<BackendType> {
Ok(BackendType::RUST)
}
}
struct FooInterface;
impl Interface for FooInterface {}
impl IFooInterface::IFooInterface for FooInterface {
fn originalApi(&self) -> binder::Result<()> {
Ok(())
}
fn acceptUnionAndReturnString(&self, u: &BazUnion) -> binder::Result<String> {
match u {
BazUnion::IntNum(n) => Ok(n.to_string()),
}
}
fn returnsLengthOfFooArray(&self, foos: &[Foo]) -> binder::Result<i32> {
Ok(foos.len() as i32)
}
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 {}
impl INestedService::INestedService for NestedService {
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 })
}
}
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)
}
}
}
struct FixedSizeArrayService;
impl Interface for FixedSizeArrayService {}
impl IRepeatFixedSizeArray::IRepeatFixedSizeArray for FixedSizeArrayService {
fn RepeatBytes(&self, input: &[u8; 3], repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]> {
*repeated = *input;
Ok(*input)
}
fn RepeatInts(&self, input: &[i32; 3], repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]> {
*repeated = *input;
Ok(*input)
}
fn RepeatBinders(
&self,
input: &[SpIBinder; 3],
repeated: &mut [Option<SpIBinder>; 3],
) -> binder::Result<[SpIBinder; 3]> {
*repeated = input.clone().map(Some);
Ok(input.clone())
}
fn RepeatParcelables(
&self,
input: &[IntParcelable; 3],
repeated: &mut [IntParcelable; 3],
) -> binder::Result<[IntParcelable; 3]> {
*repeated = *input;
Ok(*input)
}
fn Repeat2dBytes(
&self,
input: &[[u8; 3]; 2],
repeated: &mut [[u8; 3]; 2],
) -> binder::Result<[[u8; 3]; 2]> {
*repeated = *input;
Ok(*input)
}
fn Repeat2dInts(
&self,
input: &[[i32; 3]; 2],
repeated: &mut [[i32; 3]; 2],
) -> binder::Result<[[i32; 3]; 2]> {
*repeated = *input;
Ok(*input)
}
fn Repeat2dBinders(
&self,
input: &[[SpIBinder; 3]; 2],
repeated: &mut [[Option<SpIBinder>; 3]; 2],
) -> binder::Result<[[SpIBinder; 3]; 2]> {
*repeated = input.clone().map(|nested| nested.map(Some));
Ok(input.clone())
}
fn Repeat2dParcelables(
&self,
input: &[[IntParcelable; 3]; 2],
repeated: &mut [[IntParcelable; 3]; 2],
) -> binder::Result<[[IntParcelable; 3]; 2]> {
*repeated = *input;
Ok(*input)
}
}
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_binder(TestService::default(), 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_binder(FooInterface, 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_binder(NestedService, BinderFeatures::default());
binder::add_service(nested_service_name, nested_service.as_binder())
.expect("Could not register service");
let fixed_size_array_service_name =
<IRepeatFixedSizeArray::BpRepeatFixedSizeArray as IRepeatFixedSizeArray::IRepeatFixedSizeArray>::get_descriptor();
let fixed_size_array_service = IRepeatFixedSizeArray::BnRepeatFixedSizeArray::new_binder(
FixedSizeArrayService,
BinderFeatures::default(),
);
binder::add_service(fixed_size_array_service_name, fixed_size_array_service.as_binder())
.expect("Could not register service");
binder::ProcessState::join_thread_pool();
}