Migrate fake value generator hub.

Migrate fake value generator hub. This CL also turns all exising
LockGuard to ScopedLock.

Test: atest FakeVehicleHalValueGeneratorsTest
Bug: 201830716
Change-Id: I3ce64792fa5a49ae5e11e1fc5636a30221c596e6
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp
new file mode 100644
index 0000000..4735313
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "FakeVehicleHalValueGenerators",
+    vendor: true,
+    srcs: ["src/*.cpp"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: ["VehicleHalUtils"],
+    shared_libs: [
+        "libjsoncpp",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
new file mode 100644
index 0000000..93ffebf
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
@@ -0,0 +1,46 @@
+/*
+ * 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_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
+
+#include <VehicleHalTypes.h>
+
+#include <optional>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+// A abstract class for all fake value generators.
+class FakeValueGenerator {
+  public:
+    virtual ~FakeValueGenerator() = default;
+
+    // Returns the next event if there is one or {@code std::nullopt} if there is none.
+    virtual std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+    nextEvent() = 0;
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
new file mode 100644
index 0000000..ad04d23
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
@@ -0,0 +1,92 @@
+/*
+ * 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_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
+#define android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
+
+#include "FakeValueGenerator.h"
+
+#include <android-base/thread_annotations.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <mutex>
+#include <optional>
+#include <queue>
+#include <thread>
+#include <unordered_map>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+// This is the scheduler for all VHAL event generators. It manages all generators and uses priority
+// queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to
+// keep querying and updating the event queue to make sure events from all generators are produced
+// in order.
+class GeneratorHub {
+  public:
+    using OnHalEvent = std::function<void(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& event)>;
+
+    explicit GeneratorHub(OnHalEvent&& onHalEvent);
+    ~GeneratorHub();
+
+    // Register a new generator. The generator will be discarded if it could not produce next event.
+    // The existing generator will be overridden if it has the same generatorId.
+    void registerGenerator(int32_t generatorId, std::unique_ptr<FakeValueGenerator> generator);
+
+    // Unregister a generator with the generatorId. If no registered generator is found, this
+    // function does nothing.
+    void unregisterGenerator(int32_t generatorId);
+
+  private:
+    struct VhalEvent {
+        int32_t generatorId;
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropValue val;
+    };
+
+    // Comparator used by priority queue to keep track of soonest event.
+    struct GreaterByTime {
+        bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const {
+            return lhs.val.timestamp > rhs.val.timestamp;
+        }
+    };
+
+    std::priority_queue<VhalEvent, std::vector<VhalEvent>, GreaterByTime> mEventQueue;
+    std::mutex mGeneratorsLock;
+    std::unordered_map<int32_t, std::unique_ptr<FakeValueGenerator>> mGenerators
+            GUARDED_BY(mGeneratorsLock);
+    OnHalEvent mOnHalEvent;
+    std::condition_variable mCond;
+    std::thread mThread;
+    std::atomic<bool> mShuttingDownFlag{false};
+
+    // Main loop of the single thread to producing event and updating event queue.
+    void run();
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
new file mode 100644
index 0000000..0c182d9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 "GeneratorHub"
+
+#include "GeneratorHub.h"
+
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::android::base::ScopedLockAssertion;
+
+GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent)
+    : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+
+GeneratorHub::~GeneratorHub() {
+    mShuttingDownFlag.store(true);
+    mCond.notify_all();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GeneratorHub::registerGenerator(int32_t id, std::unique_ptr<FakeValueGenerator> generator) {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
+        auto maybeNextEvent = generator->nextEvent();
+        // Register only if the generator can produce at least one event.
+        if (maybeNextEvent.has_value()) {
+            // Push the next event if it is a new generator
+            if (mGenerators.find(id) == mGenerators.end()) {
+                ALOGI("%s: Registering new generator, id: %d", __func__, id);
+                mEventQueue.push({id, maybeNextEvent.value()});
+            }
+            mGenerators[id] = std::move(generator);
+            ALOGI("%s: Registered generator, id: %d", __func__, id);
+        }
+    }
+    mCond.notify_one();
+}
+
+void GeneratorHub::unregisterGenerator(int32_t id) {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
+        mGenerators.erase(id);
+    }
+    mCond.notify_one();
+    ALOGI("%s: Unregistered generator, id: %d", __func__, id);
+}
+
+void GeneratorHub::run() {
+    while (!mShuttingDownFlag.load()) {
+        std::unique_lock<std::mutex> lock(mGeneratorsLock);
+        ScopedLockAssertion lock_assertion(mGeneratorsLock);
+        // Pop events whose generator does not exist (may be already unregistered)
+        while (!mEventQueue.empty() &&
+               mGenerators.find(mEventQueue.top().generatorId) == mGenerators.end()) {
+            mEventQueue.pop();
+        }
+        // Wait until event queue is not empty or shutting down flag is set.
+        // This would unlock mGeneratorsLock and reacquire later.
+        mCond.wait(lock, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
+        if (mShuttingDownFlag.load()) {
+            break;
+        }
+
+        const VhalEvent& curEvent = mEventQueue.top();
+        long currentTime = elapsedRealtimeNano();
+        long waitTime =
+                curEvent.val.timestamp > currentTime ? curEvent.val.timestamp - currentTime : 0;
+        if (waitTime != 0) {
+            // Wait until the soonest event happen
+            if (mCond.wait_for(lock, std::chrono::nanoseconds(waitTime)) !=
+                std::cv_status::timeout) {
+                // It is possible that a new generator is registered and produced a sooner event, or
+                // current generator is unregistered, in this case the thread will re-evaluate the
+                // soonest event
+                ALOGI("Something happened while waiting");
+                continue;
+            }
+        }
+        // Now it's time to handle current event.
+        mOnHalEvent(curEvent.val);
+        // Update queue by popping current event and producing next event from the same generator
+        int32_t id = curEvent.generatorId;
+        mEventQueue.pop();
+        if (mGenerators.find(id) != mGenerators.end()) {
+            auto maybeNextEvent = mGenerators[id]->nextEvent();
+            if (maybeNextEvent.has_value()) {
+                mEventQueue.push({id, maybeNextEvent.value()});
+                continue;
+            }
+        }
+
+        ALOGI("%s: Generator ended, unregister it, id: %d", __func__, id);
+        mGenerators.erase(id);
+    }
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
new file mode 100644
index 0000000..981a077
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "FakeVehicleHalValueGeneratorsTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "VehicleHalUtils",
+        "FakeVehicleHalValueGenerators",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
new file mode 100644
index 0000000..abb3da2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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 <GeneratorHub.h>
+#include <VehicleUtils.h>
+#include <android-base/file.h>
+#include <android-base/thread_annotations.h>
+#include <gtest/gtest.h>
+#include <utils/SystemClock.h>
+
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <thread>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+class FakeVehicleHalValueGeneratorsTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        mHub = std::make_unique<GeneratorHub>(
+                [this](const VehiclePropValue& event) { return onHalEvent(event); });
+    }
+
+    GeneratorHub* getHub() { return mHub.get(); }
+
+    std::vector<VehiclePropValue> getEvents() {
+        std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+        return mEvents;
+    }
+
+    void clearEvents() {
+        std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+        mEvents.clear();
+    }
+
+    void TearDown() override {
+        // Generator callback uses mEvents, must stop generator before destroying mEvents.
+        mHub.reset();
+    }
+
+  private:
+    void onHalEvent(const VehiclePropValue& event) {
+        VehiclePropValue eventCopy = event;
+        std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+        mEvents.push_back(std::move(eventCopy));
+    }
+
+    std::unique_ptr<GeneratorHub> mHub;
+    std::mutex mEventsLock;
+    std::vector<VehiclePropValue> mEvents GUARDED_BY(mEventsLock);
+};
+
+class TestFakeValueGenerator : public FakeValueGenerator {
+  public:
+    void setEvents(const std::vector<VehiclePropValue>& events) {
+        mEvents = events;
+        mEventIndex = 0;
+    }
+
+    std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+            override {
+        if (mEventIndex == mEvents.size()) {
+            return std::nullopt;
+        }
+        return mEvents[mEventIndex++];
+    }
+
+  private:
+    std::vector<VehiclePropValue> mEvents;
+    size_t mEventIndex = 0;
+};
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testRegisterTestFakeValueGenerator) {
+    auto generator = std::make_unique<TestFakeValueGenerator>();
+    std::vector<VehiclePropValue> events;
+    size_t eventCount = 10;
+    int64_t timestamp = elapsedRealtimeNano();
+    for (size_t i = 0; i < eventCount; i++) {
+        events.push_back(VehiclePropValue{
+                .prop = static_cast<int32_t>(i),
+                .timestamp = timestamp + static_cast<int64_t>(50 * i),
+        });
+    }
+    generator->setEvents(events);
+
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // All the events require 500ms to generate, so waiting for 1000ms should be enough.
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    ASSERT_EQ(getEvents(), events);
+
+    getHub()->unregisterGenerator(0);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testUnregisterGeneratorStopGeneration) {
+    auto generator = std::make_unique<TestFakeValueGenerator>();
+    std::vector<VehiclePropValue> events;
+    size_t eventCount = 10;
+    int64_t timestamp = elapsedRealtimeNano();
+    for (size_t i = 0; i < eventCount; i++) {
+        events.push_back(VehiclePropValue{
+                .prop = static_cast<int32_t>(i),
+                .timestamp = timestamp + static_cast<int64_t>(50 * i),
+        });
+    }
+    generator->setEvents(events);
+
+    getHub()->registerGenerator(0, std::move(generator));
+    getHub()->unregisterGenerator(0);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    ASSERT_LT(getEvents().size(), static_cast<size_t>(10))
+            << "Must stop generating event after generator is unregistered";
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 6dc3e76..1c06ba0 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -182,17 +182,17 @@
 }
 
 void FakeVehicleHardware::registerOnPropertyChangeEvent(OnPropertyChangeCallback&& callback) {
-    std::lock_guard<std::mutex> lockGuard(mCallbackLock);
+    std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
     mOnPropertyChangeCallback = std::move(callback);
 }
 
 void FakeVehicleHardware::registerOnPropertySetErrorEvent(OnPropertySetErrorCallback&& callback) {
-    std::lock_guard<std::mutex> lockGuard(mCallbackLock);
+    std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
     mOnPropertySetErrorCallback = std::move(callback);
 }
 
 void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
-    std::lock_guard<std::mutex> lockGuard(mCallbackLock);
+    std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
     if (mOnPropertyChangeCallback != nullptr) {
         std::vector<VehiclePropValue> updatedValues;
         updatedValues.push_back(value);
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
index 68bd559..9a8f19b 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
@@ -44,7 +44,7 @@
     std::vector<T> flush() {
         std::vector<T> items;
 
-        std::lock_guard<std::mutex> lockGuard(mLock);
+        std::scoped_lock<std::mutex> lockGuard(mLock);
         if (mQueue.empty()) {
             return items;
         }
@@ -59,7 +59,7 @@
 
     void push(T&& item) {
         {
-            std::lock_guard<std::mutex> lockGuard(mLock);
+            std::scoped_lock<std::mutex> lockGuard(mLock);
             if (!mIsActive) {
                 return;
             }
@@ -72,7 +72,7 @@
     // The items already in the queue could still be flushed even after the queue is deactivated.
     void deactivate() {
         {
-            std::lock_guard<std::mutex> lockGuard(mLock);
+            std::scoped_lock<std::mutex> lockGuard(mLock);
             mIsActive = false;
         }
         // To unblock all waiting consumers.
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
index 61e475a..4b2a11a 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
@@ -80,7 +80,7 @@
     virtual ~ObjectPool() = default;
 
     virtual recyclable_ptr<T> obtain() {
-        std::lock_guard<std::mutex> lock(mLock);
+        std::scoped_lock<std::mutex> lock(mLock);
         INC_METRIC_IF_DEBUG(Obtained)
         if (mObjects.empty()) {
             INC_METRIC_IF_DEBUG(Created)
@@ -100,7 +100,7 @@
     virtual T* createObject() = 0;
 
     virtual void recycle(T* o) {
-        std::lock_guard<std::mutex> lock(mLock);
+        std::scoped_lock<std::mutex> lock(mLock);
         size_t objectSize = mGetSizeFunc(*o);
 
         if (objectSize > mMaxPoolObjectsSize ||
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
index 0ff58f7..1cdc461 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
@@ -101,7 +101,7 @@
 
 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable(
         VehiclePropertyType type, size_t vectorSize) {
-    std::lock_guard<std::mutex> lock(mLock);
+    std::scoped_lock<std::mutex> lock(mLock);
     assert(vectorSize > 0);
 
     // VehiclePropertyType is not overlapping with vectorSize.
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index 8d12c2b..1a79230 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -53,7 +53,7 @@
 }
 
 VehiclePropertyStore::~VehiclePropertyStore() {
-    std::lock_guard<std::mutex> lockGuard(mLock);
+    std::scoped_lock<std::mutex> lockGuard(mLock);
 
     // Recycling record requires mValuePool, so need to recycle them before destroying mValuePool.
     mRecordsByPropId.clear();
@@ -95,7 +95,7 @@
 
 void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
                                             VehiclePropertyStore::TokenFunction tokenFunc) {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     mRecordsByPropId[config.prop] = Record{
             .propConfig = config,
@@ -105,7 +105,7 @@
 
 Result<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
                                               bool updateStatus) {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     int32_t propId = propValue->prop;
 
@@ -150,7 +150,7 @@
 }
 
 void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
     if (record == nullptr) {
@@ -164,7 +164,7 @@
 }
 
 void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     VehiclePropertyStore::Record* record = getRecordLocked(propId);
     if (record == nullptr) {
@@ -175,7 +175,7 @@
 }
 
 std::vector<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readAllValues() const {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     std::vector<VehiclePropValuePool::RecyclableType> allValues;
 
@@ -190,7 +190,7 @@
 
 Result<std::vector<VehiclePropValuePool::RecyclableType>>
 VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     std::vector<VehiclePropValuePool::RecyclableType> values;
 
@@ -207,7 +207,7 @@
 
 Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(
         const VehiclePropValue& propValue) const {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     int32_t propId = propValue.prop;
     const VehiclePropertyStore::Record* record = getRecordLocked(propId);
@@ -222,7 +222,7 @@
 Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(int32_t propId,
                                                                              int32_t areaId,
                                                                              int64_t token) const {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     const VehiclePropertyStore::Record* record = getRecordLocked(propId);
     if (record == nullptr) {
@@ -234,7 +234,7 @@
 }
 
 std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     std::vector<VehiclePropConfig> configs;
     configs.reserve(mRecordsByPropId.size());
@@ -245,7 +245,7 @@
 }
 
 Result<const VehiclePropConfig*> VehiclePropertyStore::getConfig(int32_t propId) const {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     const VehiclePropertyStore::Record* record = getRecordLocked(propId);
     if (record == nullptr) {
@@ -257,7 +257,7 @@
 
 void VehiclePropertyStore::setOnValueChangeCallback(
         const VehiclePropertyStore::OnValueChangeCallback& callback) {
-    std::lock_guard<std::mutex> g(mLock);
+    std::scoped_lock<std::mutex> g(mLock);
 
     mOnValueChangeCallback = callback;
 }