• 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 //! Included as a module in the binder crate internal tests for internal API
18 //! access.
19 
20 use binder::declare_binder_interface;
21 use binder::{
22     BinderFeatures, ExceptionCode, Interface, ParcelFileDescriptor, SpIBinder, Status, StatusCode,
23 };
24 // Import from impl API for testing only, should not be necessary as long as you
25 // are using AIDL.
26 use binder::binder_impl::{Binder, BorrowedParcel, TransactionCode};
27 
28 use std::ffi::{c_void, CStr, CString};
29 use std::sync::Once;
30 
31 #[allow(
32     non_camel_case_types,
33     non_snake_case,
34     non_upper_case_globals,
35     unused,
36     improper_ctypes,
37     missing_docs,
38     clippy::all
39 )]
40 mod bindings {
41     include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
42 }
43 
44 macro_rules! assert_eq {
45     ($left:expr, $right:expr $(,)?) => {
46         match (&$left, &$right) {
47             (left, right) => {
48                 if *left != *right {
49                     eprintln!(
50                         "assertion failed: `{:?}` == `{:?}`, {}:{}:{}",
51                         &*left,
52                         &*right,
53                         file!(),
54                         line!(),
55                         column!()
56                     );
57                     return Err(StatusCode::FAILED_TRANSACTION);
58                 }
59             }
60         }
61     };
62 }
63 
64 macro_rules! assert {
65     ($expr:expr) => {
66         if !$expr {
67             eprintln!("assertion failed: `{:?}`, {}:{}:{}", $expr, file!(), line!(), column!());
68             return Err(StatusCode::FAILED_TRANSACTION);
69         }
70     };
71 }
72 
73 static SERVICE_ONCE: Once = Once::new();
74 static mut SERVICE: Option<SpIBinder> = None;
75 
76 /// Start binder service and return a raw AIBinder pointer to it.
77 ///
78 /// Safe to call multiple times, only creates the service once.
79 #[no_mangle]
rust_service() -> *mut c_void80 pub extern "C" fn rust_service() -> *mut c_void {
81     unsafe {
82         SERVICE_ONCE.call_once(|| {
83             SERVICE = Some(BnReadParcelTest::new_binder((), BinderFeatures::default()).as_binder());
84         });
85         SERVICE.as_ref().unwrap().as_raw().cast()
86     }
87 }
88 
89 /// Empty interface just to use the declare_binder_interface macro
90 pub trait ReadParcelTest: Interface {}
91 
92 declare_binder_interface! {
93     ReadParcelTest["read_parcel_test"] {
94         native: BnReadParcelTest(on_transact),
95         proxy: BpReadParcelTest,
96     }
97 }
98 
99 impl ReadParcelTest for Binder<BnReadParcelTest> {}
100 
101 impl ReadParcelTest for BpReadParcelTest {}
102 
103 impl ReadParcelTest for () {}
104 
105 #[allow(clippy::float_cmp)]
on_transact( _service: &dyn ReadParcelTest, code: TransactionCode, parcel: &BorrowedParcel<'_>, reply: &mut BorrowedParcel<'_>, ) -> Result<(), StatusCode>106 fn on_transact(
107     _service: &dyn ReadParcelTest,
108     code: TransactionCode,
109     parcel: &BorrowedParcel<'_>,
110     reply: &mut BorrowedParcel<'_>,
111 ) -> Result<(), StatusCode> {
112     match code {
113         bindings::Transaction_TEST_BOOL => {
114             assert!(parcel.read::<bool>()?);
115             assert!(!parcel.read::<bool>()?);
116             assert_eq!(parcel.read::<Vec<bool>>()?, unsafe { bindings::TESTDATA_BOOL });
117             assert_eq!(parcel.read::<Option<Vec<bool>>>()?, None);
118 
119             reply.write(&true)?;
120             reply.write(&false)?;
121             reply.write(&unsafe { bindings::TESTDATA_BOOL }[..])?;
122             reply.write(&(None as Option<Vec<bool>>))?;
123         }
124         bindings::Transaction_TEST_BYTE => {
125             assert_eq!(parcel.read::<i8>()?, 0);
126             assert_eq!(parcel.read::<i8>()?, 1);
127             assert_eq!(parcel.read::<i8>()?, i8::max_value());
128             assert_eq!(parcel.read::<Vec<i8>>()?, unsafe { bindings::TESTDATA_I8 });
129             assert_eq!(parcel.read::<Vec<u8>>()?, unsafe { bindings::TESTDATA_U8 });
130             assert_eq!(parcel.read::<Option<Vec<i8>>>()?, None);
131 
132             reply.write(&0i8)?;
133             reply.write(&1i8)?;
134             reply.write(&i8::max_value())?;
135             reply.write(&unsafe { bindings::TESTDATA_I8 }[..])?;
136             reply.write(&unsafe { bindings::TESTDATA_U8 }[..])?;
137             reply.write(&(None as Option<Vec<i8>>))?;
138         }
139         bindings::Transaction_TEST_U16 => {
140             assert_eq!(parcel.read::<u16>()?, 0);
141             assert_eq!(parcel.read::<u16>()?, 1);
142             assert_eq!(parcel.read::<u16>()?, u16::max_value());
143             assert_eq!(parcel.read::<Vec<u16>>()?, unsafe { bindings::TESTDATA_CHARS });
144             assert_eq!(parcel.read::<Option<Vec<u16>>>()?, None);
145 
146             reply.write(&0u16)?;
147             reply.write(&1u16)?;
148             reply.write(&u16::max_value())?;
149             reply.write(&unsafe { bindings::TESTDATA_CHARS }[..])?;
150             reply.write(&(None as Option<Vec<u16>>))?;
151         }
152         bindings::Transaction_TEST_I32 => {
153             assert_eq!(parcel.read::<i32>()?, 0);
154             assert_eq!(parcel.read::<i32>()?, 1);
155             assert_eq!(parcel.read::<i32>()?, i32::max_value());
156             assert_eq!(parcel.read::<Vec<i32>>()?, unsafe { bindings::TESTDATA_I32 });
157             assert_eq!(parcel.read::<Option<Vec<i32>>>()?, None);
158 
159             reply.write(&0i32)?;
160             reply.write(&1i32)?;
161             reply.write(&i32::max_value())?;
162             reply.write(&unsafe { bindings::TESTDATA_I32 }[..])?;
163             reply.write(&(None as Option<Vec<i32>>))?;
164         }
165         bindings::Transaction_TEST_I64 => {
166             assert_eq!(parcel.read::<i64>()?, 0);
167             assert_eq!(parcel.read::<i64>()?, 1);
168             assert_eq!(parcel.read::<i64>()?, i64::max_value());
169             assert_eq!(parcel.read::<Vec<i64>>()?, unsafe { bindings::TESTDATA_I64 });
170             assert_eq!(parcel.read::<Option<Vec<i64>>>()?, None);
171 
172             reply.write(&0i64)?;
173             reply.write(&1i64)?;
174             reply.write(&i64::max_value())?;
175             reply.write(&unsafe { bindings::TESTDATA_I64 }[..])?;
176             reply.write(&(None as Option<Vec<i64>>))?;
177         }
178         bindings::Transaction_TEST_U64 => {
179             assert_eq!(parcel.read::<u64>()?, 0);
180             assert_eq!(parcel.read::<u64>()?, 1);
181             assert_eq!(parcel.read::<u64>()?, u64::max_value());
182             assert_eq!(parcel.read::<Vec<u64>>()?, unsafe { bindings::TESTDATA_U64 });
183             assert_eq!(parcel.read::<Option<Vec<u64>>>()?, None);
184 
185             reply.write(&0u64)?;
186             reply.write(&1u64)?;
187             reply.write(&u64::max_value())?;
188             reply.write(&unsafe { bindings::TESTDATA_U64 }[..])?;
189             reply.write(&(None as Option<Vec<u64>>))?;
190         }
191         bindings::Transaction_TEST_F32 => {
192             assert_eq!(parcel.read::<f32>()?, 0f32);
193             let floats = parcel.read::<Vec<f32>>()?;
194             assert!(floats[0].is_nan());
195             assert_eq!(floats[1..], unsafe { bindings::TESTDATA_FLOAT }[1..]);
196             assert_eq!(parcel.read::<Option<Vec<f32>>>()?, None);
197 
198             reply.write(&0f32)?;
199             reply.write(&unsafe { bindings::TESTDATA_FLOAT }[..])?;
200             reply.write(&(None as Option<Vec<f32>>))?;
201         }
202         bindings::Transaction_TEST_F64 => {
203             assert_eq!(parcel.read::<f64>()?, 0f64);
204             let doubles = parcel.read::<Vec<f64>>()?;
205             assert!(doubles[0].is_nan());
206             assert_eq!(doubles[1..], unsafe { bindings::TESTDATA_DOUBLE }[1..]);
207             assert_eq!(parcel.read::<Option<Vec<f64>>>()?, None);
208 
209             reply.write(&0f64)?;
210             reply.write(&unsafe { bindings::TESTDATA_DOUBLE }[..])?;
211             reply.write(&(None as Option<Vec<f64>>))?;
212         }
213         bindings::Transaction_TEST_STRING => {
214             let s: Option<String> = parcel.read()?;
215             assert_eq!(s.as_deref(), Some("testing"));
216             let s: Option<String> = parcel.read()?;
217             assert_eq!(s, None);
218             let s: Option<Vec<Option<String>>> = parcel.read()?;
219             for (s, expected) in s.unwrap().iter().zip(unsafe { bindings::TESTDATA_STRS }.iter()) {
220                 let expected =
221                     unsafe { expected.as_ref().and_then(|e| CStr::from_ptr(e).to_str().ok()) };
222                 assert_eq!(s.as_deref(), expected);
223             }
224             let s: Option<Vec<Option<String>>> = parcel.read()?;
225             assert_eq!(s, None);
226 
227             let strings: Vec<Option<String>> = unsafe {
228                 bindings::TESTDATA_STRS
229                     .iter()
230                     .map(|s| {
231                         s.as_ref().map(|s| {
232                             CStr::from_ptr(s).to_str().expect("String was not UTF-8").to_owned()
233                         })
234                     })
235                     .collect()
236             };
237 
238             reply.write("testing")?;
239             reply.write(&(None as Option<String>))?;
240             reply.write(&strings)?;
241             reply.write(&(None as Option<Vec<String>>))?;
242         }
243         bindings::Transaction_TEST_FILE_DESCRIPTOR => {
244             let file1 = parcel.read::<ParcelFileDescriptor>()?;
245             let file2 = parcel.read::<ParcelFileDescriptor>()?;
246             let files = parcel.read::<Vec<Option<ParcelFileDescriptor>>>()?;
247 
248             reply.write(&file1)?;
249             reply.write(&file2)?;
250             reply.write(&files)?;
251         }
252         bindings::Transaction_TEST_IBINDER => {
253             assert!(parcel.read::<Option<SpIBinder>>()?.is_some());
254             assert!(parcel.read::<Option<SpIBinder>>()?.is_none());
255             let ibinders = parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.unwrap();
256             assert_eq!(ibinders.len(), 2);
257             assert!(ibinders[0].is_some());
258             assert!(ibinders[1].is_none());
259             assert!(parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.is_none());
260 
261             let service =
262                 unsafe { SERVICE.as_ref().expect("Global binder service not initialized").clone() };
263             reply.write(&service)?;
264             reply.write(&(None as Option<&SpIBinder>))?;
265             reply.write(&[Some(&service), None][..])?;
266             reply.write(&(None as Option<Vec<Option<&SpIBinder>>>))?;
267         }
268         bindings::Transaction_TEST_STATUS => {
269             let status: Status = parcel.read()?;
270             assert!(status.is_ok());
271             let status: Status = parcel.read()?;
272             assert_eq!(status.exception_code(), ExceptionCode::NULL_POINTER);
273             assert_eq!(status.get_description(), "Status(-4, EX_NULL_POINTER): 'a status message'");
274             let status: Status = parcel.read()?;
275             assert_eq!(status.service_specific_error(), 42);
276             assert_eq!(
277                 status.get_description(),
278                 "Status(-8, EX_SERVICE_SPECIFIC): '42: a service-specific error'"
279             );
280 
281             reply.write(&Status::ok())?;
282             reply.write(&Status::new_exception(
283                 ExceptionCode::NULL_POINTER,
284                 Some(&CString::new("a status message").unwrap()),
285             ))?;
286             reply.write(&Status::new_service_specific_error(
287                 42,
288                 Some(&CString::new("a service-specific error").unwrap()),
289             ))?;
290         }
291         bindings::Transaction_TEST_FAIL => {
292             assert!(false);
293         }
294         _ => return Err(StatusCode::UNKNOWN_TRANSACTION),
295     }
296 
297     assert_eq!(parcel.read::<i32>(), Err(StatusCode::NOT_ENOUGH_DATA));
298     Ok(())
299 }
300