mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge "Merge tm-qpr-dev-plus-aosp-without-vendor@9467136" into stage-aosp-master
This commit is contained in:
@@ -190,6 +190,40 @@ const std::vector<ConfigDeclaration> kVehicleProperties = {
|
||||
},
|
||||
.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,
|
||||
|
||||
@@ -83,8 +83,9 @@ class RecurrentTimer final {
|
||||
// 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
|
||||
|
||||
@@ -101,68 +101,71 @@ void RecurrentTimer::removeInvalidCallbackLocked() {
|
||||
}
|
||||
}
|
||||
|
||||
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])();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,6 +186,33 @@ TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) {
|
||||
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
|
||||
|
||||
@@ -68,7 +68,7 @@ ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callback)
|
||||
|
||||
IGnssCallback::GnssSystemInfo systemInfo = {
|
||||
.yearOfHw = 2022,
|
||||
.name = "Google Mock GNSS Implementation AIDL v2",
|
||||
.name = "Google, Cuttlefish, AIDL v2",
|
||||
};
|
||||
status = sGnssCallback->gnssSetSystemInfoCb(systemInfo);
|
||||
if (!status.isOk()) {
|
||||
|
||||
@@ -190,12 +190,13 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
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 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
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 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
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 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
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 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
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 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
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 @@ nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
|
||||
}
|
||||
|
||||
// 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 @@ nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::T
|
||||
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 @@ nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::T
|
||||
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 @@ nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::T
|
||||
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 @@ nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::T
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user