blob: f6bdf5c9edc736332ca4ad16e1f1f2a046cd3c81 [file] [log] [blame]
Stephen Craned58bce02020-07-07 12:26:02 -07001/*
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
20use binder::declare_binder_interface;
21use binder::{
Stephen Cranef2735b42022-01-19 17:49:46 +000022 BinderFeatures, ExceptionCode, Interface, ParcelFileDescriptor, SpIBinder, Status, StatusCode,
Stephen Craned58bce02020-07-07 12:26:02 -070023};
Stephen Cranef2735b42022-01-19 17:49:46 +000024// Import from impl API for testing only, should not be necessary as long as you
25// are using AIDL.
26use binder::binder_impl::{BorrowedParcel, Binder, TransactionCode};
Stephen Craned58bce02020-07-07 12:26:02 -070027
28use std::ffi::{c_void, CStr, CString};
Stephen Craned58bce02020-07-07 12:26:02 -070029use 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)]
40mod bindings {
41 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
42}
43
Stephen Crane1729e902021-02-15 11:05:43 -080044macro_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
64macro_rules! assert {
65 ($expr:expr) => {
66 if !$expr {
67 eprintln!(
68 "assertion failed: `{:?}`, {}:{}:{}",
69 $expr,
70 file!(),
71 line!(),
72 column!()
73 );
74 return Err(StatusCode::FAILED_TRANSACTION);
75 }
76 };
77}
78
Stephen Craned58bce02020-07-07 12:26:02 -070079static SERVICE_ONCE: Once = Once::new();
80static mut SERVICE: Option<SpIBinder> = None;
81
82/// Start binder service and return a raw AIBinder pointer to it.
83///
84/// Safe to call multiple times, only creates the service once.
85#[no_mangle]
86pub extern "C" fn rust_service() -> *mut c_void {
87 unsafe {
88 SERVICE_ONCE.call_once(|| {
Andrew Walbran88eca4f2021-04-13 14:26:01 +000089 SERVICE = Some(BnReadParcelTest::new_binder((), BinderFeatures::default()).as_binder());
Stephen Craned58bce02020-07-07 12:26:02 -070090 });
91 SERVICE.as_ref().unwrap().as_raw().cast()
92 }
93}
94
95/// Empty interface just to use the declare_binder_interface macro
96pub trait ReadParcelTest: Interface {}
97
98declare_binder_interface! {
99 ReadParcelTest["read_parcel_test"] {
100 native: BnReadParcelTest(on_transact),
101 proxy: BpReadParcelTest,
102 }
103}
104
105impl ReadParcelTest for Binder<BnReadParcelTest> {}
106
107impl ReadParcelTest for BpReadParcelTest {}
108
109impl ReadParcelTest for () {}
110
Stephen Craned58bce02020-07-07 12:26:02 -0700111#[allow(clippy::float_cmp)]
Andrew Walbran88eca4f2021-04-13 14:26:01 +0000112fn on_transact(
113 _service: &dyn ReadParcelTest,
114 code: TransactionCode,
Alice Ryhl8618c482021-11-09 15:35:35 +0000115 parcel: &BorrowedParcel<'_>,
116 reply: &mut BorrowedParcel<'_>,
Stephen Cranef2735b42022-01-19 17:49:46 +0000117) -> Result<(), StatusCode> {
Stephen Craned58bce02020-07-07 12:26:02 -0700118 match code {
119 bindings::Transaction_TEST_BOOL => {
Chris Wailese1f91f72022-04-19 17:26:39 -0700120 assert!(parcel.read::<bool>()?);
121 assert!(!parcel.read::<bool>()?);
Stephen Craned58bce02020-07-07 12:26:02 -0700122 assert_eq!(parcel.read::<Vec<bool>>()?, unsafe {
123 bindings::TESTDATA_BOOL
124 });
125 assert_eq!(parcel.read::<Option<Vec<bool>>>()?, None);
126
127 reply.write(&true)?;
128 reply.write(&false)?;
129 reply.write(&unsafe { bindings::TESTDATA_BOOL }[..])?;
130 reply.write(&(None as Option<Vec<bool>>))?;
131 }
132 bindings::Transaction_TEST_BYTE => {
133 assert_eq!(parcel.read::<i8>()?, 0);
134 assert_eq!(parcel.read::<i8>()?, 1);
135 assert_eq!(parcel.read::<i8>()?, i8::max_value());
136 assert_eq!(parcel.read::<Vec<i8>>()?, unsafe { bindings::TESTDATA_I8 });
137 assert_eq!(parcel.read::<Vec<u8>>()?, unsafe { bindings::TESTDATA_U8 });
138 assert_eq!(parcel.read::<Option<Vec<i8>>>()?, None);
139
140 reply.write(&0i8)?;
141 reply.write(&1i8)?;
142 reply.write(&i8::max_value())?;
143 reply.write(&unsafe { bindings::TESTDATA_I8 }[..])?;
144 reply.write(&unsafe { bindings::TESTDATA_U8 }[..])?;
145 reply.write(&(None as Option<Vec<i8>>))?;
146 }
147 bindings::Transaction_TEST_U16 => {
148 assert_eq!(parcel.read::<u16>()?, 0);
149 assert_eq!(parcel.read::<u16>()?, 1);
150 assert_eq!(parcel.read::<u16>()?, u16::max_value());
151 assert_eq!(parcel.read::<Vec<u16>>()?, unsafe {
152 bindings::TESTDATA_CHARS
153 });
154 assert_eq!(parcel.read::<Option<Vec<u16>>>()?, None);
155
156 reply.write(&0u16)?;
157 reply.write(&1u16)?;
158 reply.write(&u16::max_value())?;
159 reply.write(&unsafe { bindings::TESTDATA_CHARS }[..])?;
160 reply.write(&(None as Option<Vec<u16>>))?;
161 }
162 bindings::Transaction_TEST_I32 => {
163 assert_eq!(parcel.read::<i32>()?, 0);
164 assert_eq!(parcel.read::<i32>()?, 1);
165 assert_eq!(parcel.read::<i32>()?, i32::max_value());
166 assert_eq!(parcel.read::<Vec<i32>>()?, unsafe {
167 bindings::TESTDATA_I32
168 });
169 assert_eq!(parcel.read::<Option<Vec<i32>>>()?, None);
170
171 reply.write(&0i32)?;
172 reply.write(&1i32)?;
173 reply.write(&i32::max_value())?;
174 reply.write(&unsafe { bindings::TESTDATA_I32 }[..])?;
175 reply.write(&(None as Option<Vec<i32>>))?;
176 }
177 bindings::Transaction_TEST_I64 => {
178 assert_eq!(parcel.read::<i64>()?, 0);
179 assert_eq!(parcel.read::<i64>()?, 1);
180 assert_eq!(parcel.read::<i64>()?, i64::max_value());
181 assert_eq!(parcel.read::<Vec<i64>>()?, unsafe {
182 bindings::TESTDATA_I64
183 });
184 assert_eq!(parcel.read::<Option<Vec<i64>>>()?, None);
185
186 reply.write(&0i64)?;
187 reply.write(&1i64)?;
188 reply.write(&i64::max_value())?;
189 reply.write(&unsafe { bindings::TESTDATA_I64 }[..])?;
190 reply.write(&(None as Option<Vec<i64>>))?;
191 }
192 bindings::Transaction_TEST_U64 => {
193 assert_eq!(parcel.read::<u64>()?, 0);
194 assert_eq!(parcel.read::<u64>()?, 1);
195 assert_eq!(parcel.read::<u64>()?, u64::max_value());
196 assert_eq!(parcel.read::<Vec<u64>>()?, unsafe {
197 bindings::TESTDATA_U64
198 });
199 assert_eq!(parcel.read::<Option<Vec<u64>>>()?, None);
200
201 reply.write(&0u64)?;
202 reply.write(&1u64)?;
203 reply.write(&u64::max_value())?;
204 reply.write(&unsafe { bindings::TESTDATA_U64 }[..])?;
205 reply.write(&(None as Option<Vec<u64>>))?;
206 }
207 bindings::Transaction_TEST_F32 => {
208 assert_eq!(parcel.read::<f32>()?, 0f32);
209 let floats = parcel.read::<Vec<f32>>()?;
210 assert!(floats[0].is_nan());
211 assert_eq!(floats[1..], unsafe { bindings::TESTDATA_FLOAT }[1..]);
212 assert_eq!(parcel.read::<Option<Vec<f32>>>()?, None);
213
214 reply.write(&0f32)?;
215 reply.write(&unsafe { bindings::TESTDATA_FLOAT }[..])?;
216 reply.write(&(None as Option<Vec<f32>>))?;
217 }
218 bindings::Transaction_TEST_F64 => {
219 assert_eq!(parcel.read::<f64>()?, 0f64);
220 let doubles = parcel.read::<Vec<f64>>()?;
221 assert!(doubles[0].is_nan());
222 assert_eq!(doubles[1..], unsafe { bindings::TESTDATA_DOUBLE }[1..]);
223 assert_eq!(parcel.read::<Option<Vec<f64>>>()?, None);
224
225 reply.write(&0f64)?;
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 for (s, expected) in s
236 .unwrap()
237 .iter()
238 .zip(unsafe { bindings::TESTDATA_STRS }.iter())
239 {
240 let expected = unsafe {
241 expected
242 .as_ref()
243 .and_then(|e| CStr::from_ptr(e).to_str().ok())
244 };
245 assert_eq!(s.as_deref(), expected);
246 }
247 let s: Option<Vec<Option<String>>> = parcel.read()?;
248 assert_eq!(s, None);
249
250 let strings: Vec<Option<String>> = unsafe {
251 bindings::TESTDATA_STRS
252 .iter()
253 .map(|s| {
254 s.as_ref().map(|s| {
255 CStr::from_ptr(s)
256 .to_str()
257 .expect("String was not UTF-8")
258 .to_owned()
259 })
260 })
261 .collect()
262 };
263
264 reply.write("testing")?;
265 reply.write(&(None as Option<String>))?;
266 reply.write(&strings)?;
267 reply.write(&(None as Option<Vec<String>>))?;
268 }
269 bindings::Transaction_TEST_FILE_DESCRIPTOR => {
270 let file1 = parcel.read::<ParcelFileDescriptor>()?;
271 let file2 = parcel.read::<ParcelFileDescriptor>()?;
272 let files = parcel.read::<Vec<Option<ParcelFileDescriptor>>>()?;
273
274 reply.write(&file1)?;
275 reply.write(&file2)?;
276 reply.write(&files)?;
277 }
278 bindings::Transaction_TEST_IBINDER => {
279 assert!(parcel.read::<Option<SpIBinder>>()?.is_some());
280 assert!(parcel.read::<Option<SpIBinder>>()?.is_none());
281 let ibinders = parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.unwrap();
282 assert_eq!(ibinders.len(), 2);
283 assert!(ibinders[0].is_some());
284 assert!(ibinders[1].is_none());
285 assert!(parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.is_none());
286
287 let service = unsafe {
288 SERVICE
289 .as_ref()
290 .expect("Global binder service not initialized")
291 .clone()
292 };
293 reply.write(&service)?;
294 reply.write(&(None as Option<&SpIBinder>))?;
295 reply.write(&[Some(&service), None][..])?;
296 reply.write(&(None as Option<Vec<Option<&SpIBinder>>>))?;
297 }
298 bindings::Transaction_TEST_STATUS => {
299 let status: Status = parcel.read()?;
300 assert!(status.is_ok());
301 let status: Status = parcel.read()?;
302 assert_eq!(status.exception_code(), ExceptionCode::NULL_POINTER);
303 assert_eq!(
304 status.get_description(),
305 "Status(-4, EX_NULL_POINTER): 'a status message'"
306 );
307 let status: Status = parcel.read()?;
308 assert_eq!(status.service_specific_error(), 42);
309 assert_eq!(
310 status.get_description(),
311 "Status(-8, EX_SERVICE_SPECIFIC): '42: a service-specific error'"
312 );
313
314 reply.write(&Status::ok())?;
315 reply.write(&Status::new_exception(
316 ExceptionCode::NULL_POINTER,
317 Some(&CString::new("a status message").unwrap()),
318 ))?;
319 reply.write(&Status::new_service_specific_error(
320 42,
321 Some(&CString::new("a service-specific error").unwrap()),
322 ))?;
323 }
324 bindings::Transaction_TEST_FAIL => {
Stephen Crane1729e902021-02-15 11:05:43 -0800325 assert!(false);
Stephen Craned58bce02020-07-07 12:26:02 -0700326 }
327 _ => return Err(StatusCode::UNKNOWN_TRANSACTION),
328 }
329
330 assert_eq!(parcel.read::<i32>(), Err(StatusCode::NOT_ENOUGH_DATA));
331 Ok(())
332}