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 #pragma once 18 19 #include <binder/Parcel.h> 20 #include <binder/Parcelable.h> 21 #include <utils/String16.h> 22 #include <mutex> 23 #include <optional> 24 #include <tuple> 25 26 namespace android { 27 namespace os { 28 /* 29 * C++ implementation of the Java class android.os.ParcelableHolder 30 */ 31 class ParcelableHolder : public android::Parcelable { 32 public: 33 ParcelableHolder() = delete; ParcelableHolder(Stability stability)34 explicit ParcelableHolder(Stability stability) : mStability(stability){} 35 virtual ~ParcelableHolder() = default; ParcelableHolder(const ParcelableHolder & other)36 ParcelableHolder(const ParcelableHolder& other) { 37 mParcelable = other.mParcelable; 38 mParcelableName = other.mParcelableName; 39 if (other.mParcelPtr) { 40 mParcelPtr = std::make_unique<Parcel>(); 41 mParcelPtr->appendFrom(other.mParcelPtr.get(), 0, other.mParcelPtr->dataSize()); 42 } 43 mStability = other.mStability; 44 } 45 ParcelableHolder(ParcelableHolder&& other) = default; 46 47 status_t writeToParcel(Parcel* parcel) const override; 48 status_t readFromParcel(const Parcel* parcel) override; 49 reset()50 void reset() { 51 this->mParcelable = nullptr; 52 this->mParcelableName = std::nullopt; 53 this->mParcelPtr = nullptr; 54 } 55 56 template <typename T> setParcelable(T && p)57 status_t setParcelable(T&& p) { 58 using Tt = typename std::decay<T>::type; 59 return setParcelable<Tt>(std::make_shared<Tt>(std::forward<T>(p))); 60 } 61 62 template <typename T> setParcelable(std::shared_ptr<T> p)63 status_t setParcelable(std::shared_ptr<T> p) { 64 static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); 65 if (p && this->getStability() > p->getStability()) { 66 return android::BAD_VALUE; 67 } 68 this->mParcelable = p; 69 this->mParcelableName = T::getParcelableDescriptor(); 70 this->mParcelPtr = nullptr; 71 return android::OK; 72 } 73 74 template <typename T> getParcelable(std::shared_ptr<T> * ret)75 status_t getParcelable(std::shared_ptr<T>* ret) const { 76 static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); 77 const String16& parcelableDesc = T::getParcelableDescriptor(); 78 if (!this->mParcelPtr) { 79 if (!this->mParcelable || !this->mParcelableName) { 80 ALOGD("empty ParcelableHolder"); 81 *ret = nullptr; 82 return android::OK; 83 } else if (parcelableDesc != *mParcelableName) { 84 ALOGD("extension class name mismatch expected:%s actual:%s", 85 String8(*mParcelableName).c_str(), String8(parcelableDesc).c_str()); 86 *ret = nullptr; 87 return android::BAD_VALUE; 88 } 89 *ret = std::static_pointer_cast<T>(mParcelable); 90 return android::OK; 91 } 92 this->mParcelPtr->setDataPosition(0); 93 status_t status = this->mParcelPtr->readString16(&this->mParcelableName); 94 if (status != android::OK || parcelableDesc != this->mParcelableName) { 95 this->mParcelableName = std::nullopt; 96 *ret = nullptr; 97 return status; 98 } 99 this->mParcelable = std::make_shared<T>(); 100 status = mParcelable.get()->readFromParcel(this->mParcelPtr.get()); 101 if (status != android::OK) { 102 this->mParcelableName = std::nullopt; 103 this->mParcelable = nullptr; 104 *ret = nullptr; 105 return status; 106 } 107 this->mParcelPtr = nullptr; 108 *ret = std::static_pointer_cast<T>(mParcelable); 109 return android::OK; 110 } 111 getStability()112 Stability getStability() const override { return mStability; } 113 114 inline bool operator!=(const ParcelableHolder& rhs) const { 115 return this != &rhs; 116 } 117 inline bool operator<(const ParcelableHolder& rhs) const { 118 return this < &rhs; 119 } 120 inline bool operator<=(const ParcelableHolder& rhs) const { 121 return this <= &rhs; 122 } 123 inline bool operator==(const ParcelableHolder& rhs) const { 124 return this == &rhs; 125 } 126 inline bool operator>(const ParcelableHolder& rhs) const { 127 return this > &rhs; 128 } 129 inline bool operator>=(const ParcelableHolder& rhs) const { 130 return this >= &rhs; 131 } 132 133 private: 134 mutable std::shared_ptr<Parcelable> mParcelable; 135 mutable std::optional<String16> mParcelableName; 136 mutable std::unique_ptr<Parcel> mParcelPtr; 137 Stability mStability; 138 }; 139 } // namespace os 140 } // namespace android 141