1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //! Rust Binder NDK interop tests
18
19 use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTest::{
20 BnBinderRustNdkInteropTest, IBinderRustNdkInteropTest,
21 };
22 use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTestOther::IBinderRustNdkInteropTestOther;
23 use ::IBinderRustNdkInteropTest::binder::{self, BinderFeatures, Interface, StatusCode};
24 use std::ffi::CStr;
25 use std::os::raw::{c_char, c_int};
26
27 /// Look up the provided AIDL service and call its echo method.
28 ///
29 /// # Safety
30 ///
31 /// service_name must be a valid, non-null C-style string (nul-terminated).
32 #[no_mangle]
rust_call_ndk(service_name: *const c_char) -> c_int33 pub unsafe extern "C" fn rust_call_ndk(service_name: *const c_char) -> c_int {
34 // SAFETY: Our caller promises that service_name is a valid C string.
35 let service_name = unsafe { CStr::from_ptr(service_name) }.to_str().unwrap();
36
37 // The Rust class descriptor pointer will not match the NDK one, but the
38 // descriptor strings match so this needs to still associate.
39 let service: binder::Strong<dyn IBinderRustNdkInteropTest> =
40 match binder::get_interface(service_name) {
41 Err(e) => {
42 eprintln!("Could not find Ndk service {}: {:?}", service_name, e);
43 return StatusCode::NAME_NOT_FOUND as c_int;
44 }
45 Ok(service) => service,
46 };
47
48 match service.echo("testing") {
49 Ok(s) => {
50 if s != "testing" {
51 return StatusCode::BAD_VALUE as c_int;
52 }
53 }
54 Err(e) => return e.into(),
55 }
56
57 // Try using the binder service through the wrong interface type
58 let wrong_service: Result<binder::Strong<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
59 binder::get_interface(service_name);
60 match wrong_service {
61 Err(StatusCode::BAD_TYPE) => {}
62 Err(e) => {
63 eprintln!("Trying to use a service via the wrong interface errored with unexpected error {:?}", e);
64 return e as c_int;
65 }
66 Ok(_) => {
67 eprintln!("We should not be allowed to use a service via the wrong interface");
68 return StatusCode::BAD_TYPE as c_int;
69 }
70 }
71
72 StatusCode::OK as c_int
73 }
74
75 struct Service;
76
77 impl Interface for Service {}
78
79 impl IBinderRustNdkInteropTest for Service {
echo(&self, s: &str) -> binder::Result<String>80 fn echo(&self, s: &str) -> binder::Result<String> {
81 Ok(s.to_string())
82 }
83 }
84
85 /// Start the interop Echo test service with the given service name.
86 ///
87 /// # Safety
88 ///
89 /// service_name must be a valid, non-null C-style string (nul-terminated).
90 #[no_mangle]
rust_start_service(service_name: *const c_char) -> c_int91 pub unsafe extern "C" fn rust_start_service(service_name: *const c_char) -> c_int {
92 // SAFETY: Our caller promises that service_name is a valid C string.
93 let service_name = unsafe { CStr::from_ptr(service_name) }.to_str().unwrap();
94 let service = BnBinderRustNdkInteropTest::new_binder(Service, BinderFeatures::default());
95 match binder::add_service(service_name, service.as_binder()) {
96 Ok(_) => StatusCode::OK as c_int,
97 Err(e) => e as c_int,
98 }
99 }
100