1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/*
* 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.
*/
//! Rust Binder NDK interop tests
use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTest::{
BnBinderRustNdkInteropTest, IBinderRustNdkInteropTest,
};
use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTestOther::IBinderRustNdkInteropTestOther;
use ::IBinderRustNdkInteropTest::binder::{self, BinderFeatures, Interface, StatusCode};
use std::ffi::CStr;
use std::os::raw::{c_char, c_int};
/// Look up the provided AIDL service and call its echo method.
///
/// # Safety
///
/// service_name must be a valid, non-null C-style string (nul-terminated).
#[no_mangle]
pub unsafe extern "C" fn rust_call_ndk(service_name: *const c_char) -> c_int {
// SAFETY: Our caller promises that service_name is a valid C string.
let service_name = unsafe { CStr::from_ptr(service_name) }.to_str().unwrap();
// The Rust class descriptor pointer will not match the NDK one, but the
// descriptor strings match so this needs to still associate.
let service: binder::Strong<dyn IBinderRustNdkInteropTest> =
match binder::get_interface(service_name) {
Err(e) => {
eprintln!("Could not find Ndk service {}: {:?}", service_name, e);
return StatusCode::NAME_NOT_FOUND as c_int;
}
Ok(service) => service,
};
match service.echo("testing") {
Ok(s) => {
if s != "testing" {
return StatusCode::BAD_VALUE as c_int;
}
}
Err(e) => return e.into(),
}
// Try using the binder service through the wrong interface type
let wrong_service: Result<binder::Strong<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
binder::get_interface(service_name);
match wrong_service {
Err(StatusCode::BAD_TYPE) => {}
Err(e) => {
eprintln!("Trying to use a service via the wrong interface errored with unexpected error {:?}", e);
return e as c_int;
}
Ok(_) => {
eprintln!("We should not be allowed to use a service via the wrong interface");
return StatusCode::BAD_TYPE as c_int;
}
}
StatusCode::OK as c_int
}
struct Service;
impl Interface for Service {}
impl IBinderRustNdkInteropTest for Service {
fn echo(&self, s: &str) -> binder::Result<String> {
Ok(s.to_string())
}
}
/// Start the interop Echo test service with the given service name.
///
/// # Safety
///
/// service_name must be a valid, non-null C-style string (nul-terminated).
#[no_mangle]
pub unsafe extern "C" fn rust_start_service(service_name: *const c_char) -> c_int {
// SAFETY: Our caller promises that service_name is a valid C string.
let service_name = unsafe { CStr::from_ptr(service_name) }.to_str().unwrap();
let service = BnBinderRustNdkInteropTest::new_binder(Service, BinderFeatures::default());
match binder::add_service(service_name, service.as_binder()) {
Ok(_) => StatusCode::OK as c_int,
Err(e) => e as c_int,
}
}
|