Merge "Hide all GNSS AIDL interfaces/parcelables/enums" into tm-dev
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index ad607d8..9c72acd 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -18,7 +18,7 @@
// These values are called out in the EVS design doc (as of Mar 8, 2017)
-static const int kMaxStreamStartMilliseconds = 500;
+static const int kMaxStreamStartMilliseconds = 1000;
static const int kMinimumFramesPerSecond = 10;
static const int kSecondsToMilliseconds = 1000;
@@ -332,11 +332,6 @@
printf("Measured time to first frame %0.2f ms\n", timeToFirstFrame * kNanoToMilliseconds);
ALOGI("Measured time to first frame %0.2f ms", timeToFirstFrame * kNanoToMilliseconds);
- // Check aspect ratio
- unsigned width = 0, height = 0;
- frameHandler->getFrameDimension(&width, &height);
- EXPECT_GE(width, height);
-
// Wait a bit, then ensure we get at least the required minimum number of frames
sleep(5);
nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -370,7 +365,7 @@
ALOGI("Starting CameraStreamBuffering test");
// Arbitrary constant (should be > 1 and not too big)
- static const unsigned int kBuffersToHold = 6;
+ static const unsigned int kBuffersToHold = 2;
// Get the camera list
loadCameraList();
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index c33a2e7..84323ea 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -499,11 +499,6 @@
<< std::scientific << timeToFirstFrame * kNanoToMilliseconds
<< " ms.";
- // Check aspect ratio
- unsigned width = 0, height = 0;
- frameHandler->getFrameDimension(&width, &height);
- EXPECT_GE(width, height);
-
// Wait a bit, then ensure we get at least the required minimum number of frames
sleep(5);
nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -541,7 +536,7 @@
LOG(INFO) << "Starting CameraStreamBuffering test";
// Arbitrary constant (should be > 1 and not too big)
- static const unsigned int kBuffersToHold = 6;
+ static const unsigned int kBuffersToHold = 2;
// Get the camera list
loadCameraList();
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
index 08b56a6..327c0dc 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
@@ -33,12 +33,13 @@
template <typename T>
class ConcurrentQueue {
public:
- void waitForItems() {
+ bool waitForItems() {
std::unique_lock<std::mutex> lockGuard(mLock);
android::base::ScopedLockAssertion lockAssertion(mLock);
while (mQueue.empty() && mIsActive) {
mCond.wait(lockGuard);
}
+ return mIsActive;
}
std::vector<T> flush() {
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 84b6742..2db7675 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -22,6 +22,7 @@
#include "PendingRequestPool.h"
#include "SubscriptionManager.h"
+#include <ConcurrentQueue.h>
#include <IVehicleHardware.h>
#include <VehicleUtils.h>
#include <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
@@ -31,6 +32,7 @@
#include <memory>
#include <mutex>
+#include <shared_mutex>
#include <unordered_map>
#include <vector>
@@ -105,6 +107,8 @@
public:
SubscriptionClients(std::shared_ptr<PendingRequestPool> pool) : mPendingRequestPool(pool) {}
+ std::shared_ptr<SubscriptionClient> maybeAddClient(const CallbackType& callback);
+
std::shared_ptr<SubscriptionClient> getClient(const CallbackType& callback);
void removeClient(const AIBinder* clientId);
@@ -119,20 +123,24 @@
std::shared_ptr<PendingRequestPool> mPendingRequestPool;
};
- // A wrapper for linkToDeath to enable stubbing for test.
- class ILinkToDeath {
+ // A wrapper for binder operations to enable stubbing for test.
+ class IBinder {
public:
- virtual ~ILinkToDeath() = default;
+ virtual ~IBinder() = default;
virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) = 0;
+
+ virtual bool isAlive(const AIBinder* binder) = 0;
};
- // A real implementation for ILinkToDeath.
- class AIBinderLinkToDeathImpl final : public ILinkToDeath {
+ // A real implementation for IBinder.
+ class AIBinderImpl final : public IBinder {
public:
binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) override;
+
+ bool isAlive(const AIBinder* binder) override;
};
// OnBinderDiedContext is a type used as a cookie passed deathRecipient. The deathRecipient's
@@ -143,6 +151,13 @@
const AIBinder* clientId;
};
+ // BinderDiedUnlinkedEvent represents either an onBinderDied or an onBinderUnlinked event.
+ struct BinderDiedUnlinkedEvent {
+ // true for onBinderDied, false for onBinderUnlinked.
+ bool onBinderDied;
+ const AIBinder* clientId;
+ };
+
// The default timeout of get or set value requests is 30s.
// TODO(b/214605968): define TIMEOUT_IN_NANO in IVehicle and allow getValues/setValues/subscribe
// to specify custom timeouts.
@@ -171,14 +186,20 @@
GUARDED_BY(mLock);
// SubscriptionClients is thread-safe.
std::shared_ptr<SubscriptionClients> mSubscriptionClients;
- // mLinkToDeathImpl is only going to be changed in test.
- std::unique_ptr<ILinkToDeath> mLinkToDeathImpl;
+ // mBinderImpl is only going to be changed in test.
+ std::unique_ptr<IBinder> mBinderImpl;
// RecurrentTimer is thread-safe.
RecurrentTimer mRecurrentTimer;
ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+ // ConcurrentQueue is thread-safe.
+ ConcurrentQueue<BinderDiedUnlinkedEvent> mBinderEvents;
+
+ // A thread to handle onBinderDied or onBinderUnlinked event.
+ std::thread mOnBinderDiedUnlinkedHandlerThread;
+
android::base::Result<void> checkProperty(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
@@ -207,10 +228,17 @@
void onBinderUnlinkedWithContext(const AIBinder* clientId);
- void monitorBinderLifeCycle(const CallbackType& callback);
+ // Registers a onBinderDied callback for the client if not already registered.
+ // Returns true if the client Binder is alive, false otherwise.
+ bool monitorBinderLifeCycleLocked(const AIBinder* clientId) REQUIRES(mLock);
bool checkDumpPermission();
+ // The looping handler function to process all onBinderDied or onBinderUnlinked events in
+ // mBinderEvents.
+ void onBinderDiedUnlinkedHandler();
+
+ // Gets or creates a {@code T} object for the client to or from {@code clients}.
template <class T>
static std::shared_ptr<T> getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
@@ -239,7 +267,7 @@
void setTimeout(int64_t timeoutInNano);
// Test-only
- void setLinkToDeathImpl(std::unique_ptr<ILinkToDeath> impl);
+ void setBinderImpl(std::unique_ptr<IBinder> impl);
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
index 5c5f27e..4cfc2be 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -67,9 +67,10 @@
parcelableResults.payloads[0] = result;
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
!callbackStatus.isOk()) {
- ALOGE("failed to call callback, error: %s, exception: %d, service specific error: %d",
- callbackStatus.getMessage(), callbackStatus.getExceptionCode(),
- callbackStatus.getServiceSpecificError());
+ ALOGE("failed to call GetOrSetValueResult callback, client ID: %p, error: %s, "
+ "exception: %d, service specific error: %d",
+ callback->asBinder().get(), callbackStatus.getMessage(),
+ callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
}
}
@@ -91,9 +92,10 @@
if (status.isOk()) {
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
!callbackStatus.isOk()) {
- ALOGE("failed to call callback, error: %s, exception: %d, service specific error: %d",
- callbackStatus.getMessage(), callbackStatus.getExceptionCode(),
- callbackStatus.getServiceSpecificError());
+ ALOGE("failed to call GetOrSetValueResults callback, client ID: %p, error: %s, "
+ "exception: %d, service specific error: %d",
+ callback->asBinder().get(), callbackStatus.getMessage(),
+ callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
}
return;
}
@@ -299,10 +301,10 @@
if (ScopedAStatus callbackStatus =
callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount);
!callbackStatus.isOk()) {
- ALOGE("subscribe: failed to call callback, error: %s, exception: %d, "
- "service specific error: %d",
- callbackStatus.getMessage(), callbackStatus.getExceptionCode(),
- callbackStatus.getServiceSpecificError());
+ ALOGE("subscribe: failed to call UpdateValues callback, client ID: %p, error: %s, "
+ "exception: %d, service specific error: %d",
+ callback->asBinder().get(), callbackStatus.getMessage(),
+ callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
}
}
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index b50571b..886f897 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -80,12 +80,22 @@
} // namespace
-std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::getClient(
+std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::maybeAddClient(
const CallbackType& callback) {
std::scoped_lock<std::mutex> lockGuard(mLock);
return getOrCreateClient(&mClients, callback, mPendingRequestPool);
}
+std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::getClient(
+ const CallbackType& callback) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ const AIBinder* clientId = callback->asBinder().get();
+ if (mClients.find(clientId) == mClients.end()) {
+ return nullptr;
+ }
+ return mClients[clientId];
+}
+
int64_t DefaultVehicleHal::SubscribeIdByClient::getId(const CallbackType& callback) {
std::scoped_lock<std::mutex> lockGuard(mLock);
// This would be initialized to 0 if callback does not exist in the map.
@@ -148,7 +158,8 @@
checkHealth(hardwareCopy, subscriptionManagerCopy);
}));
- mLinkToDeathImpl = std::make_unique<AIBinderLinkToDeathImpl>();
+ mBinderImpl = std::make_unique<AIBinderImpl>();
+ mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
mDeathRecipient = ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
@@ -158,6 +169,10 @@
DefaultVehicleHal::~DefaultVehicleHal() {
// Delete the deathRecipient so that onBinderDied would not be called to reference 'this'.
mDeathRecipient = ScopedAIBinder_DeathRecipient();
+ mBinderEvents.deactivate();
+ if (mOnBinderDiedUnlinkedHandlerThread.joinable()) {
+ mOnBinderDiedUnlinkedHandlerThread.join();
+ }
}
void DefaultVehicleHal::onPropertyChangeEvent(
@@ -189,37 +204,41 @@
return (*clients)[clientId];
}
-void DefaultVehicleHal::monitorBinderLifeCycle(const CallbackType& callback) {
- AIBinder* clientId = callback->asBinder().get();
- {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
- // Already registered.
- return;
- }
- }
-
- std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
- OnBinderDiedContext{.vhal = this, .clientId = clientId});
- binder_status_t status = mLinkToDeathImpl->linkToDeath(clientId, mDeathRecipient.get(),
- static_cast<void*>(context.get()));
- if (status == STATUS_OK) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
+bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) {
+ OnBinderDiedContext* contextPtr = nullptr;
+ if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
+ return mBinderImpl->isAlive(clientId);
+ } else {
+ std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
+ OnBinderDiedContext{.vhal = this, .clientId = clientId});
+ // We know context must be alive when we use contextPtr because context would only
+ // be removed in OnBinderUnlinked, which must be called after OnBinderDied.
+ contextPtr = context.get();
// Insert into a map to keep the context object alive.
mOnBinderDiedContexts[clientId] = std::move(context);
- } else {
- ALOGE("failed to call linkToDeath on client binder, status: %d", static_cast<int>(status));
}
+
+ // If this function fails, onBinderUnlinked would be called to remove the added context.
+ binder_status_t status = mBinderImpl->linkToDeath(
+ const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
+ if (status == STATUS_OK) {
+ return true;
+ }
+ ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
+ static_cast<int>(status));
+ return false;
}
void DefaultVehicleHal::onBinderDied(void* cookie) {
OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
- context->vhal->onBinderDiedWithContext(context->clientId);
+ // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
+ // thread because we might be holding the mLock the handler requires.
+ context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{true, context->clientId});
}
void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) {
- ALOGD("binder died");
std::scoped_lock<std::mutex> lockGuard(mLock);
+ ALOGD("binder died, client ID: %p", clientId);
mSetValuesClients.erase(clientId);
mGetValuesClients.erase(clientId);
mSubscriptionClients->removeClient(clientId);
@@ -227,17 +246,31 @@
}
void DefaultVehicleHal::onBinderUnlinked(void* cookie) {
- // Delete the context associated with this cookie.
OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
- context->vhal->onBinderUnlinkedWithContext(context->clientId);
+ // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
+ // thread because we might be holding the mLock the handler requires.
+ context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{false, context->clientId});
}
void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) {
ALOGD("binder unlinked");
std::scoped_lock<std::mutex> lockGuard(mLock);
+ // Delete the context associated with this cookie.
mOnBinderDiedContexts.erase(clientId);
}
+void DefaultVehicleHal::onBinderDiedUnlinkedHandler() {
+ while (mBinderEvents.waitForItems()) {
+ for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) {
+ if (event.onBinderDied) {
+ onBinderDiedWithContext(event.clientId);
+ } else {
+ onBinderUnlinkedWithContext(event.clientId);
+ }
+ }
+ }
+}
+
template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
@@ -258,6 +291,10 @@
const VehiclePropValue& value) {
int64_t subscribeId = subscribeIdByClient->getId(callback);
auto client = subscriptionClients->getClient(callback);
+ if (client == nullptr) {
+ ALOGW("subscribe[%" PRId64 "]: the client has died", subscribeId);
+ return;
+ }
if (auto addRequestResult = client->addRequests({subscribeId}); !addRequestResult.ok()) {
ALOGE("subscribe[%" PRId64 "]: too many pending requests, ignore the getValue request",
subscribeId);
@@ -336,8 +373,6 @@
ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
const GetValueRequests& requests) {
- monitorBinderLifeCycle(callback);
-
expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
deserializedResults = fromStableLargeParcelable(requests);
if (!deserializedResults.ok()) {
@@ -379,9 +414,16 @@
std::shared_ptr<GetValuesClient> client;
{
- std::scoped_lock<std::mutex> lockGuard(mLock);
+ // Lock to make sure onBinderDied would not be called concurrently.
+ std::scoped_lock lockGuard(mLock);
+ if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
+ "client died");
+ }
+
client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
}
+
// Register the pending hardware requests and also check for duplicate request Ids.
if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
ALOGE("getValues[%s]: failed to add pending requests, error: %s",
@@ -414,8 +456,6 @@
ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
const SetValueRequests& requests) {
- monitorBinderLifeCycle(callback);
-
expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
deserializedResults = fromStableLargeParcelable(requests);
if (!deserializedResults.ok()) {
@@ -467,7 +507,12 @@
std::shared_ptr<SetValuesClient> client;
{
- std::scoped_lock<std::mutex> lockGuard(mLock);
+ // Lock to make sure onBinderDied would not be called concurrently.
+ std::scoped_lock lockGuard(mLock);
+ if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
+ "client died");
+ }
client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
}
@@ -602,8 +647,6 @@
ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
const std::vector<SubscribeOptions>& options,
[[maybe_unused]] int32_t maxSharedMemoryFileCount) {
- monitorBinderLifeCycle(callback);
-
// TODO(b/205189110): Use shared memory file count.
if (auto result = checkSubscribeOptions(options); !result.ok()) {
ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
@@ -635,14 +678,27 @@
onChangeSubscriptions.push_back(std::move(optionCopy));
}
}
- // Since we have already check the sample rates, the following functions must succeed.
- if (!onChangeSubscriptions.empty()) {
- mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
- /*isContinuousProperty=*/false);
- }
- if (!continuousSubscriptions.empty()) {
- mSubscriptionManager->subscribe(callback, continuousSubscriptions,
- /*isContinuousProperty=*/true);
+
+ {
+ // Lock to make sure onBinderDied would not be called concurrently.
+ std::scoped_lock lockGuard(mLock);
+ if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
+ "client died");
+ }
+
+ // Create a new SubscriptionClient if there isn't an existing one.
+ mSubscriptionClients->maybeAddClient(callback);
+
+ // Since we have already check the sample rates, the following functions must succeed.
+ if (!onChangeSubscriptions.empty()) {
+ mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
+ /*isContinuousProperty=*/false);
+ }
+ if (!continuousSubscriptions.empty()) {
+ mSubscriptionManager->subscribe(callback, continuousSubscriptions,
+ /*isContinuousProperty=*/true);
+ }
}
return ScopedAStatus::ok();
}
@@ -719,13 +775,18 @@
return;
}
-binder_status_t DefaultVehicleHal::AIBinderLinkToDeathImpl::linkToDeath(
- AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
+binder_status_t DefaultVehicleHal::AIBinderImpl::linkToDeath(AIBinder* binder,
+ AIBinder_DeathRecipient* recipient,
+ void* cookie) {
return AIBinder_linkToDeath(binder, recipient, cookie);
}
-void DefaultVehicleHal::setLinkToDeathImpl(std::unique_ptr<ILinkToDeath> impl) {
- mLinkToDeathImpl = std::move(impl);
+bool DefaultVehicleHal::AIBinderImpl::isAlive(const AIBinder* binder) {
+ return AIBinder_isAlive(binder);
+}
+
+void DefaultVehicleHal::setBinderImpl(std::unique_ptr<IBinder> impl) {
+ mBinderImpl = std::move(impl);
}
bool DefaultVehicleHal::checkDumpPermission() {
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index aafa17e..6f8eb1d 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -332,7 +332,9 @@
mCallbackClient = IVehicleCallback::fromBinder(mBinder);
// Set the linkToDeath to a fake implementation that always returns OK.
- setTestLinkToDeathImpl();
+ auto binderImpl = std::make_unique<TestBinderImpl>();
+ mBinderImpl = binderImpl.get();
+ mVhal->setBinderImpl(std::move(binderImpl));
}
void TearDown() override {
@@ -350,10 +352,6 @@
void setTimeout(int64_t timeoutInNano) { mVhal->setTimeout(timeoutInNano); }
- void setTestLinkToDeathImpl() {
- mVhal->setLinkToDeathImpl(std::make_unique<TestLinkToDeathImpl>());
- }
-
size_t countPendingRequests() { return mVhal->mPendingRequestPool->countPendingRequests(); }
size_t countClients() {
@@ -380,6 +378,8 @@
bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); }
+ void setBinderAlive(bool isAlive) { mBinderImpl->setAlive(isAlive); };
+
static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
std::vector<GetValueResult>& expectedResults,
std::vector<GetValueRequest>& expectedHardwareRequests) {
@@ -452,19 +452,31 @@
}
private:
+ class TestBinderImpl final : public DefaultVehicleHal::IBinder {
+ public:
+ binder_status_t linkToDeath(AIBinder*, AIBinder_DeathRecipient*, void*) override {
+ if (mIsAlive) {
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED_TRANSACTION;
+ }
+ }
+
+ bool isAlive(const AIBinder*) override { return mIsAlive; }
+
+ void setAlive(bool isAlive) { mIsAlive = isAlive; }
+
+ private:
+ bool mIsAlive = true;
+ };
+
std::shared_ptr<DefaultVehicleHal> mVhal;
std::shared_ptr<IVehicle> mVhalClient;
MockVehicleHardware* mHardwarePtr;
std::shared_ptr<MockVehicleCallback> mCallback;
std::shared_ptr<IVehicleCallback> mCallbackClient;
SpAIBinder mBinder;
-
- class TestLinkToDeathImpl final : public DefaultVehicleHal::ILinkToDeath {
- public:
- binder_status_t linkToDeath(AIBinder*, AIBinder_DeathRecipient*, void*) override {
- return STATUS_OK;
- }
- };
+ TestBinderImpl* mBinderImpl;
};
TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
@@ -587,7 +599,6 @@
ASSERT_TRUE(getValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok())
<< "requests to hardware mismatch";
- ;
getHardware()->addGetValueResponses(expectedResults);
@@ -806,6 +817,51 @@
ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail";
}
+TEST_F(DefaultVehicleHalTest, testGetValuesNewClientDied) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addGetValueResponses(expectedResults);
+
+ setBinderAlive(false);
+
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_FALSE(status.isOk()) << "getValues must fail if client died";
+ ASSERT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
+ EXPECT_EQ(countClients(), static_cast<size_t>(0))
+ << "No client should be created if the client binder died";
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesExistingClientDied) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addGetValueResponses(expectedResults);
+
+ // Try a normal getValue request to cache a GetValueClient first.
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+
+ // The client binder died before onBinderUnlinked clean up the GetValueClient.
+ setBinderAlive(false);
+
+ status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_FALSE(status.isOk()) << "getValues must fail if client died";
+ ASSERT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
+ // The client count should still be 1 but onBinderUnlinked will remove this later.
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+}
+
TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
SetValueRequests requests;
std::vector<SetValueResult> expectedResults;
@@ -1111,7 +1167,8 @@
<< "results mismatch, expect on change event for the updated value";
ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
<< "more results than expected";
- EXPECT_EQ(countClients(), static_cast<size_t>(1));
+ EXPECT_EQ(countClients(), static_cast<size_t>(2))
+ << "expect 2 clients, 1 subscribe client and 1 setvalue client";
}
TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnchangeUnrelatedEventIgnored) {
@@ -1581,12 +1638,28 @@
onBinderDied(context);
+ // Sleep for 100ms between checks.
+ int64_t sleep = 100;
+ // Timeout: 10s.
+ int64_t timeout = 10'000'000'000;
+ int64_t stopTime = elapsedRealtimeNano() + timeout;
+ // Wait until the onBinderDied event is handled.
+ while (countClients() != 0u && elapsedRealtimeNano() <= stopTime) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
+ }
+
ASSERT_EQ(countClients(), static_cast<size_t>(0))
<< "expect all clients to be removed when binder died";
ASSERT_TRUE(hasNoSubscriptions()) << "expect no subscriptions when binder died";
onBinderUnlinked(context);
+ stopTime = elapsedRealtimeNano() + timeout;
+ // Wait until the onBinderUnlinked event is handled.
+ while (countOnBinderDiedContexts() != 0u && elapsedRealtimeNano() <= stopTime) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
+ }
+
ASSERT_EQ(countOnBinderDiedContexts(), static_cast<size_t>(0))
<< "expect OnBinderDied context to be deleted when binder is unlinked";
}
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index d1fa94e..463f5d1 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -163,7 +163,7 @@
std::map<std::string, std::vector<SystemCameraKind>> hiddenPhysicalIdToLogicalMap;
for (const auto& name : cameraDeviceNames) {
std::shared_ptr<ICameraDevice> device;
- ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+ ALOGI("systemCameraTest: Testing camera device %s", name.c_str());
ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
ASSERT_TRUE(ret.isOk());
ASSERT_NE(device, nullptr);
@@ -196,13 +196,14 @@
break;
}
}
+
// For hidden physical cameras, collect their associated logical cameras
// and store the system camera kind.
if (!isPublicId) {
auto it = hiddenPhysicalIdToLogicalMap.find(physicalId);
if (it == hiddenPhysicalIdToLogicalMap.end()) {
hiddenPhysicalIdToLogicalMap.insert(std::make_pair(
- physicalId, std::vector<SystemCameraKind>(systemCameraKind)));
+ physicalId, std::vector<SystemCameraKind>({systemCameraKind})));
} else {
it->second.push_back(systemCameraKind);
}
@@ -1450,6 +1451,7 @@
for (const auto& name : cameraDeviceNames) {
std::string version, deviceId;
+ ALOGI("processMultiCaptureRequestPreview: Test device %s", name.c_str());
ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
CameraMetadata metadata;
@@ -1466,6 +1468,7 @@
ASSERT_TRUE(ret.isOk());
continue;
}
+ ASSERT_EQ(Status::OK, rc);
std::unordered_set<std::string> physicalIds;
rc = getPhysicalCameraIds(staticMeta, &physicalIds);
@@ -1521,10 +1524,14 @@
Stream previewStream;
std::shared_ptr<DeviceCb> cb;
- configurePreviewStreams(name, mProvider, &previewThreshold, physicalIds, &mSession,
- &previewStream, &halStreams /*out*/,
- &supportsPartialResults /*out*/, &partialResultCount /*out*/,
- &useHalBufManager /*out*/, &cb /*out*/, 0 /*streamConfigCounter*/);
+ configurePreviewStreams(
+ name, mProvider, &previewThreshold, physicalIds, &mSession, &previewStream,
+ &halStreams /*out*/, &supportsPartialResults /*out*/, &partialResultCount /*out*/,
+ &useHalBufManager /*out*/, &cb /*out*/, 0 /*streamConfigCounter*/, true);
+ if (mSession == nullptr) {
+ // stream combination not supported by HAL, skip test for device
+ continue;
+ }
::aidl::android::hardware::common::fmq::MQDescriptor<
int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 858dfd5..ee0c691 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -1564,6 +1564,7 @@
ASSERT_NE(*session, nullptr);
ret = (*device)->getCameraCharacteristics(staticMeta);
+ ASSERT_TRUE(ret.isOk());
}
void CameraAidlTest::openEmptyInjectionSession(const std::string& name,
@@ -2474,7 +2475,7 @@
std::shared_ptr<ICameraDeviceSession>* session, Stream* previewStream,
std::vector<HalStream>* halStreams, bool* supportsPartialResults,
int32_t* partialResultCount, bool* useHalBufManager, std::shared_ptr<DeviceCb>* cb,
- int32_t streamConfigCounter) {
+ int32_t streamConfigCounter, bool allowUnsupport) {
ASSERT_NE(nullptr, session);
ASSERT_NE(nullptr, halStreams);
ASSERT_NE(nullptr, previewStream);
@@ -2561,6 +2562,14 @@
bool supported = false;
ret = device->isStreamCombinationSupported(config, &supported);
ASSERT_TRUE(ret.isOk());
+ if (allowUnsupport && !supported) {
+ // stream combination not supported. return null session
+ ret = (*session)->close();
+ ASSERT_TRUE(ret.isOk());
+ *session = nullptr;
+ return;
+ }
+ ASSERT_TRUE(supported) << "Stream combination must be supported.";
config.streamConfigCounter = streamConfigCounter;
std::vector<HalStream> halConfigs;
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index 1ca457b..ac4b2c9 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -190,7 +190,8 @@
std::shared_ptr<ICameraDeviceSession>* session /*out*/, Stream* previewStream /*out*/,
std::vector<HalStream>* halStreams /*out*/, bool* supportsPartialResults /*out*/,
int32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
- std::shared_ptr<DeviceCb>* cb /*out*/, int32_t streamConfigCounter = 0);
+ std::shared_ptr<DeviceCb>* cb /*out*/, int32_t streamConfigCounter = 0,
+ bool allowUnsupport = false);
void configurePreviewStream(
const std::string& name, const std::shared_ptr<ICameraProvider>& provider,
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
new file mode 100644
index 0000000..2f534df
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="byte") @VintfStability
+enum UwbVendorStatusCodes {
+ STATUS_ERROR_CCC_SE_BUSY = 80,
+ STATUS_ERROR_CCC_LIFECYCLE = 81,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
new file mode 100644
index 0000000..8505b8a
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorStatusCodes.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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 android.hardware.uwb.fira_android;
+
+/**
+ * Android specific vendor status codes should be defined here.
+ *
+ */
+@VintfStability
+@Backing(type="byte")
+enum UwbVendorStatusCodes {
+ /**
+ * Use values from the vendor specific status code range: 0x50 – 0xFF defined in Table 32 of
+ * UCI specification.
+ */
+
+ /** CCC specific */
+ /** Secure element is busy */
+ STATUS_ERROR_CCC_SE_BUSY = 0x50,
+ /** CCC Lifecycle error */
+ STATUS_ERROR_CCC_LIFECYCLE = 0x51,
+}