351 lines
12 KiB
Rust
351 lines
12 KiB
Rust
/*
|
|
* 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_interface::aidl::android::aidl::tests::ITestService::{
|
|
self, BnTestService, BpTestService,
|
|
};
|
|
use aidl_test_interface::aidl::android::aidl::tests::{
|
|
BackendType::BackendType, ByteEnum::ByteEnum, ConstantExpressionEnum::ConstantExpressionEnum,
|
|
INamedCallback, INewName, IOldName, IntEnum::IntEnum, LongEnum::LongEnum, 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 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<&StructuredParcelable::StructuredParcelable>,
|
|
) -> binder::Result<Option<StructuredParcelable::StructuredParcelable>> {
|
|
Ok(input.cloned())
|
|
}
|
|
|
|
fn TakesAnIBinder(&self, _: &SpIBinder) -> binder::Result<()> {
|
|
Ok(())
|
|
}
|
|
|
|
fn TakesANullableIBinder(&self, _: 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 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 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)
|
|
}
|
|
}
|
|
|
|
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");
|
|
|
|
binder::ProcessState::join_thread_pool();
|
|
}
|