Merge "CAS: Fix memory leak in FactoryLoader" am: a81c9a1e2f

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2412032

Change-Id: Ic69e4efa01b911a7884c1b9b55e77c1c3b173f0a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/README.md b/audio/README.md
index 3f40d72..1938ad4 100644
--- a/audio/README.md
+++ b/audio/README.md
@@ -2,29 +2,10 @@
 
 Directory structure of the audio HAL related code.
 
-## Directory Structure for AIDL audio HAL
+Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL
+based on an existing one.
 
-The AIDL version is located inside `aidl` directory. The tree below explains
-the role of each subdirectory:
-
-* `aidl_api` — snapshots of the API created each Android release. Every
-  release, the current version of the API becomes "frozen" and gets assigned
-  the next version number. If the API needs further modifications, they are
-  made on the "current" version. After making modifications, run
-  `m <package name>-update-api` to update the snapshot of the "current"
-  version.
-* `android/hardware/audio/common` — data structures and interfaces shared
-  between various HALs: BT HAL, core and effects audio HALs.
-* `android/hardware/audio/core` — data structures and interfaces of the
-  core audio HAL.
-* `default` — the default, reference implementation of the audio HAL service.
-* `vts` — VTS tests for the AIDL HAL.
-
-## Directory Structure for HIDL audio HAL
-
-Run `common/all-versions/copyHAL.sh` to create a new version of the HIDL audio
-HAL based on an existing one. Note that this isn't possible since Android T
-release. Android U and above uses AIDL audio HAL.
+## Directory Structure
 
 * `2.0` — version 2.0 of the core HIDL API. Note that `.hal` files
   can not be moved into the `core` directory because that would change
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
index 9a93e1a..622846a 100644
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -190,6 +190,40 @@
                  },
          .initialValue = {.int32Values = {toInt(VehicleUnit::KILOWATT_HOUR)}}},
 
+        {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SELECT),
+                    .access = VehiclePropertyAccess::WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3}}},
+         .initialValue = {.int32Values = {1}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SET),
+                    .access = VehiclePropertyAccess::WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 3}}},
+         .initialValue = {.int32Values = {1}}},
+
         {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_BUCKLED),
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
index 5f0f716..cd2b727 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
@@ -83,8 +83,9 @@
     // each time we might introduce outdated elements to the top. We must make sure the heap is
     // always valid from the top.
     void removeInvalidCallbackLocked() REQUIRES(mLock);
-    // Pops the next closest callback (must be valid) from the heap.
-    std::unique_ptr<CallbackInfo> popNextCallbackLocked() REQUIRES(mLock);
+    // Gets the next calblack to run (must be valid) from the heap, update its nextTime and put
+    // it back to the heap.
+    std::shared_ptr<Callback> getNextCallbackLocked(int64_t now) REQUIRES(mLock);
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
index 2eca6b7..908564c 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
@@ -101,68 +101,71 @@
     }
 }
 
-std::unique_ptr<RecurrentTimer::CallbackInfo> RecurrentTimer::popNextCallbackLocked() {
+std::shared_ptr<RecurrentTimer::Callback> RecurrentTimer::getNextCallbackLocked(int64_t now) {
     std::pop_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
-    std::unique_ptr<CallbackInfo> info = std::move(mCallbackQueue[mCallbackQueue.size() - 1]);
-    mCallbackQueue.pop_back();
+    auto& callbackInfo = mCallbackQueue[mCallbackQueue.size() - 1];
+    auto nextCallback = callbackInfo->callback;
+    // intervalCount is the number of interval we have to advance until we pass now.
+    size_t intervalCount = (now - callbackInfo->nextTime) / callbackInfo->interval + 1;
+    callbackInfo->nextTime += intervalCount * callbackInfo->interval;
+    std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
+
     // Make sure the first element is always valid.
     removeInvalidCallbackLocked();
-    return info;
+
+    return nextCallback;
 }
 
 void RecurrentTimer::loop() {
-    std::unique_lock<std::mutex> uniqueLock(mLock);
-
+    std::vector<std::shared_ptr<Callback>> callbacksToRun;
     while (true) {
-        // Wait until the timer exits or we have at least one recurrent callback.
-        mCond.wait(uniqueLock, [this] {
-            ScopedLockAssertion lockAssertion(mLock);
-            return mStopRequested || mCallbackQueue.size() != 0;
-        });
-
-        int64_t interval;
         {
+            std::unique_lock<std::mutex> uniqueLock(mLock);
             ScopedLockAssertion lockAssertion(mLock);
+            // Wait until the timer exits or we have at least one recurrent callback.
+            mCond.wait(uniqueLock, [this] {
+                ScopedLockAssertion lockAssertion(mLock);
+                return mStopRequested || mCallbackQueue.size() != 0;
+            });
+
+            int64_t interval;
             if (mStopRequested) {
                 return;
             }
             // The first element is the nearest next event.
             int64_t nextTime = mCallbackQueue[0]->nextTime;
             int64_t now = uptimeNanos();
+
             if (nextTime > now) {
                 interval = nextTime - now;
             } else {
                 interval = 0;
             }
-        }
 
-        // Wait for the next event or the timer exits.
-        if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] {
-                ScopedLockAssertion lockAssertion(mLock);
-                return mStopRequested;
-            })) {
-            return;
-        }
+            // Wait for the next event or the timer exits.
+            if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] {
+                    ScopedLockAssertion lockAssertion(mLock);
+                    return mStopRequested;
+                })) {
+                return;
+            }
 
-        {
-            ScopedLockAssertion lockAssertion(mLock);
-            int64_t now = uptimeNanos();
+            now = uptimeNanos();
+            callbacksToRun.clear();
             while (mCallbackQueue.size() > 0) {
                 int64_t nextTime = mCallbackQueue[0]->nextTime;
                 if (nextTime > now) {
                     break;
                 }
 
-                std::unique_ptr<CallbackInfo> info = popNextCallbackLocked();
-                info->nextTime += info->interval;
-
-                auto callback = info->callback;
-                mCallbackQueue.push_back(std::move(info));
-                std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
-
-                (*callback)();
+                callbacksToRun.push_back(getNextCallbackLocked(now));
             }
         }
+
+        // Do not execute the callback while holding the lock.
+        for (size_t i = 0; i < callbacksToRun.size(); i++) {
+            (*callbacksToRun[i])();
+        }
     }
 }
 
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
index a033a24..141efc1 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
@@ -186,6 +186,33 @@
     ASSERT_EQ(countTimerCallbackQueue(&timer), static_cast<size_t>(0));
 }
 
+TEST_F(RecurrentTimerTest, testRegisterCallbackMultipleTimesNoDeadLock) {
+    // We want to avoid the following situation:
+    // Caller holds a lock while calling registerTimerCallback, registerTimerCallback will try
+    // to obtain an internal lock inside timer.
+    // Meanwhile an recurrent action happens with timer holding an internal lock. The action
+    // tries to obtain the lock currently hold by the caller.
+    // The solution is that while calling recurrent actions, timer must not hold the internal lock.
+
+    std::unique_ptr<RecurrentTimer> timer = std::make_unique<RecurrentTimer>();
+    std::mutex lock;
+    for (size_t i = 0; i < 1000; i++) {
+        std::scoped_lock<std::mutex> lockGuard(lock);
+        auto action = std::make_shared<RecurrentTimer::Callback>([&lock] {
+            // While calling this function, the timer must not hold lock in order not to dead
+            // lock.
+            std::scoped_lock<std::mutex> lockGuard(lock);
+        });
+        // 10ms
+        int64_t interval = 10'000'000;
+        timer->registerTimerCallback(interval, action);
+        // Sleep for a little while to let the recurrent actions begin.
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    }
+    // Make sure we stop the timer before we destroy lock.
+    timer.reset();
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index cf2c90d..2d6490c 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -68,7 +68,7 @@
 
     IGnssCallback::GnssSystemInfo systemInfo = {
             .yearOfHw = 2022,
-            .name = "Google Mock GNSS Implementation AIDL v2",
+            .name = "Google, Cuttlefish, AIDL v2",
     };
     status = sGnssCallback->gnssSetSystemInfoCb(systemInfo);
     if (!status.isOk()) {
diff --git a/neuralnetworks/1.2/utils/src/BurstUtils.cpp b/neuralnetworks/1.2/utils/src/BurstUtils.cpp
index b589c46..c4c096d 100644
--- a/neuralnetworks/1.2/utils/src/BurstUtils.cpp
+++ b/neuralnetworks/1.2/utils/src/BurstUtils.cpp
@@ -190,12 +190,13 @@
     size_t index = 0;
 
     // validate packet information
-    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
+    if (index >= data.size() ||
+        data.at(index).getDiscriminator() != discriminator::packetInformation) {
         return NN_ERROR() << "FMQ Request packet ill-formed";
     }
 
     // unpackage packet information
-    const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation();
+    const FmqRequestDatum::PacketInformation& packetInfo = data.at(index).packetInformation();
     index++;
     const uint32_t packetSize = packetInfo.packetSize;
     const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands;
@@ -212,13 +213,14 @@
     inputs.reserve(numberOfInputOperands);
     for (size_t operand = 0; operand < numberOfInputOperands; ++operand) {
         // validate input operand information
-        if (data[index].getDiscriminator() != discriminator::inputOperandInformation) {
+        if (index >= data.size() ||
+            data.at(index).getDiscriminator() != discriminator::inputOperandInformation) {
             return NN_ERROR() << "FMQ Request packet ill-formed";
         }
 
         // unpackage operand information
         const FmqRequestDatum::OperandInformation& operandInfo =
-                data[index].inputOperandInformation();
+                data.at(index).inputOperandInformation();
         index++;
         const bool hasNoValue = operandInfo.hasNoValue;
         const V1_0::DataLocation location = operandInfo.location;
@@ -229,12 +231,13 @@
         dimensions.reserve(numberOfDimensions);
         for (size_t i = 0; i < numberOfDimensions; ++i) {
             // validate dimension
-            if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) {
+            if (index >= data.size() ||
+                data.at(index).getDiscriminator() != discriminator::inputOperandDimensionValue) {
                 return NN_ERROR() << "FMQ Request packet ill-formed";
             }
 
             // unpackage dimension
-            const uint32_t dimension = data[index].inputOperandDimensionValue();
+            const uint32_t dimension = data.at(index).inputOperandDimensionValue();
             index++;
 
             // store result
@@ -251,13 +254,14 @@
     outputs.reserve(numberOfOutputOperands);
     for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) {
         // validate output operand information
-        if (data[index].getDiscriminator() != discriminator::outputOperandInformation) {
+        if (index >= data.size() ||
+            data.at(index).getDiscriminator() != discriminator::outputOperandInformation) {
             return NN_ERROR() << "FMQ Request packet ill-formed";
         }
 
         // unpackage operand information
         const FmqRequestDatum::OperandInformation& operandInfo =
-                data[index].outputOperandInformation();
+                data.at(index).outputOperandInformation();
         index++;
         const bool hasNoValue = operandInfo.hasNoValue;
         const V1_0::DataLocation location = operandInfo.location;
@@ -268,12 +272,13 @@
         dimensions.reserve(numberOfDimensions);
         for (size_t i = 0; i < numberOfDimensions; ++i) {
             // validate dimension
-            if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) {
+            if (index >= data.size() ||
+                data.at(index).getDiscriminator() != discriminator::outputOperandDimensionValue) {
                 return NN_ERROR() << "FMQ Request packet ill-formed";
             }
 
             // unpackage dimension
-            const uint32_t dimension = data[index].outputOperandDimensionValue();
+            const uint32_t dimension = data.at(index).outputOperandDimensionValue();
             index++;
 
             // store result
@@ -290,12 +295,13 @@
     slots.reserve(numberOfPools);
     for (size_t pool = 0; pool < numberOfPools; ++pool) {
         // validate input operand information
-        if (data[index].getDiscriminator() != discriminator::poolIdentifier) {
+        if (index >= data.size() ||
+            data.at(index).getDiscriminator() != discriminator::poolIdentifier) {
             return NN_ERROR() << "FMQ Request packet ill-formed";
         }
 
         // unpackage operand information
-        const int32_t poolId = data[index].poolIdentifier();
+        const int32_t poolId = data.at(index).poolIdentifier();
         index++;
 
         // store result
@@ -303,17 +309,17 @@
     }
 
     // validate measureTiming
-    if (data[index].getDiscriminator() != discriminator::measureTiming) {
+    if (index >= data.size() || data.at(index).getDiscriminator() != discriminator::measureTiming) {
         return NN_ERROR() << "FMQ Request packet ill-formed";
     }
 
     // unpackage measureTiming
-    const V1_2::MeasureTiming measure = data[index].measureTiming();
+    const V1_2::MeasureTiming measure = data.at(index).measureTiming();
     index++;
 
     // validate packet information
     if (index != packetSize) {
-        return NN_ERROR() << "FMQ Result packet ill-formed";
+        return NN_ERROR() << "FMQ Request packet ill-formed";
     }
 
     // return request
@@ -328,12 +334,13 @@
     size_t index = 0;
 
     // validate packet information
-    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
+    if (index >= data.size() ||
+        data.at(index).getDiscriminator() != discriminator::packetInformation) {
         return NN_ERROR() << "FMQ Result packet ill-formed";
     }
 
     // unpackage packet information
-    const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation();
+    const FmqResultDatum::PacketInformation& packetInfo = data.at(index).packetInformation();
     index++;
     const uint32_t packetSize = packetInfo.packetSize;
     const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus;
@@ -349,12 +356,13 @@
     outputShapes.reserve(numberOfOperands);
     for (size_t operand = 0; operand < numberOfOperands; ++operand) {
         // validate operand information
-        if (data[index].getDiscriminator() != discriminator::operandInformation) {
+        if (index >= data.size() ||
+            data.at(index).getDiscriminator() != discriminator::operandInformation) {
             return NN_ERROR() << "FMQ Result packet ill-formed";
         }
 
         // unpackage operand information
-        const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation();
+        const FmqResultDatum::OperandInformation& operandInfo = data.at(index).operandInformation();
         index++;
         const bool isSufficient = operandInfo.isSufficient;
         const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
@@ -364,12 +372,13 @@
         dimensions.reserve(numberOfDimensions);
         for (size_t i = 0; i < numberOfDimensions; ++i) {
             // validate dimension
-            if (data[index].getDiscriminator() != discriminator::operandDimensionValue) {
+            if (index >= data.size() ||
+                data.at(index).getDiscriminator() != discriminator::operandDimensionValue) {
                 return NN_ERROR() << "FMQ Result packet ill-formed";
             }
 
             // unpackage dimension
-            const uint32_t dimension = data[index].operandDimensionValue();
+            const uint32_t dimension = data.at(index).operandDimensionValue();
             index++;
 
             // store result
@@ -381,12 +390,13 @@
     }
 
     // validate execution timing
-    if (data[index].getDiscriminator() != discriminator::executionTiming) {
+    if (index >= data.size() ||
+        data.at(index).getDiscriminator() != discriminator::executionTiming) {
         return NN_ERROR() << "FMQ Result packet ill-formed";
     }
 
     // unpackage execution timing
-    const V1_2::Timing timing = data[index].executionTiming();
+    const V1_2::Timing timing = data.at(index).executionTiming();
     index++;
 
     // validate packet information