/* * Copyright (C) 2021 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. */ #ifndef CPP_CAR_BINDER_LIB_LARGEPARCELABLE_INCLUDE_LARGEPARCELABLEVECTOR_H_ #define CPP_CAR_BINDER_LIB_LARGEPARCELABLE_INCLUDE_LARGEPARCELABLEVECTOR_H_ #include "LargeParcelableBase.h" #include "SharedMemory.h" #include #include #include #include #include namespace android { namespace automotive { namespace car_binder_lib { // This class allows a list of stable AIDL parcelables to be marshalled to a shared memory file if // their serialized parcel exceeds binder limitation. template class LargeParcelableVector : public LargeParcelableBase { public: LargeParcelableVector() {} // Use a list of stable AIDL parcelables to initiate this large parcelable. // // T must be a Parcelable. explicit LargeParcelableVector(std::vector parcelable) : mParcelable(std::move(parcelable)) {} // Get the list of stable AIDL parcelable object. Caller is supposed to use // 'LargeParcelableVector' class to parse data from 'Parcel' and then use 'getParcelables' to // get the underlying parsed regular parcelable objects. inline const std::optional*> getParcelables() const { if (!hasDeserializedParcelable()) { return std::nullopt; } return &mParcelable; } protected: // Serialize this parcelable to 'dest'. binder_status_t serialize(AParcel* dest) const override; // Serialize a NULL parcelable for 'this' class to 'dest'. binder_status_t serializeNullPayload(AParcel* dest) const override; // Read a 'Parcelable' from the given Parcel. The src might be parsed to a NULL parcelable. binder_status_t deserialize(const AParcel& src) override; private: std::vector mParcelable; // Serialize a nullable Parcelabel 'payload' to 'dest'. static binder_status_t serializePayload(const std::vector* payload, AParcel* dest); }; template binder_status_t LargeParcelableVector::serializePayload(const std::vector* payload, AParcel* dest) { int32_t startPosition; if (DBG_PAYLOAD) { startPosition = AParcel_getDataPosition(dest); } if (binder_status_t status = ::ndk::AParcel_writeVector(dest, *payload); status != STATUS_OK) { ALOGE("failed to write parcelable vector to parcel, status: %d", status); return status; } if (DBG_PAYLOAD) { ALOGD("serialize-payload, start:%d size: %d", startPosition, (AParcel_getDataPosition(dest) - startPosition)); } return STATUS_OK; } template binder_status_t LargeParcelableVector::serialize(AParcel* dest) const { return serializePayload(&mParcelable, dest); } template binder_status_t LargeParcelableVector::serializeNullPayload(AParcel* dest) const { std::vector empty; return serializePayload(&empty, dest); } template binder_status_t LargeParcelableVector::deserialize(const AParcel& src) { int32_t startPosition; if (DBG_PAYLOAD) { startPosition = AParcel_getDataPosition(&src); ALOGD("start position: %d", startPosition); } if (binder_status_t status = ::ndk::AParcel_readVector(&src, &mParcelable); status != STATUS_OK) { ALOGE("failed to read parcelable vector from parcel, status: %d", status); return status; } if (DBG_PAYLOAD) { ALOGD("deserialize-payload, start:%d size: %d", startPosition, (AParcel_getDataPosition(&src) - startPosition)); } return STATUS_OK; } } // namespace car_binder_lib } // namespace automotive } // namespace android #endif // CPP_CAR_BINDER_LIB_LARGEPARCELABLE_INCLUDE_LARGEPARCELABLEVECTOR_H_