Merge "Remove ndk_platform backend. Use the ndk backend."
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
new file mode 100644
index 0000000..61e475a
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
@@ -0,0 +1,294 @@
+/*
+ * 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 android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
+#define android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <VehicleHalTypes.h>
+
+#include <android-base/thread_annotations.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// Handy metric mostly for unit tests and debug.
+#define INC_METRIC_IF_DEBUG(val) PoolStats::instance()->val++;
+
+struct PoolStats {
+    std::atomic<uint32_t> Obtained{0};
+    std::atomic<uint32_t> Created{0};
+    std::atomic<uint32_t> Recycled{0};
+    std::atomic<uint32_t> Deleted{0};
+
+    static PoolStats* instance() {
+        static PoolStats inst;
+        return &inst;
+    }
+};
+
+template <typename T>
+struct Deleter {
+    using OnDeleteFunc = std::function<void(T*)>;
+
+    explicit Deleter(const OnDeleteFunc& f) : mOnDelete(f){};
+
+    Deleter() = default;
+    Deleter(const Deleter&) = default;
+
+    void operator()(T* o) { mOnDelete(o); }
+
+  private:
+    OnDeleteFunc mOnDelete;
+};
+
+// This is std::unique_ptr<> with custom delete operation that typically moves the pointer it holds
+// back to ObjectPool.
+template <typename T>
+using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
+
+// Generic abstract object pool class. Users of this class must implement {@Code createObject}.
+//
+// This class is thread-safe. Concurrent calls to {@Code obtain} from multiple threads is OK, also
+// client can obtain an object in one thread and then move ownership to another thread.
+template <typename T>
+class ObjectPool {
+  public:
+    using GetSizeFunc = std::function<size_t(const T&)>;
+
+    ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc)
+        : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc){};
+    virtual ~ObjectPool() = default;
+
+    virtual recyclable_ptr<T> obtain() {
+        std::lock_guard<std::mutex> lock(mLock);
+        INC_METRIC_IF_DEBUG(Obtained)
+        if (mObjects.empty()) {
+            INC_METRIC_IF_DEBUG(Created)
+            return wrap(createObject());
+        }
+
+        auto o = wrap(mObjects.front().release());
+        mObjects.pop_front();
+        mPoolObjectsSize -= mGetSizeFunc(*o);
+        return o;
+    }
+
+    ObjectPool& operator=(const ObjectPool&) = delete;
+    ObjectPool(const ObjectPool&) = delete;
+
+  protected:
+    virtual T* createObject() = 0;
+
+    virtual void recycle(T* o) {
+        std::lock_guard<std::mutex> lock(mLock);
+        size_t objectSize = mGetSizeFunc(*o);
+
+        if (objectSize > mMaxPoolObjectsSize ||
+            mPoolObjectsSize > mMaxPoolObjectsSize - objectSize) {
+            INC_METRIC_IF_DEBUG(Deleted)
+
+            // We have no space left in the pool.
+            delete o;
+            return;
+        }
+
+        INC_METRIC_IF_DEBUG(Recycled)
+
+        mObjects.push_back(std::unique_ptr<T>{o});
+        mPoolObjectsSize += objectSize;
+    }
+
+    const size_t mMaxPoolObjectsSize;
+
+  private:
+    const Deleter<T>& getDeleter() {
+        if (!mDeleter.get()) {
+            Deleter<T>* d =
+                    new Deleter<T>(std::bind(&ObjectPool::recycle, this, std::placeholders::_1));
+            mDeleter.reset(d);
+        }
+        return *mDeleter.get();
+    }
+
+    recyclable_ptr<T> wrap(T* raw) { return recyclable_ptr<T>{raw, getDeleter()}; }
+
+    mutable std::mutex mLock;
+    std::deque<std::unique_ptr<T>> mObjects GUARDED_BY(mLock);
+    std::unique_ptr<Deleter<T>> mDeleter;
+    size_t mPoolObjectsSize GUARDED_BY(mLock);
+    GetSizeFunc mGetSizeFunc;
+};
+
+#undef INC_METRIC_IF_DEBUG
+
+// This class provides a pool of recyclable VehiclePropertyValue objects.
+//
+// It has only one overloaded public method - obtain(...), users must call this method when new
+// object is needed with given VehiclePropertyType and vector size (for vector properties). This
+// method returns a recyclable smart pointer to VehiclePropertyValue, essentially this is a
+// std::unique_ptr with custom delete function, so recyclable object has only one owner and
+// developers can safely pass it around. Once this object goes out of scope, it will be returned to
+// the object pool.
+//
+// Some objects are not recyclable: strings and vector data types with vector
+// length > maxRecyclableVectorSize (provided in the constructor). These objects will be deleted
+// immediately once the go out of scope. There's no synchronization penalty for these objects since
+// we do not store them in the pool.
+//
+// This class is thread-safe. Users can obtain an object in one thread and pass it to another.
+//
+// Sample usage:
+//
+//   VehiclePropValuePool pool;
+//   auto v = pool.obtain(VehiclePropertyType::INT32);
+//   v->propId = VehicleProperty::HVAC_FAN_SPEED;
+//   v->areaId = VehicleAreaSeat::ROW_1_LEFT;
+//   v->timestamp = elapsedRealtimeNano();
+//   v->value->int32Values[0] = 42;
+class VehiclePropValuePool {
+  public:
+    using RecyclableType =
+            recyclable_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>;
+
+    // Creates VehiclePropValuePool
+    //
+    // @param maxRecyclableVectorSize - vector value types (e.g. VehiclePropertyType::INT32_VEC)
+    // with size equal or less to this value will be stored in the pool. If users tries to obtain
+    // value with vector size greater than maxRecyclableVectorSize, user will receive a regular
+    // unique pointer instead of a recyclable pointer. The object would not be recycled once it
+    // goes out of scope, but would be deleted.
+    // @param maxPoolObjectsSize - The approximate upper bound of memory each internal recycling
+    // pool could take. We have 4 different type pools, each with 4 different vector size, so
+    // approximately this pool would at-most take 4 * 4 * 10240 = 160k memory.
+    VehiclePropValuePool(size_t maxRecyclableVectorSize = 4, size_t maxPoolObjectsSize = 10240)
+        : mMaxRecyclableVectorSize(maxRecyclableVectorSize),
+          mMaxPoolObjectsSize(maxPoolObjectsSize){};
+
+    // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the
+    // given type is not MIXED or STRING, the internal value vector size would be set to 1.
+    // If the given type is MIXED or STRING, all the internal vector sizes would be initialized to
+    // 0.
+    RecyclableType obtain(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type);
+
+    // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the
+    // given type is *_VEC or BYTES, the internal value vector size would be set to vectorSize. If
+    // the given type is BOOLEAN, INT32, FLOAT, or INT64, the internal value vector size would be
+    // set to 1. If the given type is MIXED or STRING, all the internal value vector sizes would be
+    // set to 0. vectorSize must be larger than 0.
+    RecyclableType obtain(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                          size_t vectorSize);
+    // Obtain a recyclable VehicePropertyValue object that is a copy of src. If src does not contain
+    // any value or the src property type is not valid, this function would return an empty
+    // VehiclePropValue.
+    RecyclableType obtain(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& src);
+    // Obtain a recyclable boolean object.
+    RecyclableType obtainBoolean(bool value);
+    // Obtain a recyclable int32 object.
+    RecyclableType obtainInt32(int32_t value);
+    // Obtain a recyclable int64 object.
+    RecyclableType obtainInt64(int64_t value);
+    // Obtain a recyclable float object.
+    RecyclableType obtainFloat(float value);
+    // Obtain a recyclable float object.
+    RecyclableType obtainString(const char* cstr);
+    // Obtain a recyclable mixed object.
+    RecyclableType obtainComplex();
+
+    VehiclePropValuePool(VehiclePropValuePool&) = delete;
+    VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete;
+
+  private:
+    static inline bool isSingleValueType(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+        return type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::
+                               BOOLEAN ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32 ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64 ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT;
+    }
+
+    static inline bool isComplexType(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+        return type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING;
+    }
+
+    bool isDisposable(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                      size_t vectorSize) const {
+        return vectorSize > mMaxRecyclableVectorSize || isComplexType(type);
+    }
+
+    RecyclableType obtainDisposable(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType valueType,
+            size_t vectorSize) const;
+    RecyclableType obtainRecyclable(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+            size_t vectorSize);
+
+    class InternalPool
+        : public ObjectPool<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> {
+      public:
+        InternalPool(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                     size_t vectorSize, size_t maxPoolObjectsSize,
+                     ObjectPool::GetSizeFunc getSizeFunc)
+            : ObjectPool(maxPoolObjectsSize, getSizeFunc),
+              mPropType(type),
+              mVectorSize(vectorSize) {}
+
+      protected:
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropValue* createObject() override;
+        void recycle(::aidl::android::hardware::automotive::vehicle::VehiclePropValue* o) override;
+
+      private:
+        bool check(::aidl::android::hardware::automotive::vehicle::RawPropValues* v);
+
+        template <typename VecType>
+        bool check(std::vector<VecType>* vec, bool isVectorType) {
+            return vec->size() == (isVectorType ? mVectorSize : 0);
+        }
+
+      private:
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType;
+        size_t mVectorSize;
+    };
+    const Deleter<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+            mDisposableDeleter{
+                    [](::aidl::android::hardware::automotive::vehicle::VehiclePropValue* v) {
+                        delete v;
+                    }};
+
+    mutable std::mutex mLock;
+    const size_t mMaxRecyclableVectorSize;
+    const size_t mMaxPoolObjectsSize;
+    // A map with 'property_type' | 'value_vector_size' as key and a recyclable object pool as
+    // value. We would create a recyclable pool for each property type and vector size combination.
+    std::map<int32_t, std::unique_ptr<InternalPool>> mValueTypePools GUARDED_BY(mLock);
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index c4bf1d3..b02aaf7 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -18,6 +18,7 @@
 #define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
 
 #include <VehicleHalTypes.h>
+#include <utils/Log.h>
 
 namespace android {
 namespace hardware {
@@ -81,6 +82,104 @@
     return nullptr;
 }
 
+inline std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValueVec(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                          size_t vecSize) {
+    auto val = std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>(
+            new ::aidl::android::hardware::automotive::vehicle::VehiclePropValue);
+    switch (type) {
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
+            vecSize = 1;
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
+            val->value.int32Values.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+            vecSize = 1;
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
+            val->value.floatValues.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+            vecSize = 1;
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
+            val->value.int64Values.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
+            val->value.byteValues.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
+            break;  // Valid, but nothing to do.
+        default:
+            ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
+            val.reset(nullptr);
+    }
+    return val;
+}
+
+inline std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValue(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+    return createVehiclePropValueVec(type, 1);
+}
+
+inline size_t getVehicleRawValueVectorSize(
+        const ::aidl::android::hardware::automotive::vehicle::RawPropValues& value,
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+    switch (type) {
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:  // fall
+                                                                                          // through
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::
+                BOOLEAN:  // fall through
+            return std::min(value.int32Values.size(), static_cast<size_t>(1));
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+            return std::min(value.floatValues.size(), static_cast<size_t>(1));
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+            return std::min(value.int64Values.size(), static_cast<size_t>(1));
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
+            return value.int32Values.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
+            return value.floatValues.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
+            return value.int64Values.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
+            return value.byteValues.size();
+        default:
+            ALOGE("getVehicleRawValueVectorSize: unknown type: %d", toInt(type));
+            return 0;
+    }
+}
+
+inline void copyVehicleRawValue(
+        ::aidl::android::hardware::automotive::vehicle::RawPropValues* dest,
+        const ::aidl::android::hardware::automotive::vehicle::RawPropValues& src) {
+    dest->int32Values = src.int32Values;
+    dest->floatValues = src.floatValues;
+    dest->int64Values = src.int64Values;
+    dest->byteValues = src.byteValues;
+    dest->stringValue = src.stringValue;
+}
+
+// getVehiclePropValueSize returns approximately how much memory 'value' would take. This should
+// only be used in a limited-size memory pool to set an upper bound for memory consumption.
+inline size_t getVehiclePropValueSize(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& prop) {
+    size_t size = 0;
+    size += sizeof(prop.timestamp);
+    size += sizeof(prop.areaId);
+    size += sizeof(prop.prop);
+    size += sizeof(prop.status);
+    size += prop.value.int32Values.size() * sizeof(int32_t);
+    size += prop.value.int64Values.size() * sizeof(int64_t);
+    size += prop.value.floatValues.size() * sizeof(float);
+    size += prop.value.byteValues.size() * sizeof(uint8_t);
+    size += prop.value.stringValue.size();
+    return size;
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
new file mode 100644
index 0000000..0ff58f7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "VehicleObjectPool"
+
+#include <VehicleObjectPool.h>
+
+#include <VehicleUtils.h>
+
+#include <assert.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type) {
+    if (isComplexType(type)) {
+        return obtain(type, 0);
+    }
+    return obtain(type, 1);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type,
+                                                                  size_t vectorSize) {
+    if (isSingleValueType(type)) {
+        vectorSize = 1;
+    } else if (isComplexType(type)) {
+        vectorSize = 0;
+    }
+    return isDisposable(type, vectorSize) ? obtainDisposable(type, vectorSize)
+                                          : obtainRecyclable(type, vectorSize);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(const VehiclePropValue& src) {
+    VehiclePropertyType type = getPropType(src.prop);
+    size_t vectorSize = getVehicleRawValueVectorSize(src.value, type);
+    if (vectorSize == 0 && !isComplexType(type)) {
+        ALOGW("empty vehicle prop value, contains no content");
+        // Return any empty VehiclePropValue.
+        return RecyclableType{new VehiclePropValue, mDisposableDeleter};
+    }
+
+    auto dest = obtain(type, vectorSize);
+
+    dest->prop = src.prop;
+    dest->areaId = src.areaId;
+    dest->status = src.status;
+    dest->timestamp = src.timestamp;
+    copyVehicleRawValue(&dest->value, src.value);
+
+    return dest;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(int32_t value) {
+    auto val = obtain(VehiclePropertyType::INT32);
+    val->value.int32Values[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(int64_t value) {
+    auto val = obtain(VehiclePropertyType::INT64);
+    val->value.int64Values[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(float value) {
+    auto val = obtain(VehiclePropertyType::FLOAT);
+    val->value.floatValues[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(const char* cstr) {
+    auto val = obtain(VehiclePropertyType::STRING);
+    val->value.stringValue = cstr;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
+    return obtain(VehiclePropertyType::MIXED);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable(
+        VehiclePropertyType type, size_t vectorSize) {
+    std::lock_guard<std::mutex> lock(mLock);
+    assert(vectorSize > 0);
+
+    // VehiclePropertyType is not overlapping with vectorSize.
+    int32_t key = static_cast<int32_t>(type) | static_cast<int32_t>(vectorSize);
+    auto it = mValueTypePools.find(key);
+
+    if (it == mValueTypePools.end()) {
+        auto newPool(std::make_unique<InternalPool>(type, vectorSize, mMaxPoolObjectsSize,
+                                                    getVehiclePropValueSize));
+        it = mValueTypePools.emplace(key, std::move(newPool)).first;
+    }
+    return it->second->obtain();
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(bool value) {
+    return obtainInt32(value);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
+        VehiclePropertyType valueType, size_t vectorSize) const {
+    return RecyclableType{createVehiclePropValueVec(valueType, vectorSize).release(),
+                          mDisposableDeleter};
+}
+
+void VehiclePropValuePool::InternalPool::recycle(VehiclePropValue* o) {
+    if (o == nullptr) {
+        ALOGE("Attempt to recycle nullptr");
+        return;
+    }
+
+    if (!check(&o->value)) {
+        ALOGE("Discarding value for prop 0x%x because it contains "
+              "data that is not consistent with this pool. "
+              "Expected type: %d, vector size: %zu",
+              o->prop, toInt(mPropType), mVectorSize);
+        delete o;
+    } else {
+        ObjectPool<VehiclePropValue>::recycle(o);
+    }
+}
+
+bool VehiclePropValuePool::InternalPool::check(RawPropValues* v) {
+    return check(&v->int32Values, (VehiclePropertyType::INT32 == mPropType ||
+                                   VehiclePropertyType::INT32_VEC == mPropType ||
+                                   VehiclePropertyType::BOOLEAN == mPropType)) &&
+           check(&v->floatValues, (VehiclePropertyType::FLOAT == mPropType ||
+                                   VehiclePropertyType::FLOAT_VEC == mPropType)) &&
+           check(&v->int64Values, (VehiclePropertyType::INT64 == mPropType ||
+                                   VehiclePropertyType::INT64_VEC == mPropType)) &&
+           check(&v->byteValues, VehiclePropertyType::BYTES == mPropType) &&
+           v->stringValue.size() == 0;
+}
+
+VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
+    return createVehiclePropValueVec(mPropType, mVectorSize).release();
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
new file mode 100644
index 0000000..a62532c
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
@@ -0,0 +1,381 @@
+/*
+ * 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.
+ */
+
+#include <thread>
+
+#include <gtest/gtest.h>
+
+#include <utils/SystemClock.h>
+
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+#include <VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+struct TestPropertyTypeInfo {
+    VehiclePropertyType type;
+    bool recyclable;
+    size_t vecSize;
+};
+
+std::vector<TestPropertyTypeInfo> getAllPropertyTypes() {
+    return {
+            {
+                    .type = VehiclePropertyType::INT32,
+                    .recyclable = true,
+                    .vecSize = 1,
+            },
+            {
+                    .type = VehiclePropertyType::INT64,
+                    .recyclable = true,
+                    .vecSize = 1,
+            },
+            {
+                    .type = VehiclePropertyType::FLOAT,
+                    .recyclable = true,
+                    .vecSize = 1,
+            },
+            {
+                    .type = VehiclePropertyType::INT32_VEC,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::INT64_VEC,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::FLOAT_VEC,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::BYTES,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::INT32_VEC,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::INT64_VEC,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::FLOAT_VEC,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::BYTES,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::STRING,
+                    .recyclable = false,
+                    .vecSize = 0,
+            },
+            {
+                    .type = VehiclePropertyType::MIXED,
+                    .recyclable = false,
+                    .vecSize = 0,
+            },
+    };
+}
+
+}  // namespace
+
+class VehicleObjectPoolTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        mStats = PoolStats::instance();
+        resetStats();
+        mValuePool.reset(new VehiclePropValuePool);
+    }
+
+    void TearDown() override {
+        // At the end, all created objects should be either recycled or deleted.
+        ASSERT_EQ(mStats->Obtained, mStats->Recycled + mStats->Deleted);
+        // Some objects could be recycled multiple times.
+        ASSERT_LE(mStats->Created, mStats->Recycled + mStats->Deleted);
+    }
+
+    PoolStats* mStats;
+    std::unique_ptr<VehiclePropValuePool> mValuePool;
+
+  private:
+    void resetStats() {
+        mStats->Obtained = 0;
+        mStats->Created = 0;
+        mStats->Recycled = 0;
+        mStats->Deleted = 0;
+    }
+};
+
+class VehiclePropertyTypesTest : public VehicleObjectPoolTest,
+                                 public testing::WithParamInterface<TestPropertyTypeInfo> {};
+
+TEST_P(VehiclePropertyTypesTest, testRecycle) {
+    auto info = GetParam();
+    if (!info.recyclable) {
+        GTEST_SKIP();
+    }
+
+    auto value = mValuePool->obtain(info.type, info.vecSize);
+    void* raw = value.get();
+    value.reset();
+    // At this point, value should be recycled and the only object in the pool.
+    ASSERT_EQ(mValuePool->obtain(info.type, info.vecSize).get(), raw);
+
+    ASSERT_EQ(mStats->Obtained, 2u);
+    ASSERT_EQ(mStats->Created, 1u);
+}
+
+TEST_P(VehiclePropertyTypesTest, testNotRecyclable) {
+    auto info = GetParam();
+    if (info.recyclable) {
+        GTEST_SKIP();
+    }
+
+    auto value = mValuePool->obtain(info.type, info.vecSize);
+
+    ASSERT_EQ(mStats->Obtained, 0u) << "Non recyclable object should not be obtained from the pool";
+    ASSERT_EQ(mStats->Created, 0u) << "Non recyclable object should not be created from the pool";
+}
+
+INSTANTIATE_TEST_SUITE_P(AllPropertyTypes, VehiclePropertyTypesTest,
+                         ::testing::ValuesIn(getAllPropertyTypes()));
+
+TEST_F(VehicleObjectPoolTest, testObtainNewObject) {
+    auto value = mValuePool->obtain(VehiclePropertyType::INT32);
+    void* raw = value.get();
+    value.reset();
+    // At this point, value should be recycled and the only object in the pool.
+    ASSERT_EQ(mValuePool->obtain(VehiclePropertyType::INT32).get(), raw);
+    // Obtaining value of another type - should return a new object
+    ASSERT_NE(mValuePool->obtain(VehiclePropertyType::FLOAT).get(), raw);
+
+    ASSERT_EQ(mStats->Obtained, 3u);
+    ASSERT_EQ(mStats->Created, 2u);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainStrings) {
+    mValuePool->obtain(VehiclePropertyType::STRING);
+    auto stringProp = mValuePool->obtain(VehiclePropertyType::STRING);
+    stringProp->value.stringValue = "Hello";
+    void* raw = stringProp.get();
+    stringProp.reset();  // delete the pointer
+
+    auto newStringProp = mValuePool->obtain(VehiclePropertyType::STRING);
+
+    ASSERT_EQ(newStringProp->value.stringValue.size(), 0u);
+    ASSERT_NE(mValuePool->obtain(VehiclePropertyType::STRING).get(), raw);
+    ASSERT_EQ(mStats->Obtained, 0u);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainBoolean) {
+    auto prop = mValuePool->obtainBoolean(true);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.int32Values = {1}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainInt32) {
+    auto prop = mValuePool->obtainInt32(1234);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.int32Values = {1234}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainInt64) {
+    auto prop = mValuePool->obtainInt64(1234);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.int64Values = {1234}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainFloat) {
+    auto prop = mValuePool->obtainFloat(1.234);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.floatValues = {1.234}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainString) {
+    auto prop = mValuePool->obtainString("test");
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.stringValue = "test"},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainComplex) {
+    auto prop = mValuePool->obtainComplex();
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, VehiclePropValue{});
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt32Values) {
+    VehiclePropValue prop{
+            // INT32_VEC property.
+            .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.int32Values = {1, 2, 3, 4}},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt64Values) {
+    VehiclePropValue prop{
+            // INT64_VEC property.
+            .prop = toInt(VehicleProperty::WHEEL_TICK),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.int64Values = {1, 2, 3, 4}},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyFloatValues) {
+    VehiclePropValue prop{
+            // FLOAT_VEC property.
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.floatValues = {1, 2, 3, 4}},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyString) {
+    VehiclePropValue prop{
+            // STRING property.
+            .prop = toInt(VehicleProperty::INFO_VIN),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.stringValue = "test"},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyMixed) {
+    VehiclePropValue prop{
+            // MIxed property.
+            .prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+            .areaId = 2,
+            .timestamp = 3,
+            .value =
+                    {
+                            .int32Values = {1, 2, 3},
+                            .floatValues = {4.0, 5.0},
+                            .stringValue = "test",
+                    },
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testMultithreaded) {
+    // In this test we have T threads that concurrently in C cycles
+    // obtain and release O VehiclePropValue objects of FLOAT / INT32 types.
+
+    const int T = 2;
+    const int C = 500;
+    const int O = 100;
+
+    auto poolPtr = mValuePool.get();
+
+    std::vector<std::thread> threads;
+    for (int i = 0; i < T; i++) {
+        threads.push_back(std::thread([&poolPtr]() {
+            for (int j = 0; j < C; j++) {
+                std::vector<recyclable_ptr<VehiclePropValue>> vec;
+                for (int k = 0; k < O; k++) {
+                    vec.push_back(poolPtr->obtain(k % 2 == 0 ? VehiclePropertyType::FLOAT
+                                                             : VehiclePropertyType::INT32));
+                }
+            }
+        }));
+    }
+
+    for (auto& t : threads) {
+        t.join();
+    }
+
+    ASSERT_EQ(mStats->Obtained, static_cast<uint32_t>(T * C * O));
+    ASSERT_EQ(mStats->Recycled + mStats->Deleted, static_cast<uint32_t>(T * C * O));
+    // Created less than obtained in one cycle.
+    ASSERT_LE(mStats->Created, static_cast<uint32_t>(T * O));
+}
+
+TEST_F(VehicleObjectPoolTest, testMemoryLimitation) {
+    std::vector<recyclable_ptr<VehiclePropValue>> vec;
+    for (size_t i = 0; i < 10000; i++) {
+        vec.push_back(mValuePool->obtain(VehiclePropertyType::INT32));
+    }
+    // We have too many values, not all of them would be recycled, some of them will be deleted.
+    vec.clear();
+
+    ASSERT_EQ(mStats->Obtained, 10000u);
+    ASSERT_EQ(mStats->Created, 10000u);
+    ASSERT_GT(mStats->Deleted, 0u) << "expect some values to be deleted, not recycled if too many "
+                                      "values are in the pool";
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index c09b06d..7ad3d31 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -16,7 +16,9 @@
 
 #include <PropertyUtils.h>
 #include <VehicleUtils.h>
+
 #include <gtest/gtest.h>
+#include <vector>
 
 namespace android {
 namespace hardware {
@@ -122,6 +124,129 @@
     ASSERT_EQ(gotConfig, nullptr);
 }
 
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT32);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValue(VehiclePropertyType::INT32_VEC);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT64);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValue(VehiclePropertyType::INT64_VEC);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloat) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::FLOAT);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValue(VehiclePropertyType::FLOAT_VEC);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueBytes) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::BYTES);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.byteValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueString) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::STRING);
+
+    ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueMixed) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::MIXED);
+
+    ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt32) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT32, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int32Values.size())
+            << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec32Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT32_VEC, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt64) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT64, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int64Values.size())
+            << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec64Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT64_VEC, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecFloat) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::FLOAT, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.floatValues.size())
+            << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloVecatVec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::FLOAT_VEC, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecBytes) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::BYTES, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.byteValues.size());
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 2d4cc7d..fe59a9d 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -61,18 +61,18 @@
 void TestRenderEngine::drawLayers() {
     base::unique_fd bufferFence;
 
-    std::vector<renderengine::LayerSettings> compositionLayers;
-    compositionLayers.reserve(mCompositionLayers.size());
+    std::vector<const renderengine::LayerSettings*> compositionLayerPointers;
+    compositionLayerPointers.reserve(mCompositionLayers.size());
     std::transform(mCompositionLayers.begin(), mCompositionLayers.end(),
-                   std::back_insert_iterator(compositionLayers),
-                   [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings {
-                       return settings;
+                   std::back_insert_iterator(compositionLayerPointers),
+                   [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* {
+                       return &settings;
                    });
     auto texture = std::make_shared<renderengine::ExternalTexture>(
             mGraphicBuffer, *mRenderEngine, renderengine::ExternalTexture::Usage::WRITEABLE);
     auto [status, readyFence] = mRenderEngine
-                                        ->drawLayers(mDisplaySettings, compositionLayers, texture,
-                                                     true, std::move(bufferFence))
+                                        ->drawLayers(mDisplaySettings, compositionLayerPointers,
+                                                     texture, true, std::move(bufferFence))
                                         .get();
     int fd = readyFence.release();
     if (fd != -1) {
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index e18b1fa..2ab9c01 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -1482,6 +1482,18 @@
 }
 
 /**
+ * Test IMapper::get(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, GetSmpte2094_10) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                std::optional<std::vector<uint8_t>> smpte2094_10;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10));
+                EXPECT_FALSE(smpte2094_10.has_value());
+            });
+}
+
+/**
  * Test IMapper::get(metadata) with a bad buffer
  */
 TEST_P(GraphicsMapperHidlTest, GetMetadataBadValue) {
@@ -1545,6 +1557,9 @@
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, &vec));
     ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_10, &vec));
+    ASSERT_EQ(0, vec.size());
 }
 
 /**
@@ -1937,6 +1952,20 @@
 }
 
 /**
+ * Test IMapper::set(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, SetSmpte2094_10) {
+    hidl_vec<uint8_t> vec;
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                std::optional<std::vector<uint8_t>> realSmpte2094_10;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &realSmpte2094_10));
+                EXPECT_FALSE(realSmpte2094_10.has_value());
+            });
+}
+
+/**
  * Test IMapper::set(metadata) with a bad buffer
  */
 TEST_P(GraphicsMapperHidlTest, SetMetadataNullBuffer) {
@@ -1977,6 +2006,8 @@
     ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_10, vec));
 }
 
 /**
@@ -2482,6 +2513,24 @@
 }
 
 /**
+ * Test IMapper::getFromBufferDescriptorInfo(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_10) {
+    hidl_vec<uint8_t> vec;
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Smpte2094_10, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
+
+    std::optional<std::vector<uint8_t>> smpte2094_10;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10));
+    EXPECT_FALSE(smpte2094_10.has_value());
+}
+
+/**
  * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedMetadata) {
diff --git a/radio/1.0/vts/OWNERS b/radio/1.0/vts/OWNERS
index 9310f8e..117692a 100644
--- a/radio/1.0/vts/OWNERS
+++ b/radio/1.0/vts/OWNERS
@@ -1,7 +1,5 @@
-# Telephony team
-amitmahajan@google.com
+# Bug component: 20868
+jminjie@google.com
+sarahchin@google.com
 shuoq@google.com
 jackyu@google.com
-
-# VTS team
-dshi@google.com
diff --git a/radio/1.1/vts/OWNERS b/radio/1.1/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.1/vts/OWNERS
+++ b/radio/1.1/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.2/vts/OWNERS b/radio/1.2/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.2/vts/OWNERS
+++ b/radio/1.2/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.3/vts/OWNERS b/radio/1.3/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.3/vts/OWNERS
+++ b/radio/1.3/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.4/vts/OWNERS b/radio/1.4/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.4/vts/OWNERS
+++ b/radio/1.4/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.5/vts/OWNERS b/radio/1.5/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.5/vts/OWNERS
+++ b/radio/1.5/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/config/1.1/vts/OWNERS b/radio/config/1.1/vts/OWNERS
new file mode 100644
index 0000000..4109967
--- /dev/null
+++ b/radio/config/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+include /radio/1.0/vts/OWNERS
diff --git a/radio/config/1.2/vts/OWNERS b/radio/config/1.2/vts/OWNERS
new file mode 100644
index 0000000..4109967
--- /dev/null
+++ b/radio/config/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+include /radio/1.0/vts/OWNERS
diff --git a/vibrator/aidl/OWNERS b/vibrator/aidl/OWNERS
index 4bd5614..e3d7e6b 100644
--- a/vibrator/aidl/OWNERS
+++ b/vibrator/aidl/OWNERS
@@ -1,4 +1,3 @@
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
 chasewu@google.com
 leungv@google.com
-lsandrade@google.com
-michaelwr@google.com
diff --git a/weaver/1.0/vts/functional/OWNERS b/weaver/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ec8c304
--- /dev/null
+++ b/weaver/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 186411
+chengyouho@google.com
+frankwoo@google.com