xref: /aosp_15_r20/frameworks/native/libs/binder/rust/src/parcel/parcelable_holder.rs (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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  */
16 
17 use crate::binder::Stability;
18 use crate::binder::StabilityType;
19 use crate::error::StatusCode;
20 use crate::parcel::{
21     BorrowedParcel, Deserialize, Parcel, Parcelable, Serialize, NON_NULL_PARCELABLE_FLAG,
22     NULL_PARCELABLE_FLAG,
23 };
24 
25 use downcast_rs::{impl_downcast, DowncastSync};
26 use std::any::Any;
27 use std::sync::{Arc, Mutex};
28 
29 /// Metadata that `ParcelableHolder` needs for all parcelables.
30 ///
31 /// The compiler auto-generates implementations of this trait
32 /// for AIDL parcelables.
33 pub trait ParcelableMetadata {
34     /// The Binder parcelable descriptor string.
35     ///
36     /// This string is a unique identifier for a Binder parcelable.
get_descriptor() -> &'static str37     fn get_descriptor() -> &'static str;
38 
39     /// The Binder parcelable stability.
get_stability(&self) -> Stability40     fn get_stability(&self) -> Stability {
41         Stability::Local
42     }
43 }
44 
45 trait AnyParcelable: DowncastSync + Parcelable + std::fmt::Debug {}
46 impl_downcast!(sync AnyParcelable);
47 impl<T> AnyParcelable for T where T: DowncastSync + Parcelable + std::fmt::Debug {}
48 
49 #[derive(Debug, Clone)]
50 enum ParcelableHolderData {
51     Empty,
52     Parcelable { parcelable: Arc<dyn AnyParcelable>, name: String },
53     Parcel(Parcel),
54 }
55 
56 /// 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)]
64 pub 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.
71     data: Mutex<ParcelableHolderData>,
72 
73     _stability_phantom: std::marker::PhantomData<STABILITY>,
74 }
75 
76 impl<STABILITY: StabilityType> ParcelableHolder<STABILITY> {
77     /// Construct a new `ParcelableHolder` with the given stability.
new() -> Self78     pub fn new() -> Self {
79         Self {
80             data: Mutex::new(ParcelableHolderData::Empty),
81             _stability_phantom: Default::default(),
82         }
83     }
84 
85     /// Reset the contents of this `ParcelableHolder`.
86     ///
87     /// Note that this method does not reset the stability,
88     /// only the contents.
reset(&mut self)89     pub fn reset(&mut self) {
90         *self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
91         // We could also clear stability here, but C++ doesn't
92     }
93 
94     /// Set the parcelable contained in this `ParcelableHolder`.
set_parcelable<T>(&mut self, p: Arc<T>) -> Result<(), StatusCode> where T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,95     pub fn set_parcelable<T>(&mut self, p: Arc<T>) -> Result<(), StatusCode>
96     where
97         T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,
98     {
99         if STABILITY::VALUE > p.get_stability() {
100             return Err(StatusCode::BAD_VALUE);
101         }
102 
103         *self.data.get_mut().unwrap() =
104             ParcelableHolderData::Parcelable { parcelable: p, name: T::get_descriptor().into() };
105 
106         Ok(())
107     }
108 
109     /// 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
get_parcelable<T>(&self) -> Result<Option<Arc<T>>, StatusCode> where T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,122     pub fn get_parcelable<T>(&self) -> Result<Option<Arc<T>>, StatusCode>
123     where
124         T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,
125     {
126         let parcelable_desc = T::get_descriptor();
127         let mut data = self.data.lock().unwrap();
128         match *data {
129             ParcelableHolderData::Empty => Ok(None),
130             ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
131                 if name != parcelable_desc {
132                     return Err(StatusCode::BAD_VALUE);
133                 }
134 
135                 match Arc::clone(parcelable).downcast_arc::<T>() {
136                     Err(_) => Err(StatusCode::BAD_VALUE),
137                     Ok(x) => Ok(Some(x)),
138                 }
139             }
140             ParcelableHolderData::Parcel(ref mut parcel) => {
141                 // Safety: 0 should always be a valid position.
142                 unsafe {
143                     parcel.set_data_position(0)?;
144                 }
145 
146                 let name: String = parcel.read()?;
147                 if name != parcelable_desc {
148                     return Ok(None);
149                 }
150 
151                 let mut parcelable = T::default();
152                 parcelable.read_from_parcel(parcel.borrowed_ref())?;
153 
154                 let parcelable = Arc::new(parcelable);
155                 let result = Arc::clone(&parcelable);
156                 *data = ParcelableHolderData::Parcelable { parcelable, name };
157 
158                 Ok(Some(result))
159             }
160         }
161     }
162 
163     /// Return the stability value of this object.
get_stability(&self) -> Stability164     pub fn get_stability(&self) -> Stability {
165         STABILITY::VALUE
166     }
167 }
168 
169 impl<STABILITY: StabilityType> Default for ParcelableHolder<STABILITY> {
default() -> Self170     fn default() -> Self {
171         Self::new()
172     }
173 }
174 
175 impl<STABILITY: StabilityType> Clone for ParcelableHolder<STABILITY> {
clone(&self) -> Self176     fn clone(&self) -> Self {
177         ParcelableHolder {
178             data: Mutex::new(self.data.lock().unwrap().clone()),
179             _stability_phantom: Default::default(),
180         }
181     }
182 }
183 
184 impl<STABILITY: StabilityType> Serialize for ParcelableHolder<STABILITY> {
serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode>185     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
186         parcel.write(&NON_NULL_PARCELABLE_FLAG)?;
187         self.write_to_parcel(parcel)
188     }
189 }
190 
191 impl<STABILITY: StabilityType> Deserialize for ParcelableHolder<STABILITY> {
192     type UninitType = Self;
uninit() -> Self::UninitType193     fn uninit() -> Self::UninitType {
194         Self::new()
195     }
from_init(value: Self) -> Self::UninitType196     fn from_init(value: Self) -> Self::UninitType {
197         value
198     }
199 
deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self, StatusCode>200     fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self, StatusCode> {
201         let status: i32 = parcel.read()?;
202         if status == NULL_PARCELABLE_FLAG {
203             Err(StatusCode::UNEXPECTED_NULL)
204         } else {
205             let mut parcelable = Self::new();
206             parcelable.read_from_parcel(parcel)?;
207             Ok(parcelable)
208         }
209     }
210 }
211 
212 impl<STABILITY: StabilityType> Parcelable for ParcelableHolder<STABILITY> {
write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode>213     fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
214         parcel.write(&STABILITY::VALUE)?;
215 
216         let mut data = self.data.lock().unwrap();
217         match *data {
218             ParcelableHolderData::Empty => parcel.write(&0i32),
219             ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
220                 let length_start = parcel.get_data_position();
221                 parcel.write(&0i32)?;
222 
223                 let data_start = parcel.get_data_position();
224                 parcel.write(name)?;
225                 parcelable.write_to_parcel(parcel)?;
226 
227                 let end = parcel.get_data_position();
228                 // Safety: we got the position from `get_data_position`.
229                 unsafe {
230                     parcel.set_data_position(length_start)?;
231                 }
232 
233                 assert!(end >= data_start);
234                 parcel.write(&(end - data_start))?;
235                 // Safety: we got the position from `get_data_position`.
236                 unsafe {
237                     parcel.set_data_position(end)?;
238                 }
239 
240                 Ok(())
241             }
242             ParcelableHolderData::Parcel(ref mut p) => {
243                 parcel.write(&p.get_data_size())?;
244                 parcel.append_all_from(&*p)
245             }
246         }
247     }
248 
read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode>249     fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode> {
250         if self.get_stability() != parcel.read()? {
251             return Err(StatusCode::BAD_VALUE);
252         }
253 
254         let data_size: i32 = parcel.read()?;
255         if data_size < 0 {
256             // C++ returns BAD_VALUE here,
257             // while Java returns ILLEGAL_ARGUMENT
258             return Err(StatusCode::BAD_VALUE);
259         }
260         if data_size == 0 {
261             *self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
262             return Ok(());
263         }
264 
265         // 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
267         let data_start = parcel.get_data_position();
268         let data_end = data_start.checked_add(data_size).ok_or(StatusCode::BAD_VALUE)?;
269 
270         let 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);
273 
274         // 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`.
278         unsafe {
279             parcel.set_data_position(data_end)?;
280         }
281 
282         Ok(())
283     }
284 }
285