619 lines
20 KiB
Rust
619 lines
20 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_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();
|
|
}
|