diff --git a/audio/common/all-versions/default/service/android.hardware.audio.service.rc b/audio/common/all-versions/default/service/android.hardware.audio.service.rc index 0de4eea373..a1df67a286 100644 --- a/audio/common/all-versions/default/service/android.hardware.audio.service.rc +++ b/audio/common/all-versions/default/service/android.hardware.audio.service.rc @@ -2,7 +2,7 @@ service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service class hal user audioserver # media gid needed for /dev/fm (radio) and for /data/misc/media (tee) - group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub + group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub system capabilities BLOCK_SUSPEND SYS_NICE # setting RLIMIT_RTPRIO allows binder RT priority inheritance rlimit rtprio 10 10 diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h index d2b701d9a5..2378676387 100644 --- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h +++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h @@ -57,7 +57,7 @@ class LinearFakeValueGenerator : public FakeValueGenerator { float dispersion; // Defines minimum and maximum value based on initial value. float increment; // Value that we will be added to currentValue with each timer tick. int64_t interval; - long lastEventTimestamp; + int64_t lastEventTimestamp; }; GeneratorCfg mGenCfg; diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp index 91331443bb..fe08dcf335 100644 --- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp +++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp @@ -86,7 +86,7 @@ std::optional LinearFakeValueGenerator::nextEvent() { if (mGenCfg.lastEventTimestamp == 0) { mGenCfg.lastEventTimestamp = elapsedRealtimeNano(); } else { - long nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval; + int64_t nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval; // Prevent overflow. assert(nextEventTime > mGenCfg.lastEventTimestamp); mGenCfg.lastEventTimestamp = nextEventTime; diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h index c3ebd3b3bc..af1bb1d16d 100644 --- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h +++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h @@ -99,12 +99,17 @@ class FakeVehicleHardware : public IVehicleHardware { const std::shared_ptr mValuePool; const std::shared_ptr mServerSidePropStore; + const std::string mDefaultConfigDir; + const std::string mOverrideConfigDir; + ValueResultType getValue( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; VhalResult setValue( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + bool UseOverrideConfigDir(); + private: // Expose private methods to unit test. friend class FakeVehicleHardwareTestHelper; @@ -156,8 +161,6 @@ class FakeVehicleHardware : public IVehicleHardware { aidl::android::hardware::automotive::vehicle::SetValueRequest> mPendingSetValueRequests; - const std::string mDefaultConfigDir; - const std::string mOverrideConfigDir; const bool mForceOverride; bool mAddExtraTestVendorConfigs; diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp index 3f5e4c4273..250a226bd5 100644 --- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp +++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -205,9 +204,10 @@ void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) // Create a separate instance for each individual zone VehiclePropValue prop = { + .timestamp = elapsedRealtimeNano(), .areaId = curArea, .prop = propId, - .timestamp = elapsedRealtimeNano(), + .value = {}, }; if (config.initialAreaValues.empty()) { @@ -240,6 +240,8 @@ FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir, bool forceOverride) : mValuePool(std::make_unique()), mServerSidePropStore(new VehiclePropertyStore(mValuePool)), + mDefaultConfigDir(defaultConfigDir), + mOverrideConfigDir(overrideConfigDir), mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)), mFakeUserHal(new FakeUserHal(mValuePool)), mRecurrentTimer(new RecurrentTimer()), @@ -247,8 +249,6 @@ FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir, [this](const VehiclePropValue& value) { eventFromVehicleBus(value); })), mPendingGetValueRequests(this), mPendingSetValueRequests(this), - mDefaultConfigDir(defaultConfigDir), - mOverrideConfigDir(overrideConfigDir), mForceOverride(forceOverride) { init(); } @@ -259,11 +259,15 @@ FakeVehicleHardware::~FakeVehicleHardware() { mGeneratorHub.reset(); } +bool FakeVehicleHardware::UseOverrideConfigDir() { + return mForceOverride || + android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false); +} + std::unordered_map FakeVehicleHardware::loadConfigDeclarations() { std::unordered_map configsByPropId; loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId); - if (mForceOverride || - android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false)) { + if (UseOverrideConfigDir()) { loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId); } return configsByPropId; @@ -938,7 +942,7 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::getValue( << StringPrintf("failed to get special value: %d, error: %s", value.prop, getErrorMsg(result).c_str()); } else { - return std::move(result); + return result; } } @@ -953,7 +957,7 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::getValue( } } - return std::move(readResult); + return readResult; } DumpResult FakeVehicleHardware::dump(const std::vector& options) { @@ -990,9 +994,11 @@ DumpResult FakeVehicleHardware::dump(const std::vector& options) { } else if (EqualsIgnoreCase(option, "--genTestVendorConfigs")) { mAddExtraTestVendorConfigs = true; result.refreshPropertyConfigs = true; + result.buffer = "successfully generated vendor configs"; } else if (EqualsIgnoreCase(option, "--restoreVendorConfigs")) { mAddExtraTestVendorConfigs = false; result.refreshPropertyConfigs = true; + result.buffer = "successfully restored vendor configs"; } else { result.buffer = StringPrintf("Invalid option: %s\n", option.c_str()); } @@ -1328,9 +1334,9 @@ std::string FakeVehicleHardware::genFakeDataCommand(const std::vector FakeVehicleHardware::getOptionValues( while (*index < options.size()) { std::string option = options[*index]; if (SET_PROP_OPTIONS.find(option) != SET_PROP_OPTIONS.end()) { - return std::move(values); + return values; } values.push_back(option); (*index)++; } - return std::move(values); + return values; } Result FakeVehicleHardware::parsePropOptions( @@ -1808,6 +1815,7 @@ void FakeVehicleHardware::registerOnPropertyChangeEvent( void FakeVehicleHardware::registerOnPropertySetErrorEvent( std::unique_ptr callback) { + // In FakeVehicleHardware, we will never use mOnPropertySetErrorCallback. if (mOnPropertySetErrorCallback != nullptr) { ALOGE("registerOnPropertySetErrorEvent must only be called once"); return; @@ -1836,8 +1844,9 @@ StatusCode FakeVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId, // Refresh the property value. In real implementation, this should poll the latest value // from vehicle bus. Here, we are just refreshing the existing value with a new timestamp. auto result = getValue(VehiclePropValue{ - .prop = propId, .areaId = areaId, + .prop = propId, + .value = {}, }); if (!result.ok()) { // Failed to read current value, skip refreshing. diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h index e740da7e5c..ddd620ea2e 100644 --- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h +++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h @@ -82,6 +82,10 @@ class GRPCVehicleHardware : public IVehicleHardware { bool waitForConnected(std::chrono::milliseconds waitTime); + protected: + std::shared_mutex mCallbackMutex; + std::unique_ptr mOnPropChange; + private: void ValuePollingLoop(); @@ -90,8 +94,6 @@ class GRPCVehicleHardware : public IVehicleHardware { std::unique_ptr mGrpcStub; std::thread mValuePollingThread; - std::shared_mutex mCallbackMutex; - std::unique_ptr mOnPropChange; std::unique_ptr mOnSetErr; std::mutex mShutdownMutex; diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h index 2e7298ff0b..b3f4a0f722 100644 --- a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h +++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h @@ -107,12 +107,18 @@ class SubscriptionClient final : public ConnectedClient { // Gets the callback to be called when the request for this client has finished. std::shared_ptr getResultCallback(); - // Marshals the updated values into largeParcelable and sents it through {@code onPropertyEvent} + // Marshals the updated values into largeParcelable and sends it through {@code onPropertyEvent} // callback. static void sendUpdatedValues( CallbackType callback, std::vector&& updatedValues); + // Marshals the set property error events into largeParcelable and sends it through + // {@code onPropertySetError} callback. + static void sendPropertySetErrors( + CallbackType callback, + std::vector&& + vehiclePropErrors); protected: // Gets the callback to be called when the request for this client has timeout. diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h index 2c2cf1a5bd..74ad7eaf3e 100644 --- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h +++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h @@ -249,10 +249,14 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi const CallbackType& callback, std::shared_ptr pendingRequestPool); static void onPropertyChangeEvent( - std::weak_ptr subscriptionManager, + const std::weak_ptr& subscriptionManager, const std::vector& updatedValues); + static void onPropertySetErrorEvent( + const std::weak_ptr& subscriptionManager, + const std::vector& errorEvents); + static void checkHealth(IVehicleHardware* hardware, std::weak_ptr subscriptionManager); diff --git a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h index 14799d9f84..301d56c270 100644 --- a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h +++ b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h @@ -99,6 +99,12 @@ class SubscriptionManager final { const std::vector& updatedValues); + // For a list of set property error events, returns a map that maps clients subscribing to the + // properties to a list of errors for each client. + std::unordered_map> + getSubscribedClientsForErrorEvents(const std::vector& errorEvents); + // Checks whether the sample rate is valid. static bool checkSampleRateHz(float sampleRateHz); diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp index 81d231c87f..fb23a25047 100644 --- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp +++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp @@ -38,6 +38,8 @@ using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; using ::aidl::android::hardware::automotive::vehicle::SetValueResult; using ::aidl::android::hardware::automotive::vehicle::SetValueResults; using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropError; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; using ::android::base::Result; @@ -300,7 +302,34 @@ void SubscriptionClient::sendUpdatedValues(std::shared_ptr cal if (ScopedAStatus callbackStatus = callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount); !callbackStatus.isOk()) { - ALOGE("subscribe: failed to call UpdateValues callback, client ID: %p, error: %s, " + ALOGE("subscribe: failed to call onPropertyEvent callback, client ID: %p, error: %s, " + "exception: %d, service specific error: %d", + callback->asBinder().get(), callbackStatus.getMessage(), + callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError()); + } +} + +void SubscriptionClient::sendPropertySetErrors(std::shared_ptr callback, + std::vector&& vehiclePropErrors) { + if (vehiclePropErrors.empty()) { + return; + } + + VehiclePropErrors vehiclePropErrorsLargeParcelable; + ScopedAStatus status = vectorToStableLargeParcelable(std::move(vehiclePropErrors), + &vehiclePropErrorsLargeParcelable); + if (!status.isOk()) { + int statusCode = status.getServiceSpecificError(); + ALOGE("subscribe: failed to marshal result into large parcelable, error: " + "%s, code: %d", + status.getMessage(), statusCode); + return; + } + + if (ScopedAStatus callbackStatus = + callback->onPropertySetError(vehiclePropErrorsLargeParcelable); + !callbackStatus.isOk()) { + ALOGE("subscribe: failed to call onPropertySetError 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 98cfc398af..0d5c070c54 100644 --- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp +++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp @@ -144,6 +144,11 @@ DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr vehicleHa [subscriptionManagerCopy](std::vector updatedValues) { onPropertyChangeEvent(subscriptionManagerCopy, updatedValues); })); + mVehicleHardware->registerOnPropertySetErrorEvent( + std::make_unique( + [subscriptionManagerCopy](std::vector errorEvents) { + onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents); + })); // Register heartbeat event. mRecurrentAction = std::make_shared>( @@ -177,7 +182,7 @@ DefaultVehicleHal::~DefaultVehicleHal() { } void DefaultVehicleHal::onPropertyChangeEvent( - std::weak_ptr subscriptionManager, + const std::weak_ptr& subscriptionManager, const std::vector& updatedValues) { auto manager = subscriptionManager.lock(); if (manager == nullptr) { @@ -194,6 +199,20 @@ void DefaultVehicleHal::onPropertyChangeEvent( } } +void DefaultVehicleHal::onPropertySetErrorEvent( + const std::weak_ptr& subscriptionManager, + const std::vector& errorEvents) { + auto manager = subscriptionManager.lock(); + if (manager == nullptr) { + ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending"); + return; + } + auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents); + for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) { + SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors)); + } +} + template std::shared_ptr DefaultVehicleHal::getOrCreateClient( std::unordered_map>* clients, @@ -692,15 +711,19 @@ ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback, // 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()) { - return toScopedAStatus(mSubscriptionManager->subscribe(callback, onChangeSubscriptions, - /*isContinuousProperty=*/false)); + auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions, + /*isContinuousProperty=*/false); + if (!result.ok()) { + return toScopedAStatus(result); + } } if (!continuousSubscriptions.empty()) { - return toScopedAStatus(mSubscriptionManager->subscribe(callback, - continuousSubscriptions, - /*isContinuousProperty=*/true)); + auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions, + /*isContinuousProperty=*/true); + if (!result.ok()) { + return toScopedAStatus(result); + } } } return ScopedAStatus::ok(); diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp index bba730f6f4..1f2690e340 100644 --- a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp +++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp @@ -36,6 +36,7 @@ constexpr float ONE_SECOND_IN_NANO = 1'000'000'000.; using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; using ::aidl::android::hardware::automotive::vehicle::StatusCode; using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropError; using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; using ::android::base::Error; using ::android::base::Result; @@ -269,6 +270,32 @@ SubscriptionManager::getSubscribedClients(const std::vector& u return clients; } +std::unordered_map, std::vector> +SubscriptionManager::getSubscribedClientsForErrorEvents( + const std::vector& errorEvents) { + std::scoped_lock lockGuard(mLock); + std::unordered_map, std::vector> clients; + + for (const auto& errorEvent : errorEvents) { + PropIdAreaId propIdAreaId{ + .propId = errorEvent.propId, + .areaId = errorEvent.areaId, + }; + if (mClientsByPropIdArea.find(propIdAreaId) == mClientsByPropIdArea.end()) { + continue; + } + + for (const auto& [_, client] : mClientsByPropIdArea[propIdAreaId]) { + clients[client].push_back({ + .propId = errorEvent.propId, + .areaId = errorEvent.areaId, + .errorCode = errorEvent.errorCode, + }); + } + } + return clients; +} + bool SubscriptionManager::isEmpty() { std::scoped_lock lockGuard(mLock); return mSubscribedPropsByClient.empty() && mClientsByPropIdArea.empty(); diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp index 05e569ab8a..96b71f0af0 100644 --- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp +++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp @@ -62,6 +62,7 @@ using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow; using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropError; using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; @@ -1653,6 +1654,63 @@ TEST_F(DefaultVehicleHalTest, testDumpCallerShouldNotDump) { ASSERT_EQ(msg.find("Vehicle HAL State: "), std::string::npos); } +TEST_F(DefaultVehicleHalTest, testOnPropertySetErrorEvent) { + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaIds = {0}, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP, + .areaIds = {0}, + .sampleRate = 1, + }, + }; + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + std::vector errorEvents = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::INTERNAL_ERROR, + }, + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::ACCESS_DENIED, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP, + .areaId = 0, + .errorCode = StatusCode::INVALID_ARG, + }, + }; + std::vector expectedResults = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::INTERNAL_ERROR, + }, + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::ACCESS_DENIED, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP, + .areaId = 0, + .errorCode = StatusCode::INVALID_ARG, + }, + }; + getHardware()->sendOnPropertySetErrorEvent(errorEvents); + + ASSERT_EQ(getCallback()->countOnPropertySetErrorResults(), 1u); + auto maybeVehiclePropErrors = getCallback()->nextOnPropertySetErrorResults(); + ASSERT_TRUE(maybeVehiclePropErrors.has_value()); + const auto& vehiclePropErrors = maybeVehiclePropErrors.value(); + ASSERT_THAT(vehiclePropErrors.payloads, UnorderedElementsAreArray(expectedResults)); +} + } // 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 f51ce5cb39..54fede1f3d 100644 --- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp +++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp @@ -81,8 +81,14 @@ ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues& resu return result; } -ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) { - return ScopedAStatus::ok(); +ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors& results) { + ScopedAStatus result; + { + std::scoped_lock lockGuard(mLock); + result = storeResults(results, &mOnPropertySetErrorResults); + } + mCond.notify_all(); + return result; } std::optional MockVehicleCallback::nextGetValueResults() { @@ -105,6 +111,16 @@ size_t MockVehicleCallback::countOnPropertyEventResults() { return mOnPropertyEventResults.size(); } +std::optional MockVehicleCallback::nextOnPropertySetErrorResults() { + std::scoped_lock lockGuard(mLock); + return pop(mOnPropertySetErrorResults); +} + +size_t MockVehicleCallback::countOnPropertySetErrorResults() { + std::scoped_lock lockGuard(mLock); + return mOnPropertySetErrorResults.size(); +} + bool MockVehicleCallback::waitForSetValueResults(size_t size, size_t timeoutInNano) { std::unique_lock lk(mLock); return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] { diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h index f17b273b18..1545eae08f 100644 --- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h +++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h @@ -63,6 +63,9 @@ class MockVehicleCallback final nextSetValueResults(); std::optional nextOnPropertyEventResults(); + size_t countOnPropertySetErrorResults(); + std::optional + nextOnPropertySetErrorResults(); size_t countOnPropertyEventResults(); bool waitForSetValueResults(size_t size, size_t timeoutInNano); bool waitForGetValueResults(size_t size, size_t timeoutInNano); @@ -77,6 +80,8 @@ class MockVehicleCallback final std::list mOnPropertyEventResults GUARDED_BY(mLock); int32_t mSharedMemoryFileCount GUARDED_BY(mLock); + std::list + mOnPropertySetErrorResults GUARDED_BY(mLock); }; } // namespace vehicle diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp index 4df4e1aea5..ba0d33dfde 100644 --- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp +++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp @@ -131,8 +131,9 @@ void MockVehicleHardware::registerOnPropertyChangeEvent( } void MockVehicleHardware::registerOnPropertySetErrorEvent( - std::unique_ptr) { - // TODO(b/200737967): mock this. + std::unique_ptr callback) { + std::scoped_lock lockGuard(mLock); + mPropertySetErrorCallback = std::move(callback); } void MockVehicleHardware::setPropertyConfigs(const std::vector& configs) { @@ -254,6 +255,12 @@ template StatusCode MockVehicleHardware::handleRequestsLocked>* storedRequests, std::list>* storedResponses) const; +void MockVehicleHardware::sendOnPropertySetErrorEvent( + const std::vector& errorEvents) { + std::scoped_lock lockGuard(mLock); + (*mPropertySetErrorCallback)(errorEvents); +} + } // namespace vehicle } // namespace automotive } // namespace hardware diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h index 743841c216..46b30b9405 100644 --- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h +++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h @@ -85,6 +85,7 @@ class MockVehicleHardware final : public IVehicleHardware { aidl::android::hardware::automotive::vehicle::StatusCode status); void setSleepTime(int64_t timeInNano); void setDumpResult(DumpResult result); + void sendOnPropertySetErrorEvent(const std::vector& errorEvents); private: mutable std::mutex mLock; @@ -104,6 +105,7 @@ class MockVehicleHardware final : public IVehicleHardware { mStatusByFunctions GUARDED_BY(mLock); int64_t mSleepTime GUARDED_BY(mLock) = 0; std::unique_ptr mPropertyChangeCallback GUARDED_BY(mLock); + std::unique_ptr mPropertySetErrorCallback GUARDED_BY(mLock); std::function, const std::vector&)> diff --git a/automotive/vehicle/proto/Android.bp b/automotive/vehicle/proto/Android.bp index 683f1281c4..e7dabcf891 100644 --- a/automotive/vehicle/proto/Android.bp +++ b/automotive/vehicle/proto/Android.bp @@ -27,6 +27,7 @@ cc_library_static { visibility: [ "//hardware/interfaces/automotive/vehicle:__subpackages__", "//device/generic/car/emulator:__subpackages__", + "//system/software_defined_vehicle/core_services:__subpackages__", ], vendor: true, host_supported: true, diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp index 90ec8f26ee..54076c88e3 100644 --- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp +++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp @@ -31,6 +31,9 @@ using ::android::base::ParseInt; namespace aidl::android::hardware::biometrics::fingerprint { +FakeFingerprintEngine::FakeFingerprintEngine() + : mRandom(std::mt19937::default_seed), mWorkMode(WorkMode::kIdle) {} + void FakeFingerprintEngine::generateChallengeImpl(ISessionCallback* cb) { BEGIN_OP(0); std::uniform_int_distribution dist; @@ -48,7 +51,7 @@ void FakeFingerprintEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t ch void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat, const std::future& cancel) { - BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency())); + BEGIN_OP(0); // Do proper HAT verification in the real implementation. if (hat.mac.empty()) { @@ -57,13 +60,77 @@ void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb, return; } + updateContext(WorkMode::kEnroll, cb, const_cast&>(cancel), 0, hat); +} + +void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t operationId, + const std::future& cancel) { + BEGIN_OP(0); + updateContext(WorkMode::kAuthenticate, cb, const_cast&>(cancel), operationId, + keymaster::HardwareAuthToken()); +} + +void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb, + const std::future& cancel) { + BEGIN_OP(0); + + auto detectInteractionSupported = + FingerprintHalProperties::detect_interaction().value_or(false); + if (!detectInteractionSupported) { + LOG(ERROR) << "Detect interaction is not supported"; + cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); + return; + } + + updateContext(WorkMode::kDetectInteract, cb, const_cast&>(cancel), 0, + keymaster::HardwareAuthToken()); +} + +void FakeFingerprintEngine::updateContext(WorkMode mode, ISessionCallback* cb, + std::future& cancel, int64_t operationId, + const keymaster::HardwareAuthToken& hat) { + mCancel = std::move(cancel); + mWorkMode = mode; + mCb = cb; + mOperationId = operationId; + mHat = hat; +} + +void FakeFingerprintEngine::fingerDownAction() { + bool isTerminal = false; + LOG(INFO) << __func__; + switch (mWorkMode) { + case WorkMode::kAuthenticate: + isTerminal = onAuthenticateFingerDown(mCb, mOperationId, mCancel); + break; + case WorkMode::kEnroll: + isTerminal = onEnrollFingerDown(mCb, mHat, mCancel); + break; + case WorkMode::kDetectInteract: + isTerminal = onDetectInteractFingerDown(mCb, mCancel); + break; + default: + LOG(WARNING) << "unexpected mode: on fingerDownAction(), " << (int)mWorkMode; + break; + } + + if (isTerminal) { + mWorkMode = WorkMode::kIdle; + } +} + +bool FakeFingerprintEngine::onEnrollFingerDown(ISessionCallback* cb, + const keymaster::HardwareAuthToken&, + const std::future& cancel) { + BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency())); + // Force error-out auto err = FingerprintHalProperties::operation_enroll_error().value_or(0); if (err != 0) { LOG(ERROR) << "Fail: operation_enroll_error"; auto ec = convertError(err); cb->onError(ec.first, ec.second); - return; + return true; } // Format is ":,...: @@ -72,7 +139,7 @@ void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb, if (parts.size() != 3) { LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll; cb->onError(Error::VENDOR, 0 /* vendorError */); - return; + return true; } auto enrollmentId = std::stoi(parts[0]); auto progress = parseEnrollmentCapture(parts[1]); @@ -88,7 +155,7 @@ void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb, if (shouldCancel(cancel)) { LOG(ERROR) << "Fail: cancel"; cb->onError(Error::CANCELED, 0 /* vendorCode */); - return; + return true; } auto ac = convertAcquiredInfo(acquired[j]); cb->onAcquired(ac.first, ac.second); @@ -114,10 +181,13 @@ void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb, cb->onEnrollmentProgress(enrollmentId, left); } } + + return true; } -void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* operationId */, - const std::future& cancel) { +bool FakeFingerprintEngine::onAuthenticateFingerDown(ISessionCallback* cb, + int64_t /* operationId */, + const std::future& cancel) { BEGIN_OP(getLatency(FingerprintHalProperties::operation_authenticate_latency())); int64_t now = Util::getSystemNanoTime(); @@ -129,19 +199,12 @@ void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* op if (N == 0) { LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired; cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); - return; + return true; } // got lockout? - FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode(); - if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) { - LOG(ERROR) << "Fail: lockout permanent"; - cb->onLockoutPermanent(); - return; - } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) { - int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft(); - LOG(ERROR) << "Fail: lockout timed " << timeLeft; - cb->onLockoutTimed(timeLeft); + if (checkSensorLockout(cb)) { + return FakeLockoutTracker::LockoutMode::kPermanent == mLockoutTracker.getMode(); } int i = 0; @@ -150,7 +213,7 @@ void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* op LOG(ERROR) << "Fail: operation_authenticate_fails"; mLockoutTracker.addFailedAttempt(); cb->onAuthenticationFailed(); - return; + return false; } auto err = FingerprintHalProperties::operation_authenticate_error().value_or(0); @@ -158,20 +221,21 @@ void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* op LOG(ERROR) << "Fail: operation_authenticate_error"; auto ec = convertError(err); cb->onError(ec.first, ec.second); - return; + return true; /* simply terminating current operation for any user inserted error, + revisit if tests need*/ } if (FingerprintHalProperties::lockout().value_or(false)) { LOG(ERROR) << "Fail: lockout"; cb->onLockoutPermanent(); cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */); - return; + return true; } if (shouldCancel(cancel)) { LOG(ERROR) << "Fail: cancel"; cb->onError(Error::CANCELED, 0 /* vendorCode */); - return; + return true; } if (i < N) { @@ -189,29 +253,23 @@ void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* op if (id > 0 && isEnrolled) { cb->onAuthenticationSucceeded(id, {} /* hat */); mLockoutTracker.reset(); - return; + return true; } else { LOG(ERROR) << "Fail: fingerprint not enrolled"; cb->onAuthenticationFailed(); mLockoutTracker.addFailedAttempt(); + checkSensorLockout(cb); + return false; } } -void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb, - const std::future& cancel) { +bool FakeFingerprintEngine::onDetectInteractFingerDown(ISessionCallback* cb, + const std::future& cancel) { BEGIN_OP(getLatency(FingerprintHalProperties::operation_detect_interaction_latency())); int64_t duration = FingerprintHalProperties::operation_detect_interaction_duration().value_or(10); - auto detectInteractionSupported = - FingerprintHalProperties::detect_interaction().value_or(false); - if (!detectInteractionSupported) { - LOG(ERROR) << "Detect interaction is not supported"; - cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); - return; - } - auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1"); auto acquiredInfos = parseIntSequence(acquired); int N = acquiredInfos.size(); @@ -220,7 +278,7 @@ void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb, if (N == 0) { LOG(ERROR) << "Fail to parse detect interaction acquired info: " + acquired; cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); - return; + return true; } int i = 0; @@ -230,13 +288,13 @@ void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb, LOG(ERROR) << "Fail: operation_detect_interaction_error"; auto ec = convertError(err); cb->onError(ec.first, ec.second); - return; + return true; } if (shouldCancel(cancel)) { LOG(ERROR) << "Fail: cancel"; cb->onError(Error::CANCELED, 0 /* vendorCode */); - return; + return true; } if (i < N) { @@ -253,21 +311,18 @@ void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb, if (id <= 0 || !isEnrolled) { LOG(ERROR) << "Fail: not enrolled"; cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); - return; + return true; } cb->onInteractionDetected(); + + return true; } void FakeFingerprintEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) { BEGIN_OP(0); std::vector ids; - // There are some enrollment sync issue with framework, which results in - // a single template removal during the very firt sync command after reboot. - // This is a workaround for now. TODO(b/243129174) - ids.push_back(-1); - for (auto& enrollment : FingerprintHalProperties::enrollments()) { auto id = enrollment.value_or(0); if (id > 0) { @@ -330,6 +385,11 @@ void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb, cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); return; } + clearLockout(cb); + isLockoutTimerAborted = true; +} + +void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) { FingerprintHalProperties::lockout(false); cb->onLockoutCleared(); mLockoutTracker.reset(); @@ -339,6 +399,7 @@ ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId* int32_t /*y*/, float /*minor*/, float /*major*/) { BEGIN_OP(0); + fingerDownAction(); return ndk::ScopedAStatus::ok(); } @@ -369,7 +430,8 @@ bool FakeFingerprintEngine::getSensorLocationConfig(SensorLocation& out) { if (dim.size() >= 4) { d = dim[3]; } - if (isValidStr) out = {0, x, y, r, d}; + if (isValidStr) + out = {.sensorLocationX = x, .sensorLocationY = y, .sensorRadius = r, .display = d}; return isValidStr; } @@ -385,8 +447,7 @@ SensorLocation FakeFingerprintEngine::getSensorLocation() { } SensorLocation FakeFingerprintEngine::defaultSensorLocation() { - return {0 /* displayId (not used) */, 0 /* sensorLocationX */, 0 /* sensorLocationY */, - 0 /* sensorRadius */, "" /* display */}; + return SensorLocation(); } std::vector FakeFingerprintEngine::parseIntSequence(const std::string& str, @@ -513,4 +574,39 @@ int32_t FakeFingerprintEngine::getRandomInRange(int32_t bound1, int32_t bound2) return dist(mRandom); } +bool FakeFingerprintEngine::checkSensorLockout(ISessionCallback* cb) { + FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode(); + if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) { + LOG(ERROR) << "Fail: lockout permanent"; + cb->onLockoutPermanent(); + isLockoutTimerAborted = true; + return true; + } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) { + int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft(); + LOG(ERROR) << "Fail: lockout timed " << timeLeft; + cb->onLockoutTimed(timeLeft); + if (isLockoutTimerSupported && !isLockoutTimerStarted) startLockoutTimer(timeLeft, cb); + return true; + } + return false; +} + +void FakeFingerprintEngine::startLockoutTimer(int64_t timeout, ISessionCallback* cb) { + BEGIN_OP(0); + std::function action = + std::bind(&FakeFingerprintEngine::lockoutTimerExpired, this, std::placeholders::_1); + std::thread([timeout, action, cb]() { + std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); + action(cb); + }).detach(); + + isLockoutTimerStarted = true; +} +void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) { + if (!isLockoutTimerAborted) { + clearLockout(cb); + } + isLockoutTimerStarted = false; + isLockoutTimerAborted = false; +} } // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp index 9f736e7abf..a78cdcdbce 100644 --- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp +++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp @@ -27,11 +27,13 @@ using namespace ::android::fingerprint::virt; namespace aidl::android::hardware::biometrics::fingerprint { -SensorLocation FakeFingerprintEngineSide::defaultSensorLocation() { - SensorLocation location; +FakeFingerprintEngineSide::FakeFingerprintEngineSide() : FakeFingerprintEngine() { + isLockoutTimerSupported = true; +} - return {0 /* displayId (not used) */, defaultSensorLocationX /* sensorLocationX */, - defaultSensorLocationY /* sensorLocationY */, defaultSensorRadius /* sensorRadius */, - "" /* display */}; +SensorLocation FakeFingerprintEngineSide::defaultSensorLocation() { + return SensorLocation{.sensorLocationX = defaultSensorLocationX, + .sensorLocationY = defaultSensorLocationY, + .sensorRadius = defaultSensorRadius}; } } // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp index 3cdfc70008..68b0f0d0de 100644 --- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp +++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp @@ -31,12 +31,12 @@ using namespace ::android::fingerprint::virt; namespace aidl::android::hardware::biometrics::fingerprint { FakeFingerprintEngineUdfps::FakeFingerprintEngineUdfps() - : FakeFingerprintEngine(), mWorkMode(WorkMode::kIdle), mPointerDownTime(0), mUiReadyTime(0) {} + : FakeFingerprintEngine(), mPointerDownTime(0), mUiReadyTime(0) {} SensorLocation FakeFingerprintEngineUdfps::defaultSensorLocation() { - return {0 /* displayId (not used) */, defaultSensorLocationX /* sensorLocationX */, - defaultSensorLocationY /* sensorLocationY */, defaultSensorRadius /* sensorRadius */, - "" /* display */}; + return SensorLocation{.sensorLocationX = defaultSensorLocationX, + .sensorLocationY = defaultSensorLocationY, + .sensorRadius = defaultSensorRadius}; } ndk::ScopedAStatus FakeFingerprintEngineUdfps::onPointerDownImpl(int32_t /*pointerId*/, @@ -70,68 +70,17 @@ ndk::ScopedAStatus FakeFingerprintEngineUdfps::onUiReadyImpl() { } void FakeFingerprintEngineUdfps::fingerDownAction() { - switch (mWorkMode) { - case WorkMode::kAuthenticate: - onAuthenticateFingerDown(); - break; - case WorkMode::kEnroll: - onEnrollFingerDown(); - break; - case WorkMode::kDetectInteract: - onDetectInteractFingerDown(); - break; - default: - LOG(WARNING) << "unexpected call: onUiReady()"; - break; - } - + FakeFingerprintEngine::fingerDownAction(); mUiReadyTime = 0; mPointerDownTime = 0; } -void FakeFingerprintEngineUdfps::onAuthenticateFingerDown() { - FakeFingerprintEngine::authenticateImpl(mCb, mOperationId, mCancelVec[0]); -} - -void FakeFingerprintEngineUdfps::onEnrollFingerDown() { - // Any use case to emulate display touch for each capture during enrollment? - FakeFingerprintEngine::enrollImpl(mCb, mHat, mCancelVec[0]); -} - -void FakeFingerprintEngineUdfps::onDetectInteractFingerDown() { - FakeFingerprintEngine::detectInteractionImpl(mCb, mCancelVec[0]); -} - -void FakeFingerprintEngineUdfps::enrollImpl(ISessionCallback* cb, - const keymaster::HardwareAuthToken& hat, - const std::future& cancel) { - updateContext(WorkMode::kEnroll, cb, const_cast&>(cancel), 0, hat); -} - -void FakeFingerprintEngineUdfps::authenticateImpl(ISessionCallback* cb, int64_t operationId, - const std::future& cancel) { - updateContext(WorkMode::kAuthenticate, cb, const_cast&>(cancel), operationId, - keymaster::HardwareAuthToken()); -} - -void FakeFingerprintEngineUdfps::detectInteractionImpl(ISessionCallback* cb, - const std::future& cancel) { - updateContext(WorkMode::kDetectInteract, cb, const_cast&>(cancel), 0, - keymaster::HardwareAuthToken()); -} - void FakeFingerprintEngineUdfps::updateContext(WorkMode mode, ISessionCallback* cb, std::future& cancel, int64_t operationId, const keymaster::HardwareAuthToken& hat) { + FakeFingerprintEngine::updateContext(mode, cb, cancel, operationId, hat); mPointerDownTime = 0; mUiReadyTime = 0; - mCancelVec.clear(); - - mCancelVec.push_back(std::move(cancel)); - mWorkMode = mode; - mCb = cb; - mOperationId = operationId; - mHat = hat; } } // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp index 5996406fd0..b0163ee246 100644 --- a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp +++ b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp @@ -67,9 +67,13 @@ int64_t FakeLockoutTracker::getLockoutTimeLeft() { int64_t res = 0; if (mLockoutTimedStart > 0) { + int32_t lockoutTimedDuration = + FingerprintHalProperties::lockout_timed_duration().value_or(10 * 100); auto now = Util::getSystemNanoTime(); - auto left = now - mLockoutTimedStart; - res = (left > 0) ? (left / 1000000LL) : 0; + auto elapsed = (now - mLockoutTimedStart) / 1000000LL; + res = lockoutTimedDuration - elapsed; + LOG(INFO) << "xxxxxx: elapsed=" << elapsed << " now = " << now + << " mLockoutTimedStart=" << mLockoutTimedStart << " res=" << res; } return res; diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp index f00a49d26e..79b563e5ad 100644 --- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp +++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp @@ -17,6 +17,7 @@ #include "Fingerprint.h" #include "Session.h" +#include #include #include @@ -59,6 +60,7 @@ Fingerprint::Fingerprint() : mWorker(MAX_WORKER_QUEUE_SIZE) { << sensorTypeProp; } LOG(INFO) << "sensorTypeProp:" << sensorTypeProp; + LOG(INFO) << "ro.product.name=" << ::android::base::GetProperty("ro.product.name", "UNKNOWN"); } ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector* out) { @@ -105,16 +107,16 @@ ndk::ScopedAStatus Fingerprint::createSession(int32_t sensorId, int32_t userId, mSession->linkToDeath(cb->asBinder().get()); - LOG(INFO) << "createSession: sensorId:" << sensorId << " userId:" << userId; + LOG(INFO) << __func__ << ": sensorId:" << sensorId << " userId:" << userId; return ndk::ScopedAStatus::ok(); } binder_status_t Fingerprint::dump(int fd, const char** /*args*/, uint32_t numArgs) { if (fd < 0) { - LOG(ERROR) << "Fingerprint::dump fd invalid: " << fd; + LOG(ERROR) << __func__ << "fd invalid: " << fd; return STATUS_BAD_VALUE; } else { - LOG(INFO) << "Fingerprint::dump fd:" << fd << "numArgs:" << numArgs; + LOG(INFO) << __func__ << " fd:" << fd << "numArgs:" << numArgs; } dprintf(fd, "----- FingerprintVirtualHal::dump -----\n"); @@ -131,11 +133,11 @@ binder_status_t Fingerprint::dump(int fd, const char** /*args*/, uint32_t numArg binder_status_t Fingerprint::handleShellCommand(int in, int out, int err, const char** args, uint32_t numArgs) { - LOG(INFO) << "Fingerprint::handleShellCommand in:" << in << " out:" << out << " err:" << err + LOG(INFO) << __func__ << " in:" << in << " out:" << out << " err:" << err << " numArgs:" << numArgs; if (numArgs == 0) { - LOG(INFO) << "Fingerprint::handleShellCommand: available commands"; + LOG(INFO) << __func__ << ": available commands"; onHelp(out); return STATUS_OK; } @@ -163,7 +165,7 @@ void Fingerprint::onHelp(int fd) { } void Fingerprint::resetConfigToDefault() { - LOG(INFO) << "reset virtual HAL configuration to default"; + LOG(INFO) << __func__ << ": reset virtual HAL configuration to default"; #define RESET_CONFIG_O(__NAME__) \ if (FingerprintHalProperties::__NAME__()) FingerprintHalProperties::__NAME__(std::nullopt) #define RESET_CONFIG_V(__NAME__) \ diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h index 1279cd92a5..2450115aaf 100644 --- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h +++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h @@ -38,7 +38,7 @@ namespace aidl::android::hardware::biometrics::fingerprint { // A fake engine that is backed by system properties instead of hardware. class FakeFingerprintEngine { public: - FakeFingerprintEngine() : mRandom(std::mt19937::default_seed) {} + FakeFingerprintEngine(); virtual ~FakeFingerprintEngine() {} void generateChallengeImpl(ISessionCallback* cb); @@ -66,6 +66,8 @@ class FakeFingerprintEngine { virtual SensorLocation defaultSensorLocation(); + virtual void fingerDownAction(); + std::vector parseIntSequence(const std::string& str, const std::string& sep = ","); std::vector> parseEnrollmentCapture(const std::string& str); @@ -74,15 +76,35 @@ class FakeFingerprintEngine { std::mt19937 mRandom; + enum class WorkMode : int8_t { kIdle = 0, kAuthenticate, kEnroll, kDetectInteract }; + + WorkMode getWorkMode() { return mWorkMode; } + virtual std::string toString() const { std::ostringstream os; os << "----- FakeFingerprintEngine:: -----" << std::endl; + os << "mWorkMode:" << (int)mWorkMode; os << "acquiredVendorInfoBase:" << FINGERPRINT_ACQUIRED_VENDOR_BASE; os << ", errorVendorBase:" << FINGERPRINT_ERROR_VENDOR_BASE << std::endl; os << mLockoutTracker.toString(); return os.str(); } + protected: + virtual void updateContext(WorkMode mode, ISessionCallback* cb, std::future& cancel, + int64_t operationId, const keymaster::HardwareAuthToken& hat); + + bool onEnrollFingerDown(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat, + const std::future& cancel); + bool onAuthenticateFingerDown(ISessionCallback* cb, int64_t, const std::future& cancel); + bool onDetectInteractFingerDown(ISessionCallback* cb, const std::future& cancel); + + WorkMode mWorkMode; + ISessionCallback* mCb; + keymaster::HardwareAuthToken mHat; + std::future mCancel; + int64_t mOperationId; + private: static constexpr int32_t FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; static constexpr int32_t FINGERPRINT_ERROR_VENDOR_BASE = 1000; @@ -91,8 +113,21 @@ class FakeFingerprintEngine { bool parseEnrollmentCaptureSingle(const std::string& str, std::vector>& res); int32_t getRandomInRange(int32_t bound1, int32_t bound2); + bool checkSensorLockout(ISessionCallback*); + void clearLockout(ISessionCallback* cb); FakeLockoutTracker mLockoutTracker; + + protected: + // lockout timer + void lockoutTimerExpired(ISessionCallback* cb); + bool isLockoutTimerSupported; + bool isLockoutTimerStarted; + bool isLockoutTimerAborted; + + public: + void startLockoutTimer(int64_t timeout, ISessionCallback* cb); + bool getLockoutTimerStarted() { return isLockoutTimerStarted; } }; } // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h index c2fc005ffc..67a3ebc467 100644 --- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h +++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h @@ -28,7 +28,7 @@ class FakeFingerprintEngineSide : public FakeFingerprintEngine { static constexpr int32_t defaultSensorLocationY = 600; static constexpr int32_t defaultSensorRadius = 150; - FakeFingerprintEngineSide() : FakeFingerprintEngine() {} + FakeFingerprintEngineSide(); ~FakeFingerprintEngineSide() {} virtual SensorLocation defaultSensorLocation() override; diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h index c5e93e72aa..2270eca532 100644 --- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h +++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h @@ -42,39 +42,20 @@ class FakeFingerprintEngineUdfps : public FakeFingerprintEngine { SensorLocation defaultSensorLocation() override; - void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat, - const std::future& cancel); - void authenticateImpl(ISessionCallback* cb, int64_t operationId, - const std::future& cancel); - void detectInteractionImpl(ISessionCallback* cb, const std::future& cancel); - - enum class WorkMode : int8_t { kIdle = 0, kAuthenticate, kEnroll, kDetectInteract }; - - WorkMode getWorkMode() { return mWorkMode; } + void updateContext(WorkMode mode, ISessionCallback* cb, std::future& cancel, + int64_t operationId, const keymaster::HardwareAuthToken& hat); + void fingerDownAction(); std::string toString() const { std::ostringstream os; os << FakeFingerprintEngine::toString(); os << "----- FakeFingerprintEngineUdfps -----" << std::endl; - os << "mWorkMode:" << (int)mWorkMode; os << ", mUiReadyTime:" << mUiReadyTime; os << ", mPointerDownTime:" << mPointerDownTime << std::endl; return os.str(); } private: - void onAuthenticateFingerDown(); - void onEnrollFingerDown(); - void onDetectInteractFingerDown(); - void fingerDownAction(); - void updateContext(WorkMode mode, ISessionCallback* cb, std::future& cancel, - int64_t operationId, const keymaster::HardwareAuthToken& hat); - - WorkMode mWorkMode; - ISessionCallback* mCb; - keymaster::HardwareAuthToken mHat; - std::vector> mCancelVec; - int64_t mOperationId; int64_t mPointerDownTime; int64_t mUiReadyTime; }; diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h index fc4fb8dbff..2bd66d4e0b 100644 --- a/biometrics/fingerprint/aidl/default/include/Fingerprint.h +++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h @@ -43,6 +43,7 @@ class Fingerprint : public BnFingerprint { private: void resetConfigToDefault(); void onHelp(int); + void onSimFingerDown(); std::unique_ptr mEngine; WorkerThread mWorker; diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp index a200b39739..fe405f4110 100644 --- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp +++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp @@ -93,9 +93,13 @@ class TestSessionCallback : public BnSessionCallback { return ndk::ScopedAStatus::ok(); }; ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override { + mLockoutTimed = true; + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus onLockoutCleared() override { + mLockoutCleared = true; return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); } Error mError = Error::UNKNOWN; @@ -110,6 +114,8 @@ class TestSessionCallback : public BnSessionCallback { bool mAuthenticateFailed = false; bool mAuthenticatorIdInvalidated = false; bool mLockoutPermanent = false; + bool mLockoutTimed = false; + bool mLockoutCleared = false; int mInteractionDetectedCount = 0; int32_t mLastAcquiredInfo = -1; int32_t mLastAcquiredVendorCode = -1; @@ -132,6 +138,8 @@ class FakeFingerprintEngineTest : public ::testing::Test { FingerprintHalProperties::operation_enroll_latency({}); FingerprintHalProperties::operation_authenticate_latency({}); FingerprintHalProperties::operation_detect_interaction_latency({}); + FingerprintHalProperties::operation_authenticate_fails(false); + FingerprintHalProperties::operation_detect_interaction_latency({}); } FakeFingerprintEngine mEngine; @@ -178,11 +186,14 @@ TEST_F(FakeFingerprintEngineTest, Enroll) { FingerprintHalProperties::next_enrollment("4:0,0:true"); keymaster::HardwareAuthToken hat{.mac = {2, 4}}; mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future()); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kEnroll); + mEngine.fingerDownAction(); ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value()); ASSERT_EQ(1, FingerprintHalProperties::enrollments().size()); ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value()); ASSERT_EQ(4, mCallback->mLastEnrolled); ASSERT_EQ(1, mCallback->mLastAcquiredInfo); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle); } TEST_F(FakeFingerprintEngineTest, EnrollCancel) { @@ -192,6 +203,7 @@ TEST_F(FakeFingerprintEngineTest, EnrollCancel) { keymaster::HardwareAuthToken hat{.mac = {2, 4}}; mCancel.set_value(); mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(Error::CANCELED, mCallback->mError); ASSERT_EQ(-1, mCallback->mLastEnrolled); ASSERT_EQ(0, FingerprintHalProperties::enrollments().size()); @@ -204,6 +216,7 @@ TEST_F(FakeFingerprintEngineTest, EnrollFail) { FingerprintHalProperties::next_enrollment(next); keymaster::HardwareAuthToken hat{.mac = {2, 4}}; mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(Error::UNABLE_TO_PROCESS, mCallback->mError); ASSERT_EQ(-1, mCallback->mLastEnrolled); ASSERT_EQ(0, FingerprintHalProperties::enrollments().size()); @@ -216,6 +229,7 @@ TEST_F(FakeFingerprintEngineTest, EnrollAcquired) { keymaster::HardwareAuthToken hat{.mac = {2, 4}}; int32_t prevCnt = mCallback->mLastAcquiredCount; mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value()); ASSERT_EQ(1, FingerprintHalProperties::enrollments().size()); ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value()); @@ -229,9 +243,12 @@ TEST_F(FakeFingerprintEngineTest, Authenticate) { FingerprintHalProperties::enrollments({1, 2}); FingerprintHalProperties::enrollment_hit(2); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate); + mEngine.fingerDownAction(); ASSERT_FALSE(mCallback->mAuthenticateFailed); ASSERT_EQ(2, mCallback->mLastAuthenticated); ASSERT_EQ(1, mCallback->mLastAcquiredInfo); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle); } TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) { @@ -239,6 +256,7 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) { FingerprintHalProperties::enrollment_hit(2); mCancel.set_value(); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(Error::CANCELED, mCallback->mError); ASSERT_EQ(-1, mCallback->mLastAuthenticated); } @@ -247,6 +265,7 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateNotSet) { FingerprintHalProperties::enrollments({1, 2}); FingerprintHalProperties::enrollment_hit({}); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_TRUE(mCallback->mAuthenticateFailed); } @@ -254,7 +273,9 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateNotEnrolled) { FingerprintHalProperties::enrollments({1, 2}); FingerprintHalProperties::enrollment_hit(3); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_TRUE(mCallback->mAuthenticateFailed); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate); } TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) { @@ -262,6 +283,7 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) { FingerprintHalProperties::enrollment_hit(2); FingerprintHalProperties::lockout(true); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_TRUE(mCallback->mLockoutPermanent); ASSERT_NE(mCallback->mError, Error::UNKNOWN); } @@ -269,6 +291,7 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) { TEST_F(FakeFingerprintEngineTest, AuthenticateError8) { FingerprintHalProperties::operation_authenticate_error(8); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(mCallback->mError, (Error)8); ASSERT_EQ(mCallback->mErrorVendorCode, 0); } @@ -276,10 +299,19 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateError8) { TEST_F(FakeFingerprintEngineTest, AuthenticateError9) { FingerprintHalProperties::operation_authenticate_error(1009); mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(mCallback->mError, (Error)7); ASSERT_EQ(mCallback->mErrorVendorCode, 9); } +TEST_F(FakeFingerprintEngineTest, AuthenticateFails) { + FingerprintHalProperties::operation_authenticate_fails(true); + mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); + ASSERT_TRUE(mCallback->mAuthenticateFailed); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate); +} + TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) { FingerprintHalProperties::lockout(false); FingerprintHalProperties::enrollments({1, 2}); @@ -287,6 +319,7 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) { FingerprintHalProperties::operation_authenticate_acquired("4,1009"); int32_t prevCount = mCallback->mLastAcquiredCount; mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_FALSE(mCallback->mAuthenticateFailed); ASSERT_EQ(2, mCallback->mLastAuthenticated); ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount); @@ -300,8 +333,11 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetect) { FingerprintHalProperties::enrollment_hit(2); FingerprintHalProperties::operation_detect_interaction_acquired(""); mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future()); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kDetectInteract); + mEngine.fingerDownAction(); ASSERT_EQ(1, mCallback->mInteractionDetectedCount); ASSERT_EQ(1, mCallback->mLastAcquiredInfo); + ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle); } TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) { @@ -310,6 +346,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) { FingerprintHalProperties::enrollment_hit(2); mCancel.set_value(); mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(Error::CANCELED, mCallback->mError); ASSERT_EQ(0, mCallback->mInteractionDetectedCount); } @@ -319,6 +356,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectNotSet) { FingerprintHalProperties::enrollments({1, 2}); FingerprintHalProperties::enrollment_hit({}); mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(0, mCallback->mInteractionDetectedCount); } @@ -326,6 +364,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectNotEnrolled) { FingerprintHalProperties::enrollments({1, 2}); FingerprintHalProperties::enrollment_hit(25); mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(0, mCallback->mInteractionDetectedCount); } @@ -333,6 +372,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectError) { FingerprintHalProperties::detect_interaction(true); FingerprintHalProperties::operation_detect_interaction_error(8); mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(0, mCallback->mInteractionDetectedCount); ASSERT_EQ(mCallback->mError, (Error)8); ASSERT_EQ(mCallback->mErrorVendorCode, 0); @@ -345,6 +385,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) { FingerprintHalProperties::operation_detect_interaction_acquired("4,1013"); int32_t prevCount = mCallback->mLastAcquiredCount; mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future()); + mEngine.fingerDownAction(); ASSERT_EQ(1, mCallback->mInteractionDetectedCount); ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount); ASSERT_EQ(7, mCallback->mLastAcquiredInfo); @@ -354,9 +395,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) { TEST_F(FakeFingerprintEngineTest, EnumerateEnrolled) { FingerprintHalProperties::enrollments({2, 4, 8}); mEngine.enumerateEnrollmentsImpl(mCallback.get()); - ASSERT_EQ( - 4, - mCallback->mLastEnrollmentEnumerated.size()); // Due to workaround. TODO (b/243129174) + ASSERT_EQ(3, mCallback->mLastEnrollmentEnumerated.size()); for (auto id : FingerprintHalProperties::enrollments()) { ASSERT_TRUE(std::find(mCallback->mLastEnrollmentEnumerated.begin(), mCallback->mLastEnrollmentEnumerated.end(), @@ -464,9 +503,15 @@ TEST_F(FakeFingerprintEngineTest, randomLatency) { FingerprintHalProperties::operation_detect_interaction_latency())); } ASSERT_TRUE(latencySet.size() > 95); - FingerprintHalProperties::operation_detect_interaction_latency({}); } +TEST_F(FakeFingerprintEngineTest, lockoutTimer) { + mEngine.startLockoutTimer(200, mCallback.get()); + ASSERT_TRUE(mEngine.getLockoutTimerStarted()); + std::this_thread::sleep_for(std::chrono::milliseconds(210)); + ASSERT_FALSE(mEngine.getLockoutTimerStarted()); + ASSERT_TRUE(mCallback->mLockoutCleared); +} } // namespace aidl::android::hardware::biometrics::fingerprint int main(int argc, char** argv) { diff --git a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp index 1b071eecd2..93c6f844ed 100644 --- a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp +++ b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp @@ -65,11 +65,11 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) { ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed); // time left int N = 5; - int64_t prevTimeLeft = INT_MIN; + int64_t prevTimeLeft = INT_MAX; for (int i = 0; i < N; i++) { SLEEP_MS(LOCKOUT_TIMED_DURATION / N + 1); int64_t currTimeLeft = mLockoutTracker.getLockoutTimeLeft(); - ASSERT_TRUE(currTimeLeft > prevTimeLeft); + ASSERT_TRUE(currTimeLeft < prevTimeLeft); prevTimeLeft = currTimeLeft; } ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone); diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl index 3298cac969..7769b8c373 100644 --- a/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl +++ b/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl @@ -70,9 +70,9 @@ union Metadata { /** * Station name. * - * This is a generic field to cover any radio technology. + *

This is a generic field to cover any radio technology. * - * If the PROGRAM_NAME has the same content as DAB_*_NAME or RDS_PS, + *

Note: If the program name has the same content as dab*Name or ({@link Metadata#rdsPs}, * it may not be present, to preserve space - framework must repopulate * it on the client side. */ @@ -86,10 +86,10 @@ union Metadata { /** * DAB ensemble name abbreviated (string). * - * The string must be up to 8 characters long. + *

Note: The string must be up to 8 characters long. * - * If the short variant is present, the long (DAB_ENSEMBLE_NAME) one must be - * present as well. + *

Note: If the short variant is present, the long ({@link Metadata#dabEnsembleName}) + * one must be present as well. */ String dabEnsembleNameShort; @@ -99,7 +99,9 @@ union Metadata { String dabServiceName; /** - * DAB service name abbreviated (see DAB_ENSEMBLE_NAME_SHORT) (string) + * DAB service name abbreviated (string) + * + *

Note: The string must be up to 8 characters long. */ String dabServiceNameShort; @@ -109,7 +111,9 @@ union Metadata { String dabComponentName; /** - * DAB component name abbreviated (see DAB_ENSEMBLE_NAME_SHORT) (string) + * DAB component name abbreviated (string) + * + *

Note: The string must be up to 8 characters long. */ String dabComponentNameShort; } diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl index 2057d97eb0..a2de5d6e21 100644 --- a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl +++ b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl @@ -30,8 +30,10 @@ parcelable ProgramIdentifier { IdentifierType type = IdentifierType.INVALID; /** - * The uint64_t value field holds the value in format described in comments - * for IdentifierType enum. + * The value field holds the value in format described in comments for IdentifierType enum. + * + * The value should be 64-bit unsigned integer, but is represented as 64-bit signed integer + * in AIDL. */ long value; } diff --git a/broadcastradio/aidl/default/VirtualRadio.cpp b/broadcastradio/aidl/default/VirtualRadio.cpp index 126bcff621..86c5a962bc 100644 --- a/broadcastradio/aidl/default/VirtualRadio.cpp +++ b/broadcastradio/aidl/default/VirtualRadio.cpp @@ -53,18 +53,18 @@ const VirtualRadio& VirtualRadio::getAmFmRadio() { static VirtualRadio amFmRadioMock( "AM/FM radio mock", { - {makeSelectorAmfm(/* frequency= */ 94900), "Wild 94.9", "Drake ft. Rihanna", + {makeSelectorAmfm(/* frequency= */ 94900u), "Wild 94.9", "Drake ft. Rihanna", "Too Good"}, - {makeSelectorAmfm(/* frequency= */ 96500), "KOIT", "Celine Dion", "All By Myself"}, - {makeSelectorAmfm(/* frequency= */ 97300), "Alice@97.3", "Drops of Jupiter", "Train"}, - {makeSelectorAmfm(/* frequency= */ 99700), "99.7 Now!", "The Chainsmokers", "Closer"}, - {makeSelectorAmfm(/* frequency= */ 101300), "101-3 KISS-FM", "Justin Timberlake", + {makeSelectorAmfm(/* frequency= */ 96500u), "KOIT", "Celine Dion", "All By Myself"}, + {makeSelectorAmfm(/* frequency= */ 97300u), "Alice@97.3", "Drops of Jupiter", "Train"}, + {makeSelectorAmfm(/* frequency= */ 99700u), "99.7 Now!", "The Chainsmokers", "Closer"}, + {makeSelectorAmfm(/* frequency= */ 101300u), "101-3 KISS-FM", "Justin Timberlake", "Rock Your Body"}, - {makeSelectorAmfm(/* frequency= */ 103700), "iHeart80s @ 103.7", "Michael Jackson", + {makeSelectorAmfm(/* frequency= */ 103700u), "iHeart80s @ 103.7", "Michael Jackson", "Billie Jean"}, - {makeSelectorAmfm(/* frequency= */ 106100), "106 KMEL", "Drake", "Marvins Room"}, - {makeSelectorAmfm(/* frequency= */ 700), "700 AM", "Artist700", "Title700"}, - {makeSelectorAmfm(/* frequency= */ 1700), "1700 AM", "Artist1700", "Title1700"}, + {makeSelectorAmfm(/* frequency= */ 106100u), "106 KMEL", "Drake", "Marvins Room"}, + {makeSelectorAmfm(/* frequency= */ 700u), "700 AM", "Artist700", "Title700"}, + {makeSelectorAmfm(/* frequency= */ 1700u), "1700 AM", "Artist1700", "Title1700"}, }); // clang-format on return amFmRadioMock; @@ -77,13 +77,13 @@ const VirtualRadio& VirtualRadio::getDabRadio() { "DAB radio mock", { {makeSelectorDab(/* sidExt= */ 0xA000000001u, /* ensemble= */ 0x0001u, - /* freq= */ 225648), "BBC Radio 1", "Khalid", "Talk"}, + /* freq= */ 225648u), "BBC Radio 1", "Khalid", "Talk"}, {makeSelectorDab(/* sidExt= */ 0xB000000001u, /* ensemble= */ 0x1001u, - /* freq= */ 222064), "Classic FM", "Jean Sibelius", "Andante Festivo"}, + /* freq= */ 222064u), "Classic FM", "Jean Sibelius", "Andante Festivo"}, {makeSelectorDab(/* sidExt= */ 0xB000000002u, /* ensemble= */ 0x1002u, - /* freq= */ 227360), "Absolute Radio", "Coldplay", "Clocks"}, + /* freq= */ 227360u), "Absolute Radio", "Coldplay", "Clocks"}, {makeSelectorDab(/* sidExt= */ 0xB000000002u, /* ensemble= */ 0x1002u, - /* freq= */ 222064), "Absolute Radio", "Coldplay", "Clocks"}, + /* freq= */ 222064u), "Absolute Radio", "Coldplay", "Clocks"}, }); // clang-format on return dabRadioMock; diff --git a/broadcastradio/common/utilsaidl/Utils.cpp b/broadcastradio/common/utilsaidl/Utils.cpp index 0551badc45..de4f52926d 100644 --- a/broadcastradio/common/utilsaidl/Utils.cpp +++ b/broadcastradio/common/utilsaidl/Utils.cpp @@ -204,7 +204,7 @@ bool isSupported(const Properties& prop, const ProgramSelector& sel) { } bool isValid(const ProgramIdentifier& id) { - int64_t val = id.value; + uint64_t val = static_cast(id.value); bool valid = true; auto expect = [&valid](bool condition, const string& message) { @@ -231,11 +231,11 @@ bool isValid(const ProgramIdentifier& id) { expect(val <= 0xFFFFu, "16bit id"); break; case IdentifierType::HD_STATION_ID_EXT: { - int64_t stationId = val & 0xFFFFFFFF; // 32bit + uint64_t stationId = val & 0xFFFFFFFF; // 32bit val >>= 32; - int64_t subchannel = val & 0xF; // 4bit + uint64_t subchannel = val & 0xF; // 4bit val >>= 4; - int64_t freq = val & 0x3FFFF; // 18bit + uint64_t freq = val & 0x3FFFF; // 18bit expect(stationId != 0u, "HD station id != 0"); expect(subchannel < 8u, "HD subch < 8"); expect(freq > 100u, "f > 100kHz"); @@ -252,9 +252,9 @@ bool isValid(const ProgramIdentifier& id) { break; } case IdentifierType::DAB_SID_EXT: { - int64_t sid = val & 0xFFFFFFFF; // 32bit + uint64_t sid = val & 0xFFFFFFFF; // 32bit val >>= 32; - int64_t ecc = val & 0xFF; // 8bit + uint64_t ecc = val & 0xFF; // 8bit expect(sid != 0u, "DAB SId != 0"); expect(ecc >= 0xA0u && ecc <= 0xF6u, "Invalid ECC, see ETSI TS 101 756 V2.1.1"); break; @@ -305,19 +305,19 @@ ProgramIdentifier makeIdentifier(IdentifierType type, int64_t value) { return {type, value}; } -ProgramSelector makeSelectorAmfm(int32_t frequency) { +ProgramSelector makeSelectorAmfm(uint32_t frequency) { ProgramSelector sel = {}; sel.primaryId = makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, frequency); return sel; } -ProgramSelector makeSelectorDab(int64_t sidExt) { +ProgramSelector makeSelectorDab(uint64_t sidExt) { ProgramSelector sel = {}; sel.primaryId = makeIdentifier(IdentifierType::DAB_SID_EXT, sidExt); return sel; } -ProgramSelector makeSelectorDab(int64_t sidExt, int32_t ensemble, int64_t freq) { +ProgramSelector makeSelectorDab(uint64_t sidExt, uint32_t ensemble, uint64_t freq) { ProgramSelector sel = {}; sel.primaryId = makeIdentifier(IdentifierType::DAB_SID_EXT, sidExt); vector secondaryIds = { diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h index ad075f2943..ee85a178da 100644 --- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h +++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h @@ -137,9 +137,9 @@ bool isValid(const ProgramIdentifier& id); bool isValid(const ProgramSelector& sel); ProgramIdentifier makeIdentifier(IdentifierType type, int64_t value); -ProgramSelector makeSelectorAmfm(int32_t frequency); -ProgramSelector makeSelectorDab(int64_t sidExt); -ProgramSelector makeSelectorDab(int64_t sidExt, int32_t ensemble, int64_t freq); +ProgramSelector makeSelectorAmfm(uint32_t frequency); +ProgramSelector makeSelectorDab(uint64_t sidExt); +ProgramSelector makeSelectorDab(uint64_t sidExt, uint32_t ensemble, uint64_t freq); bool satisfies(const ProgramFilter& filter, const ProgramSelector& sel); diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml index de2e1d14bf..633949cf0b 100644 --- a/compatibility_matrices/compatibility_matrix.9.xml +++ b/compatibility_matrices/compatibility_matrix.9.xml @@ -589,6 +589,14 @@ chip[0-9]+ + + android.hardware.threadnetwork + 1 + + IThreadChip + chip0 + + android.hardware.tv.hdmi.cec 1 diff --git a/drm/aidl/Android.bp b/drm/aidl/Android.bp index fb04d842ef..afcb603db7 100644 --- a/drm/aidl/Android.bp +++ b/drm/aidl/Android.bp @@ -23,7 +23,7 @@ aidl_interface { sdk_version: "module_current", }, ndk: { - min_sdk_version: "UpsideDownCake", + min_sdk_version: "34", }, }, double_loadable: true, diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp index 4f5e6a0b6b..5e2cbe3c52 100644 --- a/gnss/aidl/vts/gnss_hal_test.cpp +++ b/gnss/aidl/vts/gnss_hal_test.cpp @@ -486,8 +486,6 @@ void GnssHalTest::collectSvInfoListTimestamps(const int numMeasurementEvents, auto status = aidl_gnss_hal_->startSvStatus(); EXPECT_TRUE(status.isOk()); - ASSERT_TRUE(aidl_gnss_cb_->sv_info_list_timestamps_millis_cbq_.size() == - aidl_gnss_cb_->sv_info_list_cbq_.size()); long lastElapsedRealtimeMillis = 0; for (int i = 0; i < numMeasurementEvents; i++) { long timeStamp; diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp index 7bc2eeb349..83e11939fd 100644 --- a/wifi/aidl/default/aidl_struct_util.cpp +++ b/wifi/aidl/default/aidl_struct_util.cpp @@ -887,6 +887,15 @@ bool convertLegacyLinkLayerRadioStatsToAidl( return true; } +StaLinkLayerLinkStats::StaLinkState convertLegacyMlLinkStateToAidl(wifi_link_state state) { + if (state == wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE) { + return StaLinkLayerLinkStats::StaLinkState::NOT_IN_USE; + } else if (state == wifi_link_state::WIFI_LINK_STATE_IN_USE) { + return StaLinkLayerLinkStats::StaLinkState::IN_USE; + } + return StaLinkLayerLinkStats::StaLinkState::UNKNOWN; +} + bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats, StaLinkLayerStats* aidl_stats) { if (!aidl_stats) { @@ -898,6 +907,7 @@ bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& leg for (const auto& link : legacy_ml_stats.links) { StaLinkLayerLinkStats linkStats = {}; linkStats.linkId = link.stat.link_id; + linkStats.state = convertLegacyMlLinkStateToAidl(link.stat.state); linkStats.radioId = link.stat.radio; linkStats.frequencyMhz = link.stat.frequency; linkStats.beaconRx = link.stat.beacon_rx; diff --git a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp index 5c334f8d56..995a13d996 100644 --- a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp +++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp @@ -123,6 +123,9 @@ TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerMlStatsToAidl) { // Add two radio stats legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + wifi_link_state states[sizeof(wifi_link_state)] = {wifi_link_state::WIFI_LINK_STATE_UNKNOWN, + wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE, + wifi_link_state::WIFI_LINK_STATE_IN_USE}; // Add two links. legacy_ml_stats.links.push_back(legacy_hal::LinkStats{}); legacy_ml_stats.links.push_back(legacy_hal::LinkStats{}); @@ -133,6 +136,7 @@ TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerMlStatsToAidl) { link.stat.beacon_rx = rand(); // MLO link id: 0 - 15 link.stat.link_id = rand() % 16; + link.stat.state = states[rand() % sizeof(states)]; // Maximum number of radios is limited to 3 for testing. link.stat.radio = rand() % 4; link.stat.frequency = rand(); @@ -241,6 +245,18 @@ TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerMlStatsToAidl) { int l = 0; for (legacy_hal::LinkStats& link : legacy_ml_stats.links) { EXPECT_EQ(link.stat.link_id, (uint8_t)converted.iface.links[l].linkId); + StaLinkLayerLinkStats::StaLinkState expectedState; + switch (link.stat.state) { + case wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE: + expectedState = StaLinkLayerLinkStats::StaLinkState::NOT_IN_USE; + break; + case wifi_link_state::WIFI_LINK_STATE_IN_USE: + expectedState = StaLinkLayerLinkStats::StaLinkState::IN_USE; + break; + default: + expectedState = StaLinkLayerLinkStats::StaLinkState::UNKNOWN; + } + EXPECT_EQ(expectedState, converted.iface.links[l].state); EXPECT_EQ(link.stat.radio, converted.iface.links[l].radioId); EXPECT_EQ(link.stat.frequency, (uint32_t)converted.iface.links[l].frequencyMhz); EXPECT_EQ(link.stat.beacon_rx, (uint32_t)converted.iface.links[l].beaconRx); diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp index 6dd9156414..8265e5bdc9 100644 --- a/wifi/aidl/default/wifi_chip.cpp +++ b/wifi/aidl/default/wifi_chip.cpp @@ -1452,14 +1452,24 @@ WifiChip::getSupportedRadioCombinationsInternal() { if (legacy_status != legacy_hal::WIFI_SUCCESS) { LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: " << legacyErrorToString(legacy_status); + if (legacy_matrix != nullptr) { + free(legacy_matrix); + } return {aidl_combinations, createWifiStatusFromLegacyError(legacy_status)}; } if (!aidl_struct_util::convertLegacyRadioCombinationsMatrixToAidl(legacy_matrix, &aidl_combinations)) { LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToAidl() "; + if (legacy_matrix != nullptr) { + free(legacy_matrix); + } return {aidl_combinations, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)}; } + + if (legacy_matrix != nullptr) { + free(legacy_matrix); + } return {aidl_combinations, ndk::ScopedAStatus::ok()}; }