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