1/*
2 * Copyright (C) 2021 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 */
1617use crate::binder::Stability;
18use crate::binder::StabilityType;
19use crate::error::StatusCode;
20use crate::parcel::{
21 BorrowedParcel, Deserialize, Parcel, Parcelable, Serialize, NON_NULL_PARCELABLE_FLAG,
22 NULL_PARCELABLE_FLAG,
23};
2425use downcast_rs::{impl_downcast, DowncastSync};
26use std::any::Any;
27use std::sync::{Arc, Mutex};
2829/// Metadata that `ParcelableHolder` needs for all parcelables.
30///
31/// The compiler auto-generates implementations of this trait
32/// for AIDL parcelables.
33pub trait ParcelableMetadata {
34/// The Binder parcelable descriptor string.
35 ///
36 /// This string is a unique identifier for a Binder parcelable.
37fn get_descriptor() -> &'static str;
3839/// The Binder parcelable stability.
40fn get_stability(&self) -> Stability {
41 Stability::Local
42 }
43}
4445trait AnyParcelable: DowncastSync + Parcelable + std::fmt::Debug {}
46impl_downcast!(sync AnyParcelable);
47impl<T> AnyParcelable for T where T: DowncastSync + Parcelable + std::fmt::Debug {}
4849#[derive(Debug, Clone)]
50enum ParcelableHolderData {
51 Empty,
52 Parcelable { parcelable: Arc<dyn AnyParcelable>, name: String },
53 Parcel(Parcel),
54}
5556/// A container that can hold any arbitrary `Parcelable`.
57///
58/// This type is currently used for AIDL parcelable fields.
59///
60/// `ParcelableHolder` is currently not thread-safe (neither
61/// `Send` nor `Sync`), mainly because it internally contains
62/// a `Parcel` which in turn is not thread-safe.
63#[derive(Debug)]
64pub struct ParcelableHolder<STABILITY: StabilityType> {
65// This is a `Mutex` because of `get_parcelable`
66 // which takes `&self` for consistency with C++.
67 // We could make `get_parcelable` take a `&mut self`
68 // and get rid of the `Mutex` here for a performance
69 // improvement, but then callers would require a mutable
70 // `ParcelableHolder` even for that getter method.
71data: Mutex<ParcelableHolderData>,
7273 _stability_phantom: std::marker::PhantomData<STABILITY>,
74}
7576impl<STABILITY: StabilityType> ParcelableHolder<STABILITY> {
77/// Construct a new `ParcelableHolder` with the given stability.
78pub fn new() -> Self {
79Self {
80 data: Mutex::new(ParcelableHolderData::Empty),
81 _stability_phantom: Default::default(),
82 }
83 }
8485/// Reset the contents of this `ParcelableHolder`.
86 ///
87 /// Note that this method does not reset the stability,
88 /// only the contents.
89pub fn reset(&mut self) {
90*self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
91// We could also clear stability here, but C++ doesn't
92}
9394/// Set the parcelable contained in this `ParcelableHolder`.
95pub fn set_parcelable<T>(&mut self, p: Arc<T>) -> Result<(), StatusCode>
96where
97T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,
98 {
99if STABILITY::VALUE > p.get_stability() {
100return Err(StatusCode::BAD_VALUE);
101 }
102103*self.data.get_mut().unwrap() =
104 ParcelableHolderData::Parcelable { parcelable: p, name: T::get_descriptor().into() };
105106Ok(())
107 }
108109/// Retrieve the parcelable stored in this `ParcelableHolder`.
110 ///
111 /// This method attempts to retrieve the parcelable inside
112 /// the current object as a parcelable of type `T`.
113 /// The object is validated against `T` by checking that
114 /// its parcelable descriptor matches the one returned
115 /// by `T::get_descriptor()`.
116 ///
117 /// Returns one of the following:
118 /// * `Err(_)` in case of error
119 /// * `Ok(None)` if the holder is empty or the descriptor does not match
120 /// * `Ok(Some(_))` if the object holds a parcelable of type `T`
121 /// with the correct descriptor
122pub fn get_parcelable<T>(&self) -> Result<Option<Arc<T>>, StatusCode>
123where
124T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,
125 {
126let parcelable_desc = T::get_descriptor();
127let mut data = self.data.lock().unwrap();
128match *data {
129 ParcelableHolderData::Empty => Ok(None),
130 ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
131if name != parcelable_desc {
132return Err(StatusCode::BAD_VALUE);
133 }
134135match Arc::clone(parcelable).downcast_arc::<T>() {
136Err(_) => Err(StatusCode::BAD_VALUE),
137Ok(x) => Ok(Some(x)),
138 }
139 }
140 ParcelableHolderData::Parcel(ref mut parcel) => {
141// Safety: 0 should always be a valid position.
142unsafe {
143 parcel.set_data_position(0)?;
144 }
145146let name: String = parcel.read()?;
147if name != parcelable_desc {
148return Ok(None);
149 }
150151let mut parcelable = T::default();
152 parcelable.read_from_parcel(parcel.borrowed_ref())?;
153154let parcelable = Arc::new(parcelable);
155let result = Arc::clone(&parcelable);
156*data = ParcelableHolderData::Parcelable { parcelable, name };
157158Ok(Some(result))
159 }
160 }
161 }
162163/// Return the stability value of this object.
164pub fn get_stability(&self) -> Stability {
165 STABILITY::VALUE
166 }
167}
168169impl<STABILITY: StabilityType> Default for ParcelableHolder<STABILITY> {
170fn default() -> Self {
171Self::new()
172 }
173}
174175impl<STABILITY: StabilityType> Clone for ParcelableHolder<STABILITY> {
176fn clone(&self) -> Self {
177 ParcelableHolder {
178 data: Mutex::new(self.data.lock().unwrap().clone()),
179 _stability_phantom: Default::default(),
180 }
181 }
182}
183184impl<STABILITY: StabilityType> Serialize for ParcelableHolder<STABILITY> {
185fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
186 parcel.write(&NON_NULL_PARCELABLE_FLAG)?;
187self.write_to_parcel(parcel)
188 }
189}
190191impl<STABILITY: StabilityType> Deserialize for ParcelableHolder<STABILITY> {
192type UninitType = Self;
193fn uninit() -> Self::UninitType {
194Self::new()
195 }
196fn from_init(value: Self) -> Self::UninitType {
197 value
198 }
199200fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self, StatusCode> {
201let status: i32 = parcel.read()?;
202if status == NULL_PARCELABLE_FLAG {
203Err(StatusCode::UNEXPECTED_NULL)
204 } else {
205let mut parcelable = Self::new();
206 parcelable.read_from_parcel(parcel)?;
207Ok(parcelable)
208 }
209 }
210}
211212impl<STABILITY: StabilityType> Parcelable for ParcelableHolder<STABILITY> {
213fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
214 parcel.write(&STABILITY::VALUE)?;
215216let mut data = self.data.lock().unwrap();
217match *data {
218 ParcelableHolderData::Empty => parcel.write(&0i32),
219 ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
220let length_start = parcel.get_data_position();
221 parcel.write(&0i32)?;
222223let data_start = parcel.get_data_position();
224 parcel.write(name)?;
225 parcelable.write_to_parcel(parcel)?;
226227let end = parcel.get_data_position();
228// Safety: we got the position from `get_data_position`.
229unsafe {
230 parcel.set_data_position(length_start)?;
231 }
232233assert!(end >= data_start);
234 parcel.write(&(end - data_start))?;
235// Safety: we got the position from `get_data_position`.
236unsafe {
237 parcel.set_data_position(end)?;
238 }
239240Ok(())
241 }
242 ParcelableHolderData::Parcel(ref mut p) => {
243 parcel.write(&p.get_data_size())?;
244 parcel.append_all_from(&*p)
245 }
246 }
247 }
248249fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode> {
250if self.get_stability() != parcel.read()? {
251return Err(StatusCode::BAD_VALUE);
252 }
253254let data_size: i32 = parcel.read()?;
255if data_size < 0 {
256// C++ returns BAD_VALUE here,
257 // while Java returns ILLEGAL_ARGUMENT
258return Err(StatusCode::BAD_VALUE);
259 }
260if data_size == 0 {
261*self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
262return Ok(());
263 }
264265// TODO: C++ ParcelableHolder accepts sizes up to SIZE_MAX here, but we
266 // only go up to i32::MAX because that's what our API uses everywhere
267let data_start = parcel.get_data_position();
268let data_end = data_start.checked_add(data_size).ok_or(StatusCode::BAD_VALUE)?;
269270let mut new_parcel = Parcel::new();
271 new_parcel.append_from(parcel, data_start, data_size)?;
272*self.data.get_mut().unwrap() = ParcelableHolderData::Parcel(new_parcel);
273274// Safety: `append_from` checks if `data_size` overflows
275 // `parcel` and returns `BAD_VALUE` if that happens. We also
276 // explicitly check for negative and zero `data_size` above,
277 // so `data_end` is guaranteed to be greater than `data_start`.
278unsafe {
279 parcel.set_data_position(data_end)?;
280 }
281282Ok(())
283 }
284}