Loading libs/binder/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ cc_library { "MemoryDealer.cpp", "MemoryHeapBase.cpp", "Parcel.cpp", "ParcelableHolder.cpp", "ParcelFileDescriptor.cpp", "PersistableBundle.cpp", "ProcessState.cpp", Loading libs/binder/ParcelableHolder.cpp 0 → 100644 +97 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <binder/Parcel.h> #include <binder/Parcelable.h> #include <binder/ParcelableHolder.h> #define RETURN_ON_FAILURE(expr) \ do { \ android::status_t _status = (expr); \ if (_status != android::OK) return _status; \ } while (false) namespace android { namespace os { status_t ParcelableHolder::writeToParcel(Parcel* p) const { std::lock_guard<std::mutex> l(mMutex); RETURN_ON_FAILURE(p->writeInt32(static_cast<int32_t>(this->getStability()))); if (this->mParcelPtr) { RETURN_ON_FAILURE(p->writeInt32(this->mParcelPtr->dataSize())); RETURN_ON_FAILURE(p->appendFrom(this->mParcelPtr.get(), 0, this->mParcelPtr->dataSize())); return OK; } if (this->mParcelable) { size_t sizePos = p->dataPosition(); RETURN_ON_FAILURE(p->writeInt32(0)); size_t dataStartPos = p->dataPosition(); RETURN_ON_FAILURE(p->writeUtf8AsUtf16(this->mParcelableName)); this->mParcelable->writeToParcel(p); size_t dataSize = p->dataPosition() - dataStartPos; p->setDataPosition(sizePos); RETURN_ON_FAILURE(p->writeInt32(dataSize)); p->setDataPosition(p->dataPosition() + dataSize); return OK; } RETURN_ON_FAILURE(p->writeInt32(0)); return OK; } status_t ParcelableHolder::readFromParcel(const Parcel* p) { std::lock_guard<std::mutex> l(mMutex); this->mStability = static_cast<Stability>(p->readInt32()); this->mParcelable = nullptr; this->mParcelableName = std::nullopt; int32_t rawDataSize; status_t status = p->readInt32(&rawDataSize); if (status != android::OK || rawDataSize < 0) { this->mParcelPtr = nullptr; return status != android::OK ? status : BAD_VALUE; } if (rawDataSize == 0) { if (this->mParcelPtr) { this->mParcelPtr = nullptr; } return OK; } size_t dataSize = rawDataSize; size_t dataStartPos = p->dataPosition(); if (dataStartPos > SIZE_MAX - dataSize) { this->mParcelPtr = nullptr; return BAD_VALUE; } if (!this->mParcelPtr) { this->mParcelPtr = std::make_unique<Parcel>(); } this->mParcelPtr->freeData(); status = this->mParcelPtr->appendFrom(p, dataStartPos, dataSize); if (status != android::OK) { this->mParcelPtr = nullptr; return status; } p->setDataPosition(dataStartPos + dataSize); return OK; } } // namespace os } // namespace android libs/binder/include/binder/Parcelable.h +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ public: // WARNING: for use by auto-generated code only (AIDL). Should not be used // manually, or there is a risk of breaking CTS, GTS, VTS, or CTS-on-GSI // tests. enum class Stability { enum class Stability : int32_t { STABILITY_LOCAL, STABILITY_VINTF, // corresponds to @VintfStability }; Loading libs/binder/include/binder/ParcelableHolder.h 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <binder/Parcel.h> #include <binder/Parcelable.h> #include <mutex> #include <optional> #include <tuple> namespace android { namespace os { /* * C++ implementation of the Java class android.os.ParcelableHolder */ class ParcelableHolder : public android::Parcelable { public: ParcelableHolder() = delete; explicit ParcelableHolder(Stability stability) : mStability(stability){}; virtual ~ParcelableHolder() = default; ParcelableHolder(const ParcelableHolder& other) { mParcelable = other.mParcelable; mParcelableName = other.mParcelableName; if (other.mParcelPtr) { mParcelPtr = std::make_unique<Parcel>(); mParcelPtr->appendFrom(other.mParcelPtr.get(), 0, other.mParcelPtr->dataSize()); } mStability = other.mStability; }; status_t writeToParcel(Parcel* parcel) const override; status_t readFromParcel(const Parcel* parcel) override; void reset() { this->mParcelable = nullptr; this->mParcelableName = std::nullopt; this->mParcelPtr = nullptr; } template <typename T> bool setParcelable(T&& p) { using Tt = typename std::decay<T>::type; return setParcelable<Tt>(std::make_shared<Tt>(std::forward<T>(p))); } template <typename T> bool setParcelable(std::shared_ptr<T> p) { std::lock_guard<std::mutex> l(mMutex); static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); if (p && this->getStability() > p->getStability()) { return false; } this->mParcelable = p; this->mParcelableName = T::getParcelableDescriptor(); this->mParcelPtr = nullptr; return true; } template <typename T> std::shared_ptr<T> getParcelable() const { static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); std::lock_guard<std::mutex> l(mMutex); const std::string& parcelableDesc = T::getParcelableDescriptor(); if (!this->mParcelPtr) { if (!this->mParcelable || !this->mParcelableName) { ALOGD("empty ParcelableHolder"); return nullptr; } else if (parcelableDesc != *mParcelableName) { ALOGD("extension class name mismatch expected:%s actual:%s", mParcelableName->c_str(), parcelableDesc.c_str()); return nullptr; } return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); } this->mParcelPtr->setDataPosition(0); status_t status = this->mParcelPtr->readUtf8FromUtf16(&this->mParcelableName); if (status != android::OK || parcelableDesc != this->mParcelableName) { this->mParcelableName = std::nullopt; return nullptr; } this->mParcelable = std::make_shared<T>(); status = mParcelable.get()->readFromParcel(this->mParcelPtr.get()); if (status != android::OK) { this->mParcelableName = std::nullopt; this->mParcelable = nullptr; return nullptr; } this->mParcelPtr = nullptr; return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); } Stability getStability() const override { return mStability; }; inline bool operator!=(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) != std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator<(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) < std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator<=(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) <= std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator==(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) == std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator>(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) > std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator>=(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) >= std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } private: mutable std::shared_ptr<Parcelable> mParcelable; mutable std::optional<std::string> mParcelableName; mutable std::unique_ptr<Parcel> mParcelPtr; Stability mStability; mutable std::mutex mMutex; }; } // namespace os } // namespace android Loading
libs/binder/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ cc_library { "MemoryDealer.cpp", "MemoryHeapBase.cpp", "Parcel.cpp", "ParcelableHolder.cpp", "ParcelFileDescriptor.cpp", "PersistableBundle.cpp", "ProcessState.cpp", Loading
libs/binder/ParcelableHolder.cpp 0 → 100644 +97 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <binder/Parcel.h> #include <binder/Parcelable.h> #include <binder/ParcelableHolder.h> #define RETURN_ON_FAILURE(expr) \ do { \ android::status_t _status = (expr); \ if (_status != android::OK) return _status; \ } while (false) namespace android { namespace os { status_t ParcelableHolder::writeToParcel(Parcel* p) const { std::lock_guard<std::mutex> l(mMutex); RETURN_ON_FAILURE(p->writeInt32(static_cast<int32_t>(this->getStability()))); if (this->mParcelPtr) { RETURN_ON_FAILURE(p->writeInt32(this->mParcelPtr->dataSize())); RETURN_ON_FAILURE(p->appendFrom(this->mParcelPtr.get(), 0, this->mParcelPtr->dataSize())); return OK; } if (this->mParcelable) { size_t sizePos = p->dataPosition(); RETURN_ON_FAILURE(p->writeInt32(0)); size_t dataStartPos = p->dataPosition(); RETURN_ON_FAILURE(p->writeUtf8AsUtf16(this->mParcelableName)); this->mParcelable->writeToParcel(p); size_t dataSize = p->dataPosition() - dataStartPos; p->setDataPosition(sizePos); RETURN_ON_FAILURE(p->writeInt32(dataSize)); p->setDataPosition(p->dataPosition() + dataSize); return OK; } RETURN_ON_FAILURE(p->writeInt32(0)); return OK; } status_t ParcelableHolder::readFromParcel(const Parcel* p) { std::lock_guard<std::mutex> l(mMutex); this->mStability = static_cast<Stability>(p->readInt32()); this->mParcelable = nullptr; this->mParcelableName = std::nullopt; int32_t rawDataSize; status_t status = p->readInt32(&rawDataSize); if (status != android::OK || rawDataSize < 0) { this->mParcelPtr = nullptr; return status != android::OK ? status : BAD_VALUE; } if (rawDataSize == 0) { if (this->mParcelPtr) { this->mParcelPtr = nullptr; } return OK; } size_t dataSize = rawDataSize; size_t dataStartPos = p->dataPosition(); if (dataStartPos > SIZE_MAX - dataSize) { this->mParcelPtr = nullptr; return BAD_VALUE; } if (!this->mParcelPtr) { this->mParcelPtr = std::make_unique<Parcel>(); } this->mParcelPtr->freeData(); status = this->mParcelPtr->appendFrom(p, dataStartPos, dataSize); if (status != android::OK) { this->mParcelPtr = nullptr; return status; } p->setDataPosition(dataStartPos + dataSize); return OK; } } // namespace os } // namespace android
libs/binder/include/binder/Parcelable.h +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ public: // WARNING: for use by auto-generated code only (AIDL). Should not be used // manually, or there is a risk of breaking CTS, GTS, VTS, or CTS-on-GSI // tests. enum class Stability { enum class Stability : int32_t { STABILITY_LOCAL, STABILITY_VINTF, // corresponds to @VintfStability }; Loading
libs/binder/include/binder/ParcelableHolder.h 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <binder/Parcel.h> #include <binder/Parcelable.h> #include <mutex> #include <optional> #include <tuple> namespace android { namespace os { /* * C++ implementation of the Java class android.os.ParcelableHolder */ class ParcelableHolder : public android::Parcelable { public: ParcelableHolder() = delete; explicit ParcelableHolder(Stability stability) : mStability(stability){}; virtual ~ParcelableHolder() = default; ParcelableHolder(const ParcelableHolder& other) { mParcelable = other.mParcelable; mParcelableName = other.mParcelableName; if (other.mParcelPtr) { mParcelPtr = std::make_unique<Parcel>(); mParcelPtr->appendFrom(other.mParcelPtr.get(), 0, other.mParcelPtr->dataSize()); } mStability = other.mStability; }; status_t writeToParcel(Parcel* parcel) const override; status_t readFromParcel(const Parcel* parcel) override; void reset() { this->mParcelable = nullptr; this->mParcelableName = std::nullopt; this->mParcelPtr = nullptr; } template <typename T> bool setParcelable(T&& p) { using Tt = typename std::decay<T>::type; return setParcelable<Tt>(std::make_shared<Tt>(std::forward<T>(p))); } template <typename T> bool setParcelable(std::shared_ptr<T> p) { std::lock_guard<std::mutex> l(mMutex); static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); if (p && this->getStability() > p->getStability()) { return false; } this->mParcelable = p; this->mParcelableName = T::getParcelableDescriptor(); this->mParcelPtr = nullptr; return true; } template <typename T> std::shared_ptr<T> getParcelable() const { static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); std::lock_guard<std::mutex> l(mMutex); const std::string& parcelableDesc = T::getParcelableDescriptor(); if (!this->mParcelPtr) { if (!this->mParcelable || !this->mParcelableName) { ALOGD("empty ParcelableHolder"); return nullptr; } else if (parcelableDesc != *mParcelableName) { ALOGD("extension class name mismatch expected:%s actual:%s", mParcelableName->c_str(), parcelableDesc.c_str()); return nullptr; } return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); } this->mParcelPtr->setDataPosition(0); status_t status = this->mParcelPtr->readUtf8FromUtf16(&this->mParcelableName); if (status != android::OK || parcelableDesc != this->mParcelableName) { this->mParcelableName = std::nullopt; return nullptr; } this->mParcelable = std::make_shared<T>(); status = mParcelable.get()->readFromParcel(this->mParcelPtr.get()); if (status != android::OK) { this->mParcelableName = std::nullopt; this->mParcelable = nullptr; return nullptr; } this->mParcelPtr = nullptr; return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get())); } Stability getStability() const override { return mStability; }; inline bool operator!=(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) != std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator<(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) < std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator<=(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) <= std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator==(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) == std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator>(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) > std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } inline bool operator>=(const ParcelableHolder& rhs) const { return std::tie(mParcelable, mParcelPtr, mStability) >= std::tie(rhs.mParcelable, rhs.mParcelPtr, rhs.mStability); } private: mutable std::shared_ptr<Parcelable> mParcelable; mutable std::optional<std::string> mParcelableName; mutable std::unique_ptr<Parcel> mParcelPtr; Stability mStability; mutable std::mutex mMutex; }; } // namespace os } // namespace android