• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (null-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     let service_name = CStr::from_ptr(service_name).to_str().unwrap();
35 
36     // The Rust class descriptor pointer will not match the NDK one, but the
37     // descriptor strings match so this needs to still associate.
38     let service: binder::Strong<dyn IBinderRustNdkInteropTest> =
39         match binder::get_interface(service_name) {
40             Err(e) => {
41                 eprintln!("Could not find Ndk service {}: {:?}", service_name, e);
42                 return StatusCode::NAME_NOT_FOUND as c_int;
43             }
44             Ok(service) => service,
45         };
46 
47     match service.echo("testing") {
48         Ok(s) => {
49             if s != "testing" {
50                 return StatusCode::BAD_VALUE as c_int;
51             }
52         }
53         Err(e) => return e.into(),
54     }
55 
56     // Try using the binder service through the wrong interface type
57     let wrong_service: Result<binder::Strong<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
58         binder::get_interface(service_name);
59     match wrong_service {
60         Err(e) if e == StatusCode::BAD_TYPE => {}
61         Err(e) => {
62             eprintln!("Trying to use a service via the wrong interface errored with unexpected error {:?}", e);
63             return e as c_int;
64         }
65         Ok(_) => {
66             eprintln!("We should not be allowed to use a service via the wrong interface");
67             return StatusCode::BAD_TYPE as c_int;
68         }
69     }
70 
71     StatusCode::OK as c_int
72 }
73 
74 struct Service;
75 
76 impl Interface for Service {}
77 
78 impl IBinderRustNdkInteropTest for Service {
echo(&self, s: &str) -> binder::Result<String>79     fn echo(&self, s: &str) -> binder::Result<String> {
80         Ok(s.to_string())
81     }
82 }
83 
84 /// Start the interop Echo test service with the given service name.
85 ///
86 /// # Safety
87 ///
88 /// service_name must be a valid, non-null C-style string (null-terminated).
89 #[no_mangle]
rust_start_service(service_name: *const c_char) -> c_int90 pub unsafe extern "C" fn rust_start_service(service_name: *const c_char) -> c_int {
91     let service_name = CStr::from_ptr(service_name).to_str().unwrap();
92     let service = BnBinderRustNdkInteropTest::new_binder(Service, BinderFeatures::default());
93     match binder::add_service(&service_name, service.as_binder()) {
94         Ok(_) => StatusCode::OK as c_int,
95         Err(e) => e as c_int,
96     }
97 }
98