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