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 
46     status_t writeToParcel(Parcel* parcel) const override;
47     status_t readFromParcel(const Parcel* parcel) override;
48 
reset()49     void reset() {
50         this->mParcelable = nullptr;
51         this->mParcelableName = std::nullopt;
52         this->mParcelPtr = nullptr;
53     }
54 
55     template <typename T>
setParcelable(T && p)56     status_t setParcelable(T&& p) {
57         using Tt = typename std::decay<T>::type;
58         return setParcelable<Tt>(std::make_shared<Tt>(std::forward<T>(p)));
59     }
60 
61     template <typename T>
setParcelable(std::shared_ptr<T> p)62     status_t setParcelable(std::shared_ptr<T> p) {
63         static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
64         if (p && this->getStability() > p->getStability()) {
65             return android::BAD_VALUE;
66         }
67         this->mParcelable = p;
68         this->mParcelableName = T::getParcelableDescriptor();
69         this->mParcelPtr = nullptr;
70         return android::OK;
71     }
72 
73     template <typename T>
getParcelable(std::shared_ptr<T> * ret)74     status_t getParcelable(std::shared_ptr<T>* ret) const {
75         static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
76         const String16& parcelableDesc = T::getParcelableDescriptor();
77         if (!this->mParcelPtr) {
78             if (!this->mParcelable || !this->mParcelableName) {
79                 ALOGD("empty ParcelableHolder");
80                 *ret = nullptr;
81                 return android::OK;
82             } else if (parcelableDesc != *mParcelableName) {
83                 ALOGD("extension class name mismatch expected:%s actual:%s",
84                       String8(*mParcelableName).c_str(), String8(parcelableDesc).c_str());
85                 *ret = nullptr;
86                 return android::BAD_VALUE;
87             }
88             *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
89             return android::OK;
90         }
91         this->mParcelPtr->setDataPosition(0);
92         status_t status = this->mParcelPtr->readString16(&this->mParcelableName);
93         if (status != android::OK || parcelableDesc != this->mParcelableName) {
94             this->mParcelableName = std::nullopt;
95             *ret = nullptr;
96             return status;
97         }
98         this->mParcelable = std::make_shared<T>();
99         status = mParcelable.get()->readFromParcel(this->mParcelPtr.get());
100         if (status != android::OK) {
101             this->mParcelableName = std::nullopt;
102             this->mParcelable = nullptr;
103             *ret = nullptr;
104             return status;
105         }
106         this->mParcelPtr = nullptr;
107         *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
108         return android::OK;
109     }
110 
getStability()111     Stability getStability() const override { return mStability; }
112 
113     inline bool operator!=(const ParcelableHolder& rhs) const {
114         return this != &rhs;
115     }
116     inline bool operator<(const ParcelableHolder& rhs) const {
117         return this < &rhs;
118     }
119     inline bool operator<=(const ParcelableHolder& rhs) const {
120         return this <= &rhs;
121     }
122     inline bool operator==(const ParcelableHolder& rhs) const {
123         return this == &rhs;
124     }
125     inline bool operator>(const ParcelableHolder& rhs) const {
126         return this > &rhs;
127     }
128     inline bool operator>=(const ParcelableHolder& rhs) const {
129         return this >= &rhs;
130     }
131 
132 private:
133     mutable std::shared_ptr<Parcelable> mParcelable;
134     mutable std::optional<String16> mParcelableName;
135     mutable std::unique_ptr<Parcel> mParcelPtr;
136     Stability mStability;
137 };
138 } // namespace os
139 } // namespace android
140