Merge "Added resolution to SubscribeOptions." into main
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
index e53947e..3fecbd9 100644
--- a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -118,7 +118,7 @@
virtual aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
// Register a callback that would be called when there is a property change event from vehicle.
- // Must only be called once during initialization.
+ // This function must only be called once during initialization.
virtual void registerOnPropertyChangeEvent(
std::unique_ptr<const PropertyChangeCallback> callback) = 0;
@@ -126,6 +126,25 @@
// vehicle. Must only be called once during initialization.
virtual void registerOnPropertySetErrorEvent(
std::unique_ptr<const PropertySetErrorCallback> callback) = 0;
+
+ // Gets the batching window used by DefaultVehicleHal for property change events.
+ //
+ // In DefaultVehicleHal, all the property change events generated within the batching window
+ // will be delivered through one callback to the VHAL client. This affects the maximum supported
+ // subscription rate. For example, if this returns 10ms, then only one callback for property
+ // change events will be called per 10ms, meaining that the max subscription rate for all
+ // continuous properties would be 100hz.
+ //
+ // A higher batching window means less callbacks to the VHAL client, causing a better
+ // performance. However, it also means a longer average latency for every property change
+ // events.
+ //
+ // 0 means no batching should be enabled in DefaultVehicleHal. In this case, batching can
+ // be optionally implemented in IVehicleHardware layer.
+ virtual std::chrono::nanoseconds getPropertyOnChangeEventBatchingWindow() {
+ // By default batching is disabled.
+ return std::chrono::nanoseconds(0);
+ }
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
index 327c0dc..b636aa3 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
@@ -69,6 +69,19 @@
mCond.notify_one();
}
+ void push(std::vector<T>&& items) {
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (!mIsActive) {
+ return;
+ }
+ for (T& item : items) {
+ mQueue.push(std::move(item));
+ }
+ }
+ mCond.notify_one();
+ }
+
// Deactivates the queue, thus no one can push items to it, also notifies all waiting thread.
// The items already in the queue could still be flushed even after the queue is deactivated.
void deactivate() {
@@ -92,6 +105,69 @@
std::queue<T> mQueue GUARDED_BY(mLock);
};
+template <typename T>
+class BatchingConsumer {
+ private:
+ enum class State {
+ INIT = 0,
+ RUNNING = 1,
+ STOP_REQUESTED = 2,
+ STOPPED = 3,
+ };
+
+ public:
+ BatchingConsumer() : mState(State::INIT) {}
+
+ BatchingConsumer(const BatchingConsumer&) = delete;
+ BatchingConsumer& operator=(const BatchingConsumer&) = delete;
+
+ using OnBatchReceivedFunc = std::function<void(std::vector<T> vec)>;
+
+ void run(ConcurrentQueue<T>* queue, std::chrono::nanoseconds batchInterval,
+ const OnBatchReceivedFunc& func) {
+ mQueue = queue;
+ mBatchInterval = batchInterval;
+
+ mWorkerThread = std::thread(&BatchingConsumer<T>::runInternal, this, func);
+ }
+
+ void requestStop() { mState = State::STOP_REQUESTED; }
+
+ void waitStopped() {
+ if (mWorkerThread.joinable()) {
+ mWorkerThread.join();
+ }
+ }
+
+ private:
+ void runInternal(const OnBatchReceivedFunc& onBatchReceived) {
+ if (mState.exchange(State::RUNNING) == State::INIT) {
+ while (State::RUNNING == mState) {
+ mQueue->waitForItems();
+ if (State::STOP_REQUESTED == mState) break;
+
+ std::this_thread::sleep_for(mBatchInterval);
+ if (State::STOP_REQUESTED == mState) break;
+
+ std::vector<T> items = mQueue->flush();
+
+ if (items.size() > 0) {
+ onBatchReceived(std::move(items));
+ }
+ }
+ }
+
+ mState = State::STOPPED;
+ }
+
+ private:
+ std::thread mWorkerThread;
+
+ std::atomic<State> mState;
+ std::chrono::nanoseconds mBatchInterval;
+ ConcurrentQueue<T>* mQueue;
+};
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 419e16b..9a42180 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -144,6 +144,15 @@
std::shared_ptr<PendingRequestPool> mPendingRequestPool;
// SubscriptionManager is thread-safe.
std::shared_ptr<SubscriptionManager> mSubscriptionManager;
+ // ConcurrentQueue is thread-safe.
+ std::shared_ptr<ConcurrentQueue<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
+ mBatchedEventQueue;
+ // BatchingConsumer is thread-safe.
+ std::shared_ptr<
+ BatchingConsumer<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
+ mPropertyChangeEventsBatchingConsumer;
+ // Only set once during initialization.
+ std::chrono::nanoseconds mEventBatchingWindow;
std::mutex mLock;
std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -209,6 +218,19 @@
size_t countSubscribeClients();
+ // Handles the property change events in batch.
+ void handleBatchedPropertyEvents(
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
+ batchedEvents);
+
+ // Puts the property change events into a queue so that they can handled in batch.
+ static void batchPropertyChangeEvent(
+ const std::weak_ptr<ConcurrentQueue<
+ aidl::android::hardware::automotive::vehicle::VehiclePropValue>>&
+ batchedEventQueue,
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
+ updatedValues);
+
// Gets or creates a {@code T} object for the client to or from {@code clients}.
template <class T>
static std::shared_ptr<T> getOrCreateClient(
@@ -217,7 +239,7 @@
static void onPropertyChangeEvent(
const std::weak_ptr<SubscriptionManager>& subscriptionManager,
- const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
updatedValues);
static void onPropertySetErrorEvent(
diff --git a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
index 512d906..b91895e 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
@@ -92,11 +92,10 @@
// For a list of updated properties, returns a map that maps clients subscribing to
// the updated properties to a list of updated values. This would only return on-change property
// clients that should be informed for the given updated values.
- std::unordered_map<
- CallbackType,
- std::vector<const aidl::android::hardware::automotive::vehicle::VehiclePropValue*>>
+ std::unordered_map<CallbackType,
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
getSubscribedClients(
- const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
updatedValues);
// For a list of set property error events, returns a map that maps clients subscribing to the
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index f3eba2e..111a6ec 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -32,6 +32,7 @@
#include <utils/Trace.h>
#include <inttypes.h>
+#include <chrono>
#include <set>
#include <unordered_set>
@@ -101,12 +102,32 @@
IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
+ mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
+ if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
+ mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
+ mPropertyChangeEventsBatchingConsumer =
+ std::make_shared<BatchingConsumer<VehiclePropValue>>();
+ mPropertyChangeEventsBatchingConsumer->run(
+ mBatchedEventQueue.get(), mEventBatchingWindow,
+ [this](std::vector<VehiclePropValue> batchedEvents) {
+ handleBatchedPropertyEvents(std::move(batchedEvents));
+ });
+ }
+ std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
+ std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
mVehicleHardware->registerOnPropertyChangeEvent(
std::make_unique<IVehicleHardware::PropertyChangeCallback>(
- [subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) {
- onPropertyChangeEvent(subscriptionManagerCopy, updatedValues);
+ [subscriptionManagerCopy, batchedEventQueueCopy,
+ eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
+ if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
+ batchPropertyChangeEvent(batchedEventQueueCopy,
+ std::move(updatedValues));
+ } else {
+ onPropertyChangeEvent(subscriptionManagerCopy,
+ std::move(updatedValues));
+ }
}));
mVehicleHardware->registerOnPropertySetErrorEvent(
std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
@@ -139,26 +160,47 @@
// mRecurrentAction uses pointer to mVehicleHardware, so it has to be unregistered before
// mVehicleHardware.
mRecurrentTimer.unregisterTimerCallback(mRecurrentAction);
+
+ if (mBatchedEventQueue) {
+ // mPropertyChangeEventsBatchingConsumer uses mSubscriptionManager and mBatchedEventQueue.
+ mBatchedEventQueue->deactivate();
+ mPropertyChangeEventsBatchingConsumer->requestStop();
+ mPropertyChangeEventsBatchingConsumer->waitStopped();
+ mPropertyChangeEventsBatchingConsumer.reset();
+ mBatchedEventQueue.reset();
+ }
+
// mSubscriptionManager uses pointer to mVehicleHardware, so it has to be destroyed before
// mVehicleHardware.
mSubscriptionManager.reset();
mVehicleHardware.reset();
}
+void DefaultVehicleHal::batchPropertyChangeEvent(
+ const std::weak_ptr<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
+ std::vector<VehiclePropValue>&& updatedValues) {
+ auto batchedEventQueueStrong = batchedEventQueue.lock();
+ if (batchedEventQueueStrong == nullptr) {
+ ALOGW("the batched property events queue is destroyed, DefaultVehicleHal is ending");
+ return;
+ }
+ batchedEventQueueStrong->push(std::move(updatedValues));
+}
+
+void DefaultVehicleHal::handleBatchedPropertyEvents(std::vector<VehiclePropValue>&& batchedEvents) {
+ onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
+}
+
void DefaultVehicleHal::onPropertyChangeEvent(
const std::weak_ptr<SubscriptionManager>& subscriptionManager,
- const std::vector<VehiclePropValue>& updatedValues) {
+ std::vector<VehiclePropValue>&& updatedValues) {
auto manager = subscriptionManager.lock();
if (manager == nullptr) {
ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
return;
}
- auto updatedValuesByClients = manager->getSubscribedClients(updatedValues);
- for (const auto& [callback, valuePtrs] : updatedValuesByClients) {
- std::vector<VehiclePropValue> values;
- for (const VehiclePropValue* valuePtr : valuePtrs) {
- values.push_back(*valuePtr);
- }
+ auto updatedValuesByClients = manager->getSubscribedClients(std::move(updatedValues));
+ for (auto& [callback, values] : updatedValuesByClients) {
SubscriptionClient::sendUpdatedValues(callback, std::move(values));
}
}
@@ -742,12 +784,12 @@
return;
}
std::vector<VehiclePropValue> values = {{
- .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
.areaId = 0,
+ .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
.status = VehiclePropertyStatus::AVAILABLE,
.value.int64Values = {uptimeMillis()},
}};
- onPropertyChangeEvent(subscriptionManager, values);
+ onPropertyChangeEvent(subscriptionManager, std::move(values));
return;
}
diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
index 17683ae..b3c2693 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
@@ -248,13 +248,12 @@
return {};
}
-std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<const VehiclePropValue*>>
-SubscriptionManager::getSubscribedClients(const std::vector<VehiclePropValue>& updatedValues) {
+std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropValue>>
+SubscriptionManager::getSubscribedClients(std::vector<VehiclePropValue>&& updatedValues) {
std::scoped_lock<std::mutex> lockGuard(mLock);
- std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<const VehiclePropValue*>>
- clients;
+ std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropValue>> clients;
- for (const auto& value : updatedValues) {
+ for (auto& value : updatedValues) {
PropIdAreaId propIdAreaId{
.propId = value.prop,
.areaId = value.areaId,
@@ -264,7 +263,7 @@
}
for (const auto& [_, client] : mClientsByPropIdArea[propIdAreaId]) {
- clients[client].push_back(&value);
+ clients[client].push_back(value);
}
}
return clients;
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index fb14373..e775612 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -211,8 +211,9 @@
class DefaultVehicleHalTest : public testing::Test {
public:
- void SetUp() override {
- auto hardware = std::make_unique<MockVehicleHardware>();
+ void SetUp() override { init(std::make_unique<MockVehicleHardware>()); }
+
+ void init(std::unique_ptr<MockVehicleHardware> hardware) {
std::vector<VehiclePropConfig> testConfigs;
for (size_t i = 0; i < 10000; i++) {
testConfigs.push_back(VehiclePropConfig{
@@ -1711,6 +1712,93 @@
ASSERT_THAT(vehiclePropErrors.payloads, UnorderedElementsAreArray(expectedResults));
}
+TEST_F(DefaultVehicleHalTest, testBatchOnPropertyChangeEvents) {
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyOnChangeEventBatchingWindow(std::chrono::milliseconds(10));
+ init(std::move(hardware));
+
+ std::vector<SubscribeOptions> options = {
+ {
+ .propId = GLOBAL_ON_CHANGE_PROP,
+ },
+ {
+ .propId = AREA_ON_CHANGE_PROP,
+ // No areaIds means subscribing to all area IDs.
+ .areaIds = {},
+ },
+ };
+
+ getClient()->subscribe(getCallbackClient(), options, 0);
+ VehiclePropValue testValue1 = {
+ .prop = GLOBAL_ON_CHANGE_PROP,
+ .value.int32Values = {0},
+ };
+ SetValueRequest request1 = {
+ .requestId = 1,
+ .value = testValue1,
+ };
+ SetValueResult result1 = {
+ .requestId = 1,
+ .status = StatusCode::OK,
+ };
+ VehiclePropValue testValue2 = {
+ .prop = AREA_ON_CHANGE_PROP,
+ .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT),
+ .value.int32Values = {1},
+ };
+ SetValueRequest request2 = {
+ .requestId = 2,
+ .value = testValue2,
+ };
+ SetValueResult result2 = {
+ .requestId = 2,
+ .status = StatusCode::OK,
+ };
+ VehiclePropValue testValue3 = {
+ .prop = AREA_ON_CHANGE_PROP,
+ .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT),
+ .value.int32Values = {1},
+ };
+ SetValueRequest request3 = {
+ .requestId = 3,
+ .value = testValue3,
+ };
+ SetValueResult result3 = {
+ .requestId = 3,
+ .status = StatusCode::OK,
+ };
+ // Prepare the responses
+ for (int i = 0; i < 2; i++) {
+ getHardware()->addSetValueResponses({result1});
+ getHardware()->addSetValueResponses({result2, result3});
+ }
+
+ // Try to cause two batches, each with three on property change events.
+ // Set GLOBAL_ON_CHANGE_PROP causing one event.
+ // Set AREA_ON_CHANGE_PROP with two areas causing two events.
+ for (int i = 0; i < 2; i++) {
+ auto status = getClient()->setValues(getCallbackClient(),
+ SetValueRequests{.payloads = {request1}});
+ ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+ status = getClient()->setValues(getCallbackClient(),
+ SetValueRequests{.payloads = {request2, request3}});
+ ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+ ASSERT_TRUE(getCallback()->waitForOnPropertyEventResults(/*size=*/1,
+ /*timeoutInNano=*/1'000'000'000))
+ << "not received enough property change events before timeout";
+
+ auto maybeResults = getCallback()->nextOnPropertyEventResults();
+ ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
+ ASSERT_THAT(maybeResults.value().payloads,
+ UnorderedElementsAre(testValue1, testValue2, testValue3))
+ << "results mismatch, expect 3 batched on change events";
+ ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
+ << "more results than expected";
+ }
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
index 54fede1..c272123 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
@@ -137,6 +137,14 @@
});
}
+bool MockVehicleCallback::waitForOnPropertyEventResults(size_t size, size_t timeoutInNano) {
+ std::unique_lock lk(mLock);
+ return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mOnPropertyEventResults.size() >= size;
+ });
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
index 1545eae..672ff4f 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
@@ -69,6 +69,7 @@
size_t countOnPropertyEventResults();
bool waitForSetValueResults(size_t size, size_t timeoutInNano);
bool waitForGetValueResults(size_t size, size_t timeoutInNano);
+ bool waitForOnPropertyEventResults(size_t size, size_t timeoutInNano);
private:
std::mutex mLock;
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
index ba0d33d..3fae596 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
@@ -186,6 +186,16 @@
mSleepTime = timeInNano;
}
+void MockVehicleHardware::setPropertyOnChangeEventBatchingWindow(std::chrono::nanoseconds window) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mEventBatchingWindow = window;
+}
+
+std::chrono::nanoseconds MockVehicleHardware::getPropertyOnChangeEventBatchingWindow() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mEventBatchingWindow;
+}
+
template <class ResultType>
StatusCode MockVehicleHardware::returnResponse(
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
index 46b30b9..3ce18c5 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
@@ -24,6 +24,7 @@
#include <android-base/thread_annotations.h>
#include <atomic>
+#include <chrono>
#include <condition_variable>
#include <list>
#include <memory>
@@ -60,6 +61,7 @@
void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override;
aidl::android::hardware::automotive::vehicle::StatusCode updateSampleRate(
int32_t propId, int32_t areaId, float sampleRate) override;
+ std::chrono::nanoseconds getPropertyOnChangeEventBatchingWindow() override;
// Test functions.
void setPropertyConfigs(
@@ -86,6 +88,7 @@
void setSleepTime(int64_t timeInNano);
void setDumpResult(DumpResult result);
void sendOnPropertySetErrorEvent(const std::vector<SetValueErrorEvent>& errorEvents);
+ void setPropertyOnChangeEventBatchingWindow(std::chrono::nanoseconds window);
private:
mutable std::mutex mLock;
@@ -110,6 +113,7 @@
std::shared_ptr<const GetValuesCallback>,
const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&)>
mGetValueResponder GUARDED_BY(mLock);
+ std::chrono::nanoseconds mEventBatchingWindow GUARDED_BY(mLock) = std::chrono::nanoseconds(0);
template <class ResultType>
aidl::android::hardware::automotive::vehicle::StatusCode returnResponse(
diff --git a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
index cb8c8d1..5464304 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
@@ -48,7 +48,7 @@
using ::ndk::ScopedAStatus;
using ::ndk::SpAIBinder;
using ::testing::ElementsAre;
-using ::testing::WhenSorted;
+using ::testing::UnorderedElementsAre;
class PropertyCallback final : public BnVehicleCallback {
public:
@@ -389,11 +389,11 @@
.areaId = 1,
},
};
- auto clients = getManager()->getSubscribedClients(updatedValues);
+ auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
ASSERT_THAT(clients[client1],
- WhenSorted(ElementsAre(&updatedValues[0], &updatedValues[1], &updatedValues[2])));
- ASSERT_THAT(clients[client2], ElementsAre(&updatedValues[0]));
+ UnorderedElementsAre(updatedValues[0], updatedValues[1], updatedValues[2]));
+ ASSERT_THAT(clients[client2], ElementsAre(updatedValues[0]));
}
TEST_F(SubscriptionManagerTest, testSubscribeInvalidOption) {
@@ -480,9 +480,9 @@
.areaId = 0,
},
};
- auto clients = getManager()->getSubscribedClients(updatedValues);
+ auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
- ASSERT_THAT(clients[getCallbackClient()], ElementsAre(&updatedValues[1]));
+ ASSERT_THAT(clients[getCallbackClient()], ElementsAre(updatedValues[1]));
}
TEST_F(SubscriptionManagerTest, testCheckSampleRateHzValid) {
diff --git a/broadcastradio/aidl/default/Android.bp b/broadcastradio/aidl/default/Android.bp
index 1d1bef7..e95208c 100644
--- a/broadcastradio/aidl/default/Android.bp
+++ b/broadcastradio/aidl/default/Android.bp
@@ -62,7 +62,7 @@
cc_library {
name: "DefaultBroadcastRadioHal",
- vendor: true,
+ vendor_available: true,
export_include_dirs: ["."],
defaults: [
"BroadcastRadioHalDefaults",
@@ -76,7 +76,8 @@
cc_fuzz {
name: "android.hardware.broadcastradio-service.default_fuzzer",
- vendor: true,
+ // TODO(b/307611931): avoid fuzzing on vendor until hermiticity issue is fixed
+ // vendor: true,
defaults: [
"BroadcastRadioHalDefaults",
"service_fuzzer_defaults",
diff --git a/rebootescrow/aidl/default/Android.bp b/rebootescrow/aidl/default/Android.bp
index 4409314..7f9b6d6 100644
--- a/rebootescrow/aidl/default/Android.bp
+++ b/rebootescrow/aidl/default/Android.bp
@@ -42,10 +42,10 @@
cc_binary {
name: "android.hardware.rebootescrow-service.default",
- init_rc: ["rebootescrow-default.rc"],
relative_install_path: "hw",
- vintf_fragments: ["rebootescrow-default.xml"],
vendor: true,
+ installable: false, // installed in APEX
+
srcs: [
"service.cpp",
],
@@ -53,12 +53,14 @@
"-Wall",
"-Werror",
],
+ stl: "c++_static",
shared_libs: [
- "libbase",
"libbinder_ndk",
- "android.hardware.rebootescrow-V1-ndk",
+ "liblog",
],
static_libs: [
+ "android.hardware.rebootescrow-V1-ndk",
+ "libbase",
"libhadamardutils",
"librebootescrowdefaultimpl",
],
@@ -97,3 +99,35 @@
],
test_suites: ["device-tests"],
}
+
+prebuilt_etc {
+ name: "rebootescrow-default.rc",
+ src: "rebootescrow-default.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "rebootescrow-default.xml",
+ src: "rebootescrow-default.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.rebootescrow",
+ manifest: "apex_manifest.json",
+ file_contexts: "apex_file_contexts",
+ key: "com.android.hardware.key",
+ certificate: ":com.android.hardware.certificate",
+ vendor: true,
+ updatable: false,
+
+ binaries: [
+ "android.hardware.rebootescrow-service.default",
+ ],
+ prebuilts: [
+ "rebootescrow-default.rc",
+ "rebootescrow-default.xml",
+ "android.hardware.reboot_escrow.prebuilt.xml", // <feature>
+ ],
+}
diff --git a/rebootescrow/aidl/default/apex_file_contexts b/rebootescrow/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..aa84984
--- /dev/null
+++ b/rebootescrow/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.rebootescrow-service\.default u:object_r:hal_rebootescrow_default_exec:s0
diff --git a/rebootescrow/aidl/default/apex_manifest.json b/rebootescrow/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..8be495b
--- /dev/null
+++ b/rebootescrow/aidl/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.rebootescrow",
+ "version": 1
+}
\ No newline at end of file
diff --git a/rebootescrow/aidl/default/rebootescrow-default.rc b/rebootescrow/aidl/default/rebootescrow-default.rc
index ad90465..024dd6d 100644
--- a/rebootescrow/aidl/default/rebootescrow-default.rc
+++ b/rebootescrow/aidl/default/rebootescrow-default.rc
@@ -1,4 +1,4 @@
-service vendor.rebootescrow-default /vendor/bin/hw/android.hardware.rebootescrow-service.default
+service vendor.rebootescrow-default /apex/com.android.hardware.rebootescrow/bin/hw/android.hardware.rebootescrow-service.default
interface aidl android.hardware.rebootescrow.IRebootEscrow/default
class hal
user system
diff --git a/secure_element/aidl/default/Android.bp b/secure_element/aidl/default/Android.bp
index d1bb393..b382822 100644
--- a/secure_element/aidl/default/Android.bp
+++ b/secure_element/aidl/default/Android.bp
@@ -11,14 +11,50 @@
name: "android.hardware.secure_element-service.example",
relative_install_path: "hw",
vendor: true,
- init_rc: ["secure_element.rc"],
- vintf_fragments: ["secure_element.xml"],
+ installable: false, // installed in APEX
+
+ stl: "c++_static",
shared_libs: [
- "libbase",
"libbinder_ndk",
+ "liblog",
+ ],
+ static_libs: [
"android.hardware.secure_element-V1-ndk",
+ "libbase",
],
srcs: [
"main.cpp",
],
}
+
+prebuilt_etc {
+ name: "secure_element.rc",
+ src: "secure_element.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "secure_element.xml",
+ src: "secure_element.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.secure_element",
+ manifest: "apex_manifest.json",
+ file_contexts: "apex_file_contexts",
+ key: "com.android.hardware.key",
+ certificate: ":com.android.hardware.certificate",
+ vendor: true,
+ updatable: false,
+
+ binaries: [
+ "android.hardware.secure_element-service.example",
+ ],
+ prebuilts: [
+ "secure_element.rc",
+ "secure_element.xml",
+ "android.hardware.se.omapi.ese.prebuilt.xml", // <feature>
+ ],
+}
diff --git a/secure_element/aidl/default/apex_file_contexts b/secure_element/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..e9e811e
--- /dev/null
+++ b/secure_element/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.secure_element-service\.example u:object_r:hal_secure_element_default_exec:s0
\ No newline at end of file
diff --git a/secure_element/aidl/default/apex_manifest.json b/secure_element/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..6e04c11
--- /dev/null
+++ b/secure_element/aidl/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.secure_element",
+ "version": 1
+}
\ No newline at end of file
diff --git a/secure_element/aidl/default/secure_element.rc b/secure_element/aidl/default/secure_element.rc
index 7d21666..b74b2ee 100644
--- a/secure_element/aidl/default/secure_element.rc
+++ b/secure_element/aidl/default/secure_element.rc
@@ -1,4 +1,4 @@
-service vendor.secure_element /vendor/bin/hw/android.hardware.secure_element-service.example
+service vendor.secure_element /apex/com.android.hardware.secure_element/bin/hw/android.hardware.secure_element-service.example
class hal
user nobody
group nobody