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::OnceLock;
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: OnceLock<SpIBinder> = OnceLock::new();
74
75 /// Start binder service and return a raw AIBinder pointer to it.
76 ///
77 /// Safe to call multiple times, only creates the service once.
78 #[no_mangle]
rust_service() -> *mut c_void79 pub extern "C" fn rust_service() -> *mut c_void {
80 let service = SERVICE
81 .get_or_init(|| BnReadParcelTest::new_binder((), BinderFeatures::default()).as_binder());
82 // SAFETY: The SpIBinder will remain alive as long as the program is running because it is in
83 // the static SERVICE, so the pointer is valid forever.
84 unsafe { service.as_raw().cast() }
85 }
86
87 /// Empty interface just to use the declare_binder_interface macro
88 pub trait ReadParcelTest: Interface {}
89
90 declare_binder_interface! {
91 ReadParcelTest["read_parcel_test"] {
92 native: BnReadParcelTest(on_transact),
93 proxy: BpReadParcelTest,
94 }
95 }
96
97 impl ReadParcelTest for Binder<BnReadParcelTest> {}
98
99 impl ReadParcelTest for BpReadParcelTest {}
100
101 impl ReadParcelTest for () {}
102
103 #[allow(clippy::float_cmp)]
on_transact( _service: &dyn ReadParcelTest, code: TransactionCode, parcel: &BorrowedParcel<'_>, reply: &mut BorrowedParcel<'_>, ) -> Result<(), StatusCode>104 fn on_transact(
105 _service: &dyn ReadParcelTest,
106 code: TransactionCode,
107 parcel: &BorrowedParcel<'_>,
108 reply: &mut BorrowedParcel<'_>,
109 ) -> Result<(), StatusCode> {
110 match code {
111 bindings::Transaction_TEST_BOOL => {
112 assert!(parcel.read::<bool>()?);
113 assert!(!parcel.read::<bool>()?);
114 // SAFETY: Just reading an extern constant.
115 assert_eq!(parcel.read::<Vec<bool>>()?, unsafe { bindings::TESTDATA_BOOL });
116 assert_eq!(parcel.read::<Option<Vec<bool>>>()?, None);
117
118 reply.write(&true)?;
119 reply.write(&false)?;
120 // SAFETY: Just reading an extern constant.
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 // SAFETY: Just reading an extern constant.
129 assert_eq!(parcel.read::<Vec<i8>>()?, unsafe { bindings::TESTDATA_I8 });
130 // SAFETY: Just reading an extern constant.
131 assert_eq!(parcel.read::<Vec<u8>>()?, unsafe { bindings::TESTDATA_U8 });
132 assert_eq!(parcel.read::<Option<Vec<i8>>>()?, None);
133
134 reply.write(&0i8)?;
135 reply.write(&1i8)?;
136 reply.write(&i8::max_value())?;
137 // SAFETY: Just reading an extern constant.
138 reply.write(&unsafe { bindings::TESTDATA_I8 }[..])?;
139 // SAFETY: Just reading an extern constant.
140 reply.write(&unsafe { bindings::TESTDATA_U8 }[..])?;
141 reply.write(&(None as Option<Vec<i8>>))?;
142 }
143 bindings::Transaction_TEST_U16 => {
144 assert_eq!(parcel.read::<u16>()?, 0);
145 assert_eq!(parcel.read::<u16>()?, 1);
146 assert_eq!(parcel.read::<u16>()?, u16::max_value());
147 // SAFETY: Just reading an extern constant.
148 assert_eq!(parcel.read::<Vec<u16>>()?, unsafe { bindings::TESTDATA_CHARS });
149 assert_eq!(parcel.read::<Option<Vec<u16>>>()?, None);
150
151 reply.write(&0u16)?;
152 reply.write(&1u16)?;
153 reply.write(&u16::max_value())?;
154 // SAFETY: Just reading an extern constant.
155 reply.write(&unsafe { bindings::TESTDATA_CHARS }[..])?;
156 reply.write(&(None as Option<Vec<u16>>))?;
157 }
158 bindings::Transaction_TEST_I32 => {
159 assert_eq!(parcel.read::<i32>()?, 0);
160 assert_eq!(parcel.read::<i32>()?, 1);
161 assert_eq!(parcel.read::<i32>()?, i32::max_value());
162 // SAFETY: Just reading an extern constant.
163 assert_eq!(parcel.read::<Vec<i32>>()?, unsafe { bindings::TESTDATA_I32 });
164 assert_eq!(parcel.read::<Option<Vec<i32>>>()?, None);
165
166 reply.write(&0i32)?;
167 reply.write(&1i32)?;
168 reply.write(&i32::max_value())?;
169 // SAFETY: Just reading an extern constant.
170 reply.write(&unsafe { bindings::TESTDATA_I32 }[..])?;
171 reply.write(&(None as Option<Vec<i32>>))?;
172 }
173 bindings::Transaction_TEST_I64 => {
174 assert_eq!(parcel.read::<i64>()?, 0);
175 assert_eq!(parcel.read::<i64>()?, 1);
176 assert_eq!(parcel.read::<i64>()?, i64::max_value());
177 // SAFETY: Just reading an extern constant.
178 assert_eq!(parcel.read::<Vec<i64>>()?, unsafe { bindings::TESTDATA_I64 });
179 assert_eq!(parcel.read::<Option<Vec<i64>>>()?, None);
180
181 reply.write(&0i64)?;
182 reply.write(&1i64)?;
183 reply.write(&i64::max_value())?;
184 // SAFETY: Just reading an extern constant.
185 reply.write(&unsafe { bindings::TESTDATA_I64 }[..])?;
186 reply.write(&(None as Option<Vec<i64>>))?;
187 }
188 bindings::Transaction_TEST_U64 => {
189 assert_eq!(parcel.read::<u64>()?, 0);
190 assert_eq!(parcel.read::<u64>()?, 1);
191 assert_eq!(parcel.read::<u64>()?, u64::max_value());
192 // SAFETY: Just reading an extern constant.
193 assert_eq!(parcel.read::<Vec<u64>>()?, unsafe { bindings::TESTDATA_U64 });
194 assert_eq!(parcel.read::<Option<Vec<u64>>>()?, None);
195
196 reply.write(&0u64)?;
197 reply.write(&1u64)?;
198 reply.write(&u64::max_value())?;
199 // SAFETY: Just reading an extern constant.
200 reply.write(&unsafe { bindings::TESTDATA_U64 }[..])?;
201 reply.write(&(None as Option<Vec<u64>>))?;
202 }
203 bindings::Transaction_TEST_F32 => {
204 assert_eq!(parcel.read::<f32>()?, 0f32);
205 let floats = parcel.read::<Vec<f32>>()?;
206 assert!(floats[0].is_nan());
207 // SAFETY: Just reading an extern constant.
208 assert_eq!(floats[1..], unsafe { bindings::TESTDATA_FLOAT }[1..]);
209 assert_eq!(parcel.read::<Option<Vec<f32>>>()?, None);
210
211 reply.write(&0f32)?;
212 // SAFETY: Just reading an extern constant.
213 reply.write(&unsafe { bindings::TESTDATA_FLOAT }[..])?;
214 reply.write(&(None as Option<Vec<f32>>))?;
215 }
216 bindings::Transaction_TEST_F64 => {
217 assert_eq!(parcel.read::<f64>()?, 0f64);
218 let doubles = parcel.read::<Vec<f64>>()?;
219 assert!(doubles[0].is_nan());
220 // SAFETY: Just reading an extern constant.
221 assert_eq!(doubles[1..], unsafe { bindings::TESTDATA_DOUBLE }[1..]);
222 assert_eq!(parcel.read::<Option<Vec<f64>>>()?, None);
223
224 reply.write(&0f64)?;
225 // SAFETY: Just reading an extern constant.
226 reply.write(&unsafe { bindings::TESTDATA_DOUBLE }[..])?;
227 reply.write(&(None as Option<Vec<f64>>))?;
228 }
229 bindings::Transaction_TEST_STRING => {
230 let s: Option<String> = parcel.read()?;
231 assert_eq!(s.as_deref(), Some("testing"));
232 let s: Option<String> = parcel.read()?;
233 assert_eq!(s, None);
234 let s: Option<Vec<Option<String>>> = parcel.read()?;
235 // SAFETY: Just reading an extern constant.
236 for (s, expected) in s.unwrap().iter().zip(unsafe { bindings::TESTDATA_STRS }.iter()) {
237 let expected =
238 // SAFETY: Just reading an extern constant.
239 unsafe { expected.as_ref().and_then(|e| CStr::from_ptr(e).to_str().ok()) };
240 assert_eq!(s.as_deref(), expected);
241 }
242 let s: Option<Vec<Option<String>>> = parcel.read()?;
243 assert_eq!(s, None);
244
245 // SAFETY: Just reading an extern constant.
246 let strings: Vec<Option<String>> = unsafe {
247 bindings::TESTDATA_STRS
248 .iter()
249 .map(|s| {
250 s.as_ref().map(|s| {
251 CStr::from_ptr(s).to_str().expect("String was not UTF-8").to_owned()
252 })
253 })
254 .collect()
255 };
256
257 reply.write("testing")?;
258 reply.write(&(None as Option<String>))?;
259 reply.write(&strings)?;
260 reply.write(&(None as Option<Vec<String>>))?;
261 }
262 bindings::Transaction_TEST_FILE_DESCRIPTOR => {
263 let file1 = parcel.read::<ParcelFileDescriptor>()?;
264 let file2 = parcel.read::<ParcelFileDescriptor>()?;
265 let files = parcel.read::<Vec<Option<ParcelFileDescriptor>>>()?;
266
267 reply.write(&file1)?;
268 reply.write(&file2)?;
269 reply.write(&files)?;
270 }
271 bindings::Transaction_TEST_IBINDER => {
272 assert!(parcel.read::<Option<SpIBinder>>()?.is_some());
273 assert!(parcel.read::<Option<SpIBinder>>()?.is_none());
274 let ibinders = parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.unwrap();
275 assert_eq!(ibinders.len(), 2);
276 assert!(ibinders[0].is_some());
277 assert!(ibinders[1].is_none());
278 assert!(parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.is_none());
279
280 let service = SERVICE.get().expect("Global binder service not initialized").clone();
281 reply.write(&service)?;
282 reply.write(&(None as Option<&SpIBinder>))?;
283 reply.write(&[Some(&service), None][..])?;
284 reply.write(&(None as Option<Vec<Option<&SpIBinder>>>))?;
285 }
286 bindings::Transaction_TEST_STATUS => {
287 let status: Status = parcel.read()?;
288 assert!(status.is_ok());
289 let status: Status = parcel.read()?;
290 assert_eq!(status.exception_code(), ExceptionCode::NULL_POINTER);
291 assert_eq!(status.get_description(), "Status(-4, EX_NULL_POINTER): 'a status message'");
292 let status: Status = parcel.read()?;
293 assert_eq!(status.service_specific_error(), 42);
294 assert_eq!(
295 status.get_description(),
296 "Status(-8, EX_SERVICE_SPECIFIC): '42: a service-specific error'"
297 );
298
299 reply.write(&Status::ok())?;
300 reply.write(&Status::new_exception(
301 ExceptionCode::NULL_POINTER,
302 Some(&CString::new("a status message").unwrap()),
303 ))?;
304 reply.write(&Status::new_service_specific_error(
305 42,
306 Some(&CString::new("a service-specific error").unwrap()),
307 ))?;
308 }
309 bindings::Transaction_TEST_FAIL => {
310 assert!(false);
311 }
312 _ => return Err(StatusCode::UNKNOWN_TRANSACTION),
313 }
314
315 assert_eq!(parcel.read::<i32>(), Err(StatusCode::NOT_ENOUGH_DATA));
316 Ok(())
317 }
318