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/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp index 356673f715..790d60b252 100644 --- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp +++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp @@ -32,11 +32,11 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -61,11 +61,6 @@ using ::testing::SaveArg; namespace bcutils = ::aidl::android::hardware::broadcastradio::utils; -inline constexpr std::chrono::seconds kTuneTimeoutSec = - std::chrono::seconds(IBroadcastRadio::TUNER_TIMEOUT_MS * 1000); -inline constexpr std::chrono::seconds kProgramListScanTimeoutSec = - std::chrono::seconds(IBroadcastRadio::LIST_COMPLETE_TIMEOUT_MS * 1000); - const ConfigFlag kConfigFlagValues[] = { ConfigFlag::FORCE_MONO, ConfigFlag::FORCE_ANALOG, @@ -108,20 +103,68 @@ bool supportsFM(const AmFmRegionConfig& config) { } // namespace -class TunerCallbackMock : public BnTunerCallback { +class CallbackFlag final { public: - TunerCallbackMock(); + CallbackFlag(int timeoutMs) { mTimeoutMs = timeoutMs; } + /** + * Notify that the callback is called. + */ + void notify() { + std::unique_lock lock(mMutex); + mCalled = true; + lock.unlock(); + mCv.notify_all(); + }; + + /** + * Wait for the timeout passed into the constructor. + */ + bool wait() { + std::unique_lock lock(mMutex); + return mCv.wait_for(lock, std::chrono::milliseconds(mTimeoutMs), + [this] { return mCalled; }); + }; + + /** + * Reset the callback to not called. + */ + void reset() { + std::unique_lock lock(mMutex); + mCalled = false; + } + + private: + std::mutex mMutex; + bool mCalled GUARDED_BY(mMutex) = false; + std::condition_variable mCv; + int mTimeoutMs; +}; + +class TunerCallbackImpl final : public BnTunerCallback { + public: + TunerCallbackImpl(); ScopedAStatus onTuneFailed(Result result, const ProgramSelector& selector) override; - MOCK_TIMEOUT_METHOD1(onCurrentProgramInfoChangedMock, ScopedAStatus(const ProgramInfo&)); ScopedAStatus onCurrentProgramInfoChanged(const ProgramInfo& info) override; ScopedAStatus onProgramListUpdated(const ProgramListChunk& chunk) override; - MOCK_METHOD1(onAntennaStateChange, ScopedAStatus(bool connected)); - MOCK_METHOD1(onParametersUpdated, ScopedAStatus(const vector& parameters)); - MOCK_METHOD2(onConfigFlagUpdated, ScopedAStatus(ConfigFlag in_flag, bool in_value)); - MOCK_TIMEOUT_METHOD0(onProgramListReady, void()); + ScopedAStatus onParametersUpdated(const vector& parameters) override; + ScopedAStatus onAntennaStateChange(bool connected) override; + ScopedAStatus onConfigFlagUpdated(ConfigFlag in_flag, bool in_value) override; + bool waitOnCurrentProgramInfoChangedCallback(); + bool waitProgramReady(); + void reset(); + + bool getAntennaConnectionState(); + ProgramInfo getCurrentProgramInfo(); + bcutils::ProgramInfoSet getProgramList(); + + private: std::mutex mLock; + bool mAntennaConnectionState GUARDED_BY(mLock); + ProgramInfo mCurrentProgramInfo GUARDED_BY(mLock); bcutils::ProgramInfoSet mProgramList GUARDED_BY(mLock); + CallbackFlag mOnCurrentProgramInfoChangedFlag = CallbackFlag(IBroadcastRadio::TUNER_TIMEOUT_MS); + CallbackFlag mOnProgramListReadyFlag = CallbackFlag(IBroadcastRadio::LIST_COMPLETE_TIMEOUT_MS); }; struct AnnouncementListenerMock : public BnAnnouncementListener { @@ -139,7 +182,7 @@ class BroadcastRadioHalTest : public testing::TestWithParam { std::shared_ptr mModule; Properties mProperties; - std::shared_ptr mCallback = SharedRefBase::make(); + std::shared_ptr mCallback; }; MATCHER_P(InfoHasId, id, string(negation ? "does not contain" : "contains") + " " + id.toString()) { @@ -147,20 +190,18 @@ MATCHER_P(InfoHasId, id, string(negation ? "does not contain" : "contains") + " return ids.end() != find(ids.begin(), ids.end(), id.value); } -TunerCallbackMock::TunerCallbackMock() { - EXPECT_TIMEOUT_CALL(*this, onCurrentProgramInfoChangedMock, _).Times(AnyNumber()); - - // we expect the antenna is connected through the whole test - EXPECT_CALL(*this, onAntennaStateChange(false)).Times(0); +TunerCallbackImpl::TunerCallbackImpl() { + mAntennaConnectionState = true; } -ScopedAStatus TunerCallbackMock::onTuneFailed(Result result, const ProgramSelector& selector) { +ScopedAStatus TunerCallbackImpl::onTuneFailed(Result result, const ProgramSelector& selector) { LOG(DEBUG) << "Tune failed for selector" << selector.toString(); EXPECT_TRUE(result == Result::CANCELED); return ndk::ScopedAStatus::ok(); } -ScopedAStatus TunerCallbackMock::onCurrentProgramInfoChanged(const ProgramInfo& info) { +ScopedAStatus TunerCallbackImpl::onCurrentProgramInfoChanged(const ProgramInfo& info) { + LOG(DEBUG) << "onCurrentProgramInfoChanged called"; for (const auto& id : info.selector) { EXPECT_NE(id.type, IdentifierType::INVALID); } @@ -196,21 +237,75 @@ ScopedAStatus TunerCallbackMock::onCurrentProgramInfoChanged(const ProgramInfo& } } - return onCurrentProgramInfoChangedMock(info); + { + std::lock_guard lk(mLock); + mCurrentProgramInfo = info; + } + + mOnCurrentProgramInfoChangedFlag.notify(); + return ndk::ScopedAStatus::ok(); } -ScopedAStatus TunerCallbackMock::onProgramListUpdated(const ProgramListChunk& chunk) { - std::lock_guard lk(mLock); - - updateProgramList(chunk, &mProgramList); +ScopedAStatus TunerCallbackImpl::onProgramListUpdated(const ProgramListChunk& chunk) { + LOG(DEBUG) << "onProgramListUpdated called"; + { + std::lock_guard lk(mLock); + updateProgramList(chunk, &mProgramList); + } if (chunk.complete) { - onProgramListReady(); + mOnProgramListReadyFlag.notify(); } return ndk::ScopedAStatus::ok(); } +ScopedAStatus TunerCallbackImpl::onParametersUpdated( + [[maybe_unused]] const vector& parameters) { + return ndk::ScopedAStatus::ok(); +} + +ScopedAStatus TunerCallbackImpl::onAntennaStateChange(bool connected) { + if (!connected) { + std::lock_guard lk(mLock); + mAntennaConnectionState = false; + } + return ndk::ScopedAStatus::ok(); +} + +ScopedAStatus TunerCallbackImpl::onConfigFlagUpdated([[maybe_unused]] ConfigFlag in_flag, + [[maybe_unused]] bool in_value) { + return ndk::ScopedAStatus::ok(); +} + +bool TunerCallbackImpl::waitOnCurrentProgramInfoChangedCallback() { + return mOnCurrentProgramInfoChangedFlag.wait(); +} + +bool TunerCallbackImpl::waitProgramReady() { + return mOnProgramListReadyFlag.wait(); +} + +void TunerCallbackImpl::reset() { + mOnCurrentProgramInfoChangedFlag.reset(); + mOnProgramListReadyFlag.reset(); +} + +bool TunerCallbackImpl::getAntennaConnectionState() { + std::lock_guard lk(mLock); + return mAntennaConnectionState; +} + +ProgramInfo TunerCallbackImpl::getCurrentProgramInfo() { + std::lock_guard lk(mLock); + return mCurrentProgramInfo; +} + +bcutils::ProgramInfoSet TunerCallbackImpl::getProgramList() { + std::lock_guard lk(mLock); + return mProgramList; +} + void BroadcastRadioHalTest::SetUp() { EXPECT_EQ(mModule.get(), nullptr) << "Module is already open"; @@ -228,6 +323,8 @@ void BroadcastRadioHalTest::SetUp() { EXPECT_FALSE(mProperties.product.empty()); EXPECT_GT(mProperties.supportedIdentifierTypes.size(), 0u); + mCallback = SharedRefBase::make(); + // set callback EXPECT_TRUE(mModule->setTunerCallback(mCallback).isOk()); } @@ -236,6 +333,11 @@ void BroadcastRadioHalTest::TearDown() { if (mModule) { ASSERT_TRUE(mModule->unsetTunerCallback().isOk()); } + if (mCallback) { + // we expect the antenna is connected through the whole test + EXPECT_TRUE(mCallback->getAntennaConnectionState()); + mCallback = nullptr; + } } bool BroadcastRadioHalTest::getAmFmRegionConfig(bool full, AmFmRegionConfig* config) { @@ -256,7 +358,7 @@ std::optional BroadcastRadioHalTest::getProgramList() { std::optional BroadcastRadioHalTest::getProgramList( const ProgramFilter& filter) { - EXPECT_TIMEOUT_CALL(*mCallback, onProgramListReady).Times(AnyNumber()); + mCallback->reset(); auto startResult = mModule->startProgramListUpdates(filter); @@ -268,13 +370,13 @@ std::optional BroadcastRadioHalTest::getProgramList( if (!startResult.isOk()) { return std::nullopt; } - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, kProgramListScanTimeoutSec); + EXPECT_TRUE(mCallback->waitProgramReady()); auto stopResult = mModule->stopProgramListUpdates(); EXPECT_TRUE(stopResult.isOk()); - return mCallback->mProgramList; + return mCallback->getProgramList(); } /** @@ -456,7 +558,7 @@ TEST_P(BroadcastRadioHalTest, TuneFailsWithoutTunerCallback) { * - if it is supported, the test is ignored; */ TEST_P(BroadcastRadioHalTest, TuneFailsWithNotSupported) { - LOG(DEBUG) << "TuneFailsWithInvalid Test"; + LOG(DEBUG) << "TuneFailsWithNotSupported Test"; vector supportTestId = { makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 0), // invalid @@ -477,9 +579,9 @@ TEST_P(BroadcastRadioHalTest, TuneFailsWithNotSupported) { for (const auto& id : supportTestId) { ProgramSelector sel{id, {}}; - auto result = mModule->tune(sel); - if (!bcutils::isSupported(mProperties, sel)) { + auto result = mModule->tune(sel); + EXPECT_EQ(result.getServiceSpecificError(), notSupportedError); } } @@ -508,9 +610,9 @@ TEST_P(BroadcastRadioHalTest, TuneFailsWithInvalid) { for (const auto& id : invalidId) { ProgramSelector sel{id, {}}; - auto result = mModule->tune(sel); - if (bcutils::isSupported(mProperties, sel)) { + auto result = mModule->tune(sel); + EXPECT_EQ(result.getServiceSpecificError(), invalidArgumentsError); } } @@ -549,13 +651,7 @@ TEST_P(BroadcastRadioHalTest, FmTune) { int64_t freq = 90900; // 90.9 FM ProgramSelector sel = makeSelectorAmfm(freq); // try tuning - ProgramInfo infoCb = {}; - EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, - InfoHasId(makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, freq))) - .Times(AnyNumber()) - .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(ndk::ScopedAStatus::ok())))) - .WillRepeatedly(testing::InvokeWithoutArgs([] { return ndk::ScopedAStatus::ok(); })); - + mCallback->reset(); auto result = mModule->tune(sel); // expect a failure if it's not supported @@ -566,7 +662,8 @@ TEST_P(BroadcastRadioHalTest, FmTune) { // expect a callback if it succeeds EXPECT_TRUE(result.isOk()); - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec); + EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback()); + ProgramInfo infoCb = mCallback->getCurrentProgramInfo(); LOG(DEBUG) << "Current program info: " << infoCb.toString(); @@ -638,12 +735,6 @@ TEST_P(BroadcastRadioHalTest, DabTune) { } // try tuning - ProgramInfo infoCb = {}; - EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, - InfoHasId(makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, freq))) - .Times(AnyNumber()) - .WillOnce( - DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(ndk::ScopedAStatus::ok())))); auto result = mModule->tune(sel); @@ -655,7 +746,9 @@ TEST_P(BroadcastRadioHalTest, DabTune) { // expect a callback if it succeeds EXPECT_TRUE(result.isOk()); - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec); + EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback()); + ProgramInfo infoCb = mCallback->getCurrentProgramInfo(); + LOG(DEBUG) << "Current program info: " << infoCb.toString(); // it should tune exactly to what was requested @@ -669,13 +762,13 @@ TEST_P(BroadcastRadioHalTest, DabTune) { * * Verifies that: * - the method succeeds; - * - the program info is changed within kTuneTimeoutSec; + * - the program info is changed within kTuneTimeoutMs; * - works both directions and with or without skipping sub-channel. */ TEST_P(BroadcastRadioHalTest, Seek) { LOG(DEBUG) << "Seek Test"; - EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber()); + mCallback->reset(); auto result = mModule->seek(/* in_directionUp= */ true, /* in_skipSubChannel= */ true); @@ -685,14 +778,14 @@ TEST_P(BroadcastRadioHalTest, Seek) { } EXPECT_TRUE(result.isOk()); - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec); + EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback()); - EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber()); + mCallback->reset(); result = mModule->seek(/* in_directionUp= */ false, /* in_skipSubChannel= */ false); EXPECT_TRUE(result.isOk()); - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec); + EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback()); } /** @@ -720,13 +813,13 @@ TEST_P(BroadcastRadioHalTest, SeekFailsWithoutTunerCallback) { * * Verifies that: * - the method succeeds or returns NOT_SUPPORTED; - * - the program info is changed within kTuneTimeoutSec if the method succeeded; + * - the program info is changed within kTuneTimeoutMs if the method succeeded; * - works both directions. */ TEST_P(BroadcastRadioHalTest, Step) { LOG(DEBUG) << "Step Test"; - EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber()); + mCallback->reset(); auto result = mModule->step(/* in_directionUp= */ true); @@ -735,14 +828,14 @@ TEST_P(BroadcastRadioHalTest, Step) { return; } EXPECT_TRUE(result.isOk()); - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec); + EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback()); - EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber()); + mCallback->reset(); result = mModule->step(/* in_directionUp= */ false); EXPECT_TRUE(result.isOk()); - EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec); + EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback()); } /** @@ -904,13 +997,12 @@ TEST_P(BroadcastRadioHalTest, SetConfigFlags) { LOG(DEBUG) << "SetConfigFlags Test"; auto get = [&](ConfigFlag flag) -> bool { - bool* gotValue = nullptr; + bool gotValue; - auto halResult = mModule->isConfigFlagSet(flag, gotValue); + auto halResult = mModule->isConfigFlagSet(flag, &gotValue); - EXPECT_FALSE(gotValue == nullptr); EXPECT_TRUE(halResult.isOk()); - return *gotValue; + return gotValue; }; auto notSupportedError = resultToInt(Result::NOT_SUPPORTED); @@ -955,7 +1047,7 @@ TEST_P(BroadcastRadioHalTest, SetConfigFlags) { * * Verifies that: * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED; - * - the complete list is fetched within kProgramListScanTimeoutSec; + * - the complete list is fetched within kProgramListScanTimeoutMs; * - stopProgramListUpdates does not crash. */ TEST_P(BroadcastRadioHalTest, GetProgramListFromEmptyFilter) { @@ -969,7 +1061,7 @@ TEST_P(BroadcastRadioHalTest, GetProgramListFromEmptyFilter) { * * Verifies that: * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED; - * - the complete list is fetched within kProgramListScanTimeoutSec; + * - the complete list is fetched within kProgramListScanTimeoutMs; * - stopProgramListUpdates does not crash; * - result for startProgramListUpdates using a filter with AMFM_FREQUENCY_KHZ value of the first * AMFM program matches the expected result. @@ -1017,7 +1109,7 @@ TEST_P(BroadcastRadioHalTest, GetProgramListFromAmFmFilter) { * * Verifies that: * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED; - * - the complete list is fetched within kProgramListScanTimeoutSec; + * - the complete list is fetched within kProgramListScanTimeoutMs; * - stopProgramListUpdates does not crash; * - result for startProgramListUpdates using a filter with DAB_ENSEMBLE value of the first DAB * program matches the expected result. 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/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp index be6963217d..b6b5206e7f 100644 --- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp +++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp @@ -552,6 +552,11 @@ TEST_P(CameraAidlTest, configureStreamsAvailableOutputs) { stream.rotation = StreamRotation::ROTATION_0; stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap:: ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD; + stream.useCase = ScalerAvailableStreamUseCases:: + ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT; + stream.colorSpace = static_cast( + RequestAvailableColorSpaceProfilesMap:: + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED); std::vector streams = {stream}; StreamConfiguration config; diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp index ce1cbfd29f..6a17453118 100644 --- a/camera/provider/aidl/vts/camera_aidl_test.cpp +++ b/camera/provider/aidl/vts/camera_aidl_test.cpp @@ -45,8 +45,6 @@ using ::aidl::android::hardware::camera::common::TorchModeStatus; using ::aidl::android::hardware::camera::device::CameraMetadata; using ::aidl::android::hardware::camera::device::ICameraDevice; using ::aidl::android::hardware::camera::metadata::CameraMetadataTag; -using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap; -using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap; using ::aidl::android::hardware::camera::metadata::SensorInfoColorFilterArrangement; using ::aidl::android::hardware::camera::metadata::SensorPixelMode; using ::aidl::android::hardware::camera::provider::BnCameraProviderCallback; @@ -122,7 +120,7 @@ void CameraAidlTest::SetUp() { ABinderProcess_startThreadPool(); SpAIBinder cameraProviderBinder = - SpAIBinder(AServiceManager_getService(serviceDescriptor.c_str())); + SpAIBinder(AServiceManager_waitForService(serviceDescriptor.c_str())); ASSERT_NE(cameraProviderBinder.get(), nullptr); std::shared_ptr cameraProvider = @@ -2321,21 +2319,26 @@ void CameraAidlTest::configureStreamUseCaseInternal(const AvailableStream &thres } std::vector streams(1); - streams[0] = {0, - StreamType::OUTPUT, - outputPreviewStreams[0].width, - outputPreviewStreams[0].height, - static_cast(outputPreviewStreams[0].format), - static_cast<::aidl::android::hardware::graphics::common::BufferUsage>( - GRALLOC1_CONSUMER_USAGE_CPU_READ), - Dataspace::UNKNOWN, - StreamRotation::ROTATION_0, - std::string(), - 0, - -1, - {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, - RequestAvailableDynamicRangeProfilesMap:: - ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD}; + streams[0] = { + 0, + StreamType::OUTPUT, + outputPreviewStreams[0].width, + outputPreviewStreams[0].height, + static_cast(outputPreviewStreams[0].format), + static_cast<::aidl::android::hardware::graphics::common::BufferUsage>( + GRALLOC1_CONSUMER_USAGE_CPU_READ), + Dataspace::UNKNOWN, + StreamRotation::ROTATION_0, + std::string(), + 0, + -1, + {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, + RequestAvailableDynamicRangeProfilesMap:: + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, + ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, + static_cast( + RequestAvailableColorSpaceProfilesMap:: + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)}; int32_t streamConfigCounter = 0; CameraMetadata req; @@ -2479,7 +2482,11 @@ void CameraAidlTest::configureSingleStream( /*groupId*/ -1, {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, RequestAvailableDynamicRangeProfilesMap:: - ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD}; + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, + ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, + static_cast( + RequestAvailableColorSpaceProfilesMap:: + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)}; StreamConfiguration config; config.streams = streams; @@ -2810,21 +2817,26 @@ void CameraAidlTest::configurePreviewStreams( std::vector streams(physicalIds.size()); int32_t streamId = 0; for (auto const& physicalId : physicalIds) { - streams[streamId] = {streamId, - StreamType::OUTPUT, - outputPreviewStreams[0].width, - outputPreviewStreams[0].height, - static_cast(outputPreviewStreams[0].format), - static_cast( - GRALLOC1_CONSUMER_USAGE_HWCOMPOSER), - Dataspace::UNKNOWN, - StreamRotation::ROTATION_0, - physicalId, - 0, - -1, - {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, - RequestAvailableDynamicRangeProfilesMap:: - ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD}; + streams[streamId] = { + streamId, + StreamType::OUTPUT, + outputPreviewStreams[0].width, + outputPreviewStreams[0].height, + static_cast(outputPreviewStreams[0].format), + static_cast( + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER), + Dataspace::UNKNOWN, + StreamRotation::ROTATION_0, + physicalId, + 0, + -1, + {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, + RequestAvailableDynamicRangeProfilesMap:: + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, + ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, + static_cast( + RequestAvailableColorSpaceProfilesMap:: + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)}; streamId++; } @@ -2883,7 +2895,8 @@ void CameraAidlTest::configureStreams(const std::string& name, bool* supportsPartialResults, int32_t* partialResultCount, bool* useHalBufManager, std::shared_ptr* outCb, uint32_t streamConfigCounter, bool maxResolution, - RequestAvailableDynamicRangeProfilesMap prof) { + RequestAvailableDynamicRangeProfilesMap dynamicRangeProf, + RequestAvailableColorSpaceProfilesMap colorSpaceProf) { ASSERT_NE(nullptr, session); ASSERT_NE(nullptr, halStreams); ASSERT_NE(nullptr, previewStream); @@ -2965,7 +2978,9 @@ void CameraAidlTest::configureStreams(const std::string& name, -1, {maxResolution ? SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION : SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, - prof}; + dynamicRangeProf, + ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, + static_cast(colorSpaceProf)}; StreamConfiguration config; config.streams = streams; @@ -3416,7 +3431,11 @@ void CameraAidlTest::configureOfflineStillStream( /*groupId*/ 0, {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT}, RequestAvailableDynamicRangeProfilesMap:: - ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD}; + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, + ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, + static_cast( + RequestAvailableColorSpaceProfilesMap:: + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)}; StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE, CameraMetadata()}; @@ -3531,15 +3550,12 @@ void CameraAidlTest::processColorSpaceRequest( Stream previewStream; std::shared_ptr cb; - previewStream.usage = - static_cast( - GRALLOC1_CONSUMER_USAGE_HWCOMPOSER); - previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED); - previewStream.colorSpace = static_cast(colorSpace); + previewStream.usage = static_cast( + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER); configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession, - &previewStream, &halStreams, &supportsPartialResults, - &partialResultCount, &useHalBufManager, &cb, 0, - /*maxResolution*/ false, dynamicRangeProfile); + &previewStream, &halStreams, &supportsPartialResults, &partialResultCount, + &useHalBufManager, &cb, 0, + /*maxResolution*/ false, dynamicRangeProfile, colorSpace); ASSERT_NE(mSession, nullptr); ::aidl::android::hardware::common::fmq::MQDescriptor< diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h index 809af0ac4d..3018d5a70e 100644 --- a/camera/provider/aidl/vts/camera_aidl_test.h +++ b/camera/provider/aidl/vts/camera_aidl_test.h @@ -77,6 +77,9 @@ using ::aidl::android::hardware::camera::device::StreamBuffer; using ::aidl::android::hardware::camera::device::StreamBufferRet; using ::aidl::android::hardware::camera::device::StreamConfiguration; using ::aidl::android::hardware::camera::device::StreamConfigurationMode; +using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap; +using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap; +using ::aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases; using ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination; using ::aidl::android::hardware::camera::provider::ICameraProvider; @@ -205,10 +208,12 @@ class CameraAidlTest : public ::testing::TestWithParam { bool* supportsPartialResults /*out*/, int32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/, std::shared_ptr* outCb /*out*/, uint32_t streamConfigCounter, bool maxResolution, - aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap - prof = ::aidl::android::hardware::camera::metadata:: - RequestAvailableDynamicRangeProfilesMap:: - ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD); + RequestAvailableDynamicRangeProfilesMap dynamicRangeProf = + RequestAvailableDynamicRangeProfilesMap:: + ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, + RequestAvailableColorSpaceProfilesMap colorSpaceProf = + RequestAvailableColorSpaceProfilesMap:: + ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED); void configurePreviewStreams( const std::string& name, const std::shared_ptr& provider, @@ -379,8 +384,7 @@ class CameraAidlTest : public ::testing::TestWithParam { static void get10BitDynamicRangeProfiles( const camera_metadata_t* staticMeta, - std::vector* profiles); + std::vector* profiles); static bool reportsColorSpaces(const camera_metadata_t* staticMeta); @@ -390,17 +394,13 @@ class CameraAidlTest : public ::testing::TestWithParam { RequestAvailableColorSpaceProfilesMap>* profiles); static bool isColorSpaceCompatibleWithDynamicRangeAndPixelFormat( - const camera_metadata_t* staticMeta, - aidl::android::hardware::camera::metadata:: - RequestAvailableColorSpaceProfilesMap colorSpace, - aidl::android::hardware::camera::metadata:: + const camera_metadata_t* staticMeta, RequestAvailableColorSpaceProfilesMap colorSpace, RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile, aidl::android::hardware::graphics::common::PixelFormat pixelFormat); - static const char* getColorSpaceProfileString(aidl::android::hardware::camera::metadata:: - RequestAvailableColorSpaceProfilesMap colorSpace); + static const char* getColorSpaceProfileString(RequestAvailableColorSpaceProfilesMap colorSpace); - static const char* getDynamicRangeProfileString(aidl::android::hardware::camera::metadata:: + static const char* getDynamicRangeProfileString( RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile); static int32_t halFormatToPublicFormat( @@ -411,10 +411,8 @@ class CameraAidlTest : public ::testing::TestWithParam { static Size getMinSize(Size a, Size b); - void processColorSpaceRequest(aidl::android::hardware::camera::metadata:: - RequestAvailableColorSpaceProfilesMap colorSpace, - aidl::android::hardware::camera::metadata:: - RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile); + void processColorSpaceRequest(RequestAvailableColorSpaceProfilesMap colorSpace, + RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile); void processZoomSettingsOverrideRequests( int32_t frameCount, const bool *overrideSequence, const bool *expectedResults); @@ -574,10 +572,8 @@ class CameraAidlTest : public ::testing::TestWithParam { static bool matchDeviceName(const std::string& deviceName, const std::string& providerType, std::string* deviceVersion, std::string* cameraId); - static void verify10BitMetadata( - HandleImporter& importer, const InFlightRequest& request, - aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap - profile); + static void verify10BitMetadata(HandleImporter& importer, const InFlightRequest& request, + RequestAvailableDynamicRangeProfilesMap profile); static void waitForReleaseFence( std::vector& resultOutputBuffers); diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk index d356cf32a2..c2ffb8413b 100644 --- a/compatibility_matrices/Android.mk +++ b/compatibility_matrices/Android.mk @@ -106,9 +106,15 @@ my_system_matrix_deps := \ framework_compatibility_matrix.6.xml \ framework_compatibility_matrix.7.xml \ framework_compatibility_matrix.8.xml \ - framework_compatibility_matrix.9.xml \ framework_compatibility_matrix.device.xml \ +# Only allow the use of the unreleased compatibility matrix when we can use unfrozen +# interfaces (in the `next` release configuration). +ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true) +my_system_matrix_deps += \ + framework_compatibility_matrix.9.xml +endif + my_framework_matrix_deps += \ $(my_system_matrix_deps) diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml index 99dcdbb6ad..905778882a 100644 --- a/compatibility_matrices/compatibility_matrix.8.xml +++ b/compatibility_matrices/compatibility_matrix.8.xml @@ -52,7 +52,7 @@ default - + android.hardware.authsecret 1 @@ -123,7 +123,7 @@ virtual - + android.hardware.biometrics.fingerprint 3 @@ -314,7 +314,7 @@ default - + android.hardware.security.keymint 1-3 @@ -323,7 +323,7 @@ strongbox - + android.hardware.security.keymint 1-3 @@ -532,7 +532,7 @@ SIM[1-9][0-9]* - + android.hardware.security.secureclock 1 @@ -540,7 +540,7 @@ default - + android.hardware.security.sharedsecret 1 @@ -692,7 +692,7 @@ default - + android.hardware.uwb 1 diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml index da318886a5..872099ada6 100644 --- a/compatibility_matrices/compatibility_matrix.9.xml +++ b/compatibility_matrices/compatibility_matrix.9.xml @@ -565,6 +565,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/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp index 88b5de41bb..60360fd596 100644 --- a/graphics/composer/aidl/vts/Android.bp +++ b/graphics/composer/aidl/vts/Android.bp @@ -54,7 +54,6 @@ cc_test { "libgui", "libhidlbase", "libprocessgroup", - "libtinyxml2", "android.hardware.graphics.mapper@2.0", "android.hardware.graphics.mapper@2.1", "android.hardware.graphics.mapper@3.0", diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp index b0472209dc..9b849cc133 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp @@ -31,12 +31,6 @@ #include "RenderEngineVts.h" #include "VtsComposerClient.h" -// tinyxml2 does implicit conversions >:( -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#include -#pragma clang diagnostic pop - namespace aidl::android::hardware::graphics::composer3::vts { namespace { @@ -129,76 +123,6 @@ class GraphicsCompositionTestBase : public ::testing::Test { return {false, graphicBuffer}; } - uint64_t getStableDisplayId(int64_t display) { - const auto& [status, identification] = - mComposerClient->getDisplayIdentificationData(display); - EXPECT_TRUE(status.isOk()); - - if (const auto info = ::android::parseDisplayIdentificationData( - static_cast(identification.port), identification.data)) { - return info->id.value; - } - - return ::android::PhysicalDisplayId::fromPort(static_cast(identification.port)) - .value; - } - - // Gets the per-display XML config - std::unique_ptr getDisplayConfigXml(int64_t display) { - std::stringstream pathBuilder; - pathBuilder << "/vendor/etc/displayconfig/display_id_" << getStableDisplayId(display) - << ".xml"; - const std::string path = pathBuilder.str(); - auto document = std::make_unique(); - const tinyxml2::XMLError error = document->LoadFile(path.c_str()); - if (error == tinyxml2::XML_SUCCESS) { - return document; - } else { - return nullptr; - } - } - - // Gets the max display brightness for this display. - // If the display config xml does not exist, then assume that the display is not well-configured - // enough to provide a display brightness, so return nullopt. - std::optional getMaxDisplayBrightnessNits(int64_t display) { - const auto document = getDisplayConfigXml(display); - if (!document) { - // Assume the device doesn't support display brightness - return std::nullopt; - } - - const auto root = document->RootElement(); - if (!root) { - // If there's somehow no root element, then this isn't a valid config - return std::nullopt; - } - - const auto screenBrightnessMap = root->FirstChildElement("screenBrightnessMap"); - if (!screenBrightnessMap) { - // A valid display config must have a screen brightness map - return std::nullopt; - } - - auto point = screenBrightnessMap->FirstChildElement("point"); - float maxNits = -1.f; - while (point != nullptr) { - const auto nits = point->FirstChildElement("nits"); - if (nits) { - maxNits = std::max(maxNits, nits->FloatText(-1.f)); - } - point = point->NextSiblingElement("point"); - } - - if (maxNits < 0.f) { - // If we got here, then there were no point elements containing a nit value, so this - // config isn't valid - return std::nullopt; - } - - return maxNits; - } - void writeLayers(const std::vector>& layers) { for (const auto& layer : layers) { layer->write(*mWriter); @@ -957,32 +881,6 @@ TEST_P(GraphicsCompositionTest, SetLayerZOrder) { } TEST_P(GraphicsCompositionTest, SetLayerBrightnessDims) { - const auto& [status, capabilities] = - mComposerClient->getDisplayCapabilities(getPrimaryDisplayId()); - ASSERT_TRUE(status.isOk()); - - const bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(), - DisplayCapability::BRIGHTNESS) != capabilities.end(); - - if (!brightnessSupport) { - GTEST_SUCCEED() << "Cannot verify dimming behavior without brightness support"; - return; - } - - const std::optional maxBrightnessNitsOptional = - getMaxDisplayBrightnessNits(getPrimaryDisplayId()); - - ASSERT_TRUE(maxBrightnessNitsOptional.has_value()); - - const float maxBrightnessNits = *maxBrightnessNitsOptional; - - // Preconditions to successfully run are knowing the max brightness and successfully applying - // the max brightness - ASSERT_GT(maxBrightnessNits, 0.f); - mWriter->setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 1.f, maxBrightnessNits); - execute(); - ASSERT_TRUE(mReader.takeErrors().empty()); - for (ColorMode mode : mTestColorModes) { EXPECT_TRUE(mComposerClient ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC) @@ -999,11 +897,14 @@ TEST_P(GraphicsCompositionTest, SetLayerBrightnessDims) { const common::Rect redRect = {0, 0, getDisplayWidth(), getDisplayHeight() / 2}; const common::Rect dimmerRedRect = {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}; + + static constexpr float kMaxBrightnessNits = 300.f; + const auto redLayer = std::make_shared(mComposerClient, getPrimaryDisplayId()); redLayer->setColor(RED); redLayer->setDisplayFrame(redRect); - redLayer->setWhitePointNits(maxBrightnessNits); + redLayer->setWhitePointNits(kMaxBrightnessNits); redLayer->setBrightness(1.f); const auto dimmerRedLayer = @@ -1013,7 +914,7 @@ TEST_P(GraphicsCompositionTest, SetLayerBrightnessDims) { // Intentionally use a small dimming ratio as some implementations may be more likely to // kick into GPU composition to apply dithering when the dimming ratio is high. static constexpr float kDimmingRatio = 0.9f; - dimmerRedLayer->setWhitePointNits(maxBrightnessNits * kDimmingRatio); + dimmerRedLayer->setWhitePointNits(kMaxBrightnessNits * kDimmingRatio); dimmerRedLayer->setBrightness(kDimmingRatio); const std::vector> layers = {redLayer, dimmerRedLayer}; diff --git a/radio/aidl/vts/radio_data_test.cpp b/radio/aidl/vts/radio_data_test.cpp index 0fb2fb404f..f31c254277 100644 --- a/radio/aidl/vts/radio_data_test.cpp +++ b/radio/aidl/vts/radio_data_test.cpp @@ -214,7 +214,8 @@ TEST_P(RadioDataTest, setupDataCall_osAppId) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error, {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW})); - if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0) { + if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0 || + !radioRsp_data->setupDataCallResult.trafficDescriptors[0].osAppId.has_value()) { return; } EXPECT_EQ(trafficDescriptor.osAppId.value().osAppId, diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp index 06bcd1f173..6643c1e7ff 100644 --- a/radio/aidl/vts/radio_network_test.cpp +++ b/radio/aidl/vts/radio_network_test.cpp @@ -119,7 +119,7 @@ TEST_P(RadioNetworkTest, setGetAllowedNetworkTypesBitmap) { RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES})); if (radioRsp_network->rspInfo.error == RadioError::NONE) { // verify we get the value we set - ASSERT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap); + EXPECT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap); } } 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()}; } diff --git a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp index bebad7ca08..738e72cf00 100644 --- a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp +++ b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp @@ -76,18 +76,10 @@ class WifiNanIfaceAidlTest : public testing::TestWithParam { void TearDown() override { stopWifiService(getInstanceName()); } - // Used as a mechanism to inform the test about data/event callbacks. - inline void notify() { - std::unique_lock lock(mtx_); - count_++; - cv_.notify_one(); - } - enum CallbackType { - INVALID = -2, - ANY_CALLBACK = -1, + INVALID = 0, - NOTIFY_CAPABILITIES_RESPONSE = 0, + NOTIFY_CAPABILITIES_RESPONSE = 1, NOTIFY_ENABLE_RESPONSE, NOTIFY_CONFIG_RESPONSE, NOTIFY_DISABLE_RESPONSE, @@ -128,310 +120,278 @@ class WifiNanIfaceAidlTest : public testing::TestWithParam { EVENT_SUSPENSION_MODE_CHANGE, }; + // Used as a mechanism to inform the test about data/event callbacks. + inline void notify(CallbackType callbackType) { + std::unique_lock lock(mtx_); + callback_event_bitmap_ |= (UINT64_C(0x1) << callbackType); + cv_.notify_one(); + } + // Test code calls this function to wait for data/event callback. - // Must set callbackType = INVALID before calling this function. + // Must set callback_event_bitmap_ to 0 before calling this function. inline std::cv_status wait(CallbackType waitForCallbackType) { std::unique_lock lock(mtx_); EXPECT_NE(INVALID, waitForCallbackType); std::cv_status status = std::cv_status::no_timeout; auto now = std::chrono::system_clock::now(); - while (count_ == 0) { + while (!(receivedCallback(waitForCallbackType))) { status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD)); if (status == std::cv_status::timeout) return status; - if (waitForCallbackType != ANY_CALLBACK && callback_type_ != INVALID && - callback_type_ != waitForCallbackType) { - count_--; - } } - count_--; return status; } + inline bool receivedCallback(CallbackType waitForCallbackType) { + return callback_event_bitmap_ & (UINT64_C(0x1) << waitForCallbackType); + } + class WifiNanIfaceEventCallback : public BnWifiNanIfaceEventCallback { public: WifiNanIfaceEventCallback(WifiNanIfaceAidlTest& parent) : parent_(parent){}; ::ndk::ScopedAStatus eventClusterEvent(const NanClusterEventInd& event) override { - parent_.callback_type_ = EVENT_CLUSTER_EVENT; parent_.nan_cluster_event_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_CLUSTER_EVENT); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventDataPathConfirm(const NanDataPathConfirmInd& event) override { - parent_.callback_type_ = EVENT_DATA_PATH_CONFIRM; parent_.nan_data_path_confirm_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_DATA_PATH_CONFIRM); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventDataPathRequest(const NanDataPathRequestInd& event) override { - parent_.callback_type_ = EVENT_DATA_PATH_REQUEST; parent_.nan_data_path_request_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_DATA_PATH_REQUEST); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventDataPathScheduleUpdate( const NanDataPathScheduleUpdateInd& event) override { - parent_.callback_type_ = EVENT_DATA_PATH_SCHEDULE_UPDATE; parent_.nan_data_path_schedule_update_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_DATA_PATH_SCHEDULE_UPDATE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventDataPathTerminated(int32_t ndpInstanceId) override { - parent_.callback_type_ = EVENT_DATA_PATH_TERMINATED; parent_.ndp_instance_id_ = ndpInstanceId; - parent_.notify(); + parent_.notify(EVENT_DATA_PATH_TERMINATED); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventDisabled(const NanStatus& status) override { - parent_.callback_type_ = EVENT_DISABLED; parent_.status_ = status; - parent_.notify(); + parent_.notify(EVENT_DISABLED); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventFollowupReceived(const NanFollowupReceivedInd& event) override { - parent_.callback_type_ = EVENT_FOLLOWUP_RECEIVED; parent_.nan_followup_received_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_FOLLOWUP_RECEIVED); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventMatch(const NanMatchInd& event) override { - parent_.callback_type_ = EVENT_MATCH; parent_.nan_match_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_MATCH); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventMatchExpired(int8_t discoverySessionId, int32_t peerId) override { - parent_.callback_type_ = EVENT_MATCH_EXPIRED; parent_.session_id_ = discoverySessionId; parent_.peer_id_ = peerId; - parent_.notify(); + parent_.notify(EVENT_MATCH_EXPIRED); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventPublishTerminated(int8_t sessionId, const NanStatus& status) override { - parent_.callback_type_ = EVENT_PUBLISH_TERMINATED; parent_.session_id_ = sessionId; parent_.status_ = status; - parent_.notify(); + parent_.notify(EVENT_PUBLISH_TERMINATED); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventSubscribeTerminated(int8_t sessionId, const NanStatus& status) override { - parent_.callback_type_ = EVENT_SUBSCRIBE_TERMINATED; parent_.session_id_ = sessionId; parent_.status_ = status; - parent_.notify(); + parent_.notify(EVENT_SUBSCRIBE_TERMINATED); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventTransmitFollowup(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = EVENT_TRANSMIT_FOLLOWUP; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(EVENT_TRANSMIT_FOLLOWUP); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventPairingConfirm(const NanPairingConfirmInd& event) override { - parent_.callback_type_ = EVENT_PAIRING_CONFIRM; parent_.nan_pairing_confirm_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_PAIRING_CONFIRM); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventPairingRequest(const NanPairingRequestInd& event) override { - parent_.callback_type_ = EVENT_PAIRING_REQUEST; parent_.nan_pairing_request_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_PAIRING_REQUEST); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventBootstrappingConfirm( const NanBootstrappingConfirmInd& event) override { - parent_.callback_type_ = EVENT_BOOTSTRAPPING_CONFIRM; parent_.nan_bootstrapping_confirm_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_BOOTSTRAPPING_CONFIRM); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventBootstrappingRequest( const NanBootstrappingRequestInd& event) override { - parent_.callback_type_ = EVENT_BOOTSTRAPPING_REQUEST; parent_.nan_bootstrapping_request_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_BOOTSTRAPPING_REQUEST); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus eventSuspensionModeChanged( const NanSuspensionModeChangeInd& event) override { - parent_.callback_type_ = EVENT_SUSPENSION_MODE_CHANGE; parent_.nan_suspension_mode_change_ind_ = event; - parent_.notify(); + parent_.notify(EVENT_SUSPENSION_MODE_CHANGE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyCapabilitiesResponse( char16_t id, const NanStatus& status, const NanCapabilities& capabilities) override { - parent_.callback_type_ = NOTIFY_CAPABILITIES_RESPONSE; parent_.id_ = id; parent_.status_ = status; parent_.capabilities_ = capabilities; - parent_.notify(); + parent_.notify(NOTIFY_CAPABILITIES_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyConfigResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_CONFIG_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_CONFIG_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyCreateDataInterfaceResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_CREATE_DATA_INTERFACE_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyDeleteDataInterfaceResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_DELETE_DATA_INTERFACE_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyDisableResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_DISABLE_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_DISABLE_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyEnableResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_ENABLE_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_ENABLE_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyInitiateDataPathResponse(char16_t id, const NanStatus& status, int32_t ndpInstanceId) override { - parent_.callback_type_ = NOTIFY_INITIATE_DATA_PATH_RESPONSE; parent_.id_ = id; parent_.status_ = status; parent_.ndp_instance_id_ = ndpInstanceId; - parent_.notify(); + parent_.notify(NOTIFY_INITIATE_DATA_PATH_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyRespondToDataPathIndicationResponse( char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyStartPublishResponse(char16_t id, const NanStatus& status, int8_t sessionId) override { - parent_.callback_type_ = NOTIFY_START_PUBLISH_RESPONSE; parent_.id_ = id; parent_.status_ = status; parent_.session_id_ = sessionId; - parent_.notify(); + parent_.notify(NOTIFY_START_PUBLISH_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyStartSubscribeResponse(char16_t id, const NanStatus& status, int8_t sessionId) override { - parent_.callback_type_ = NOTIFY_START_SUBSCRIBE_RESPONSE; parent_.id_ = id; parent_.status_ = status; parent_.session_id_ = sessionId; - parent_.notify(); + parent_.notify(NOTIFY_START_SUBSCRIBE_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyStopPublishResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_STOP_PUBLISH_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_STOP_PUBLISH_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyStopSubscribeResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_STOP_SUBSCRIBE_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_STOP_SUBSCRIBE_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyTerminateDataPathResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_TERMINATE_DATA_PATH_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_TERMINATE_DATA_PATH_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifySuspendResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_SUSPEND_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_SUSPEND_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyResumeResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_RESUME_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_RESUME_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyTransmitFollowupResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyInitiatePairingResponse(char16_t id, const NanStatus& status, int32_t pairingInstanceId) override { - parent_.callback_type_ = NOTIFY_INITIATE_PAIRING_RESPONSE; parent_.id_ = id; parent_.status_ = status; parent_.pairing_instance_id_ = pairingInstanceId; - parent_.notify(); + parent_.notify(NOTIFY_INITIATE_PAIRING_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyRespondToPairingIndicationResponse( char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_RESPOND_TO_PAIRING_INDICATION_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_RESPOND_TO_PAIRING_INDICATION_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyInitiateBootstrappingResponse( char16_t id, const NanStatus& status, int32_t bootstrapppingInstanceId) override { - parent_.callback_type_ = NOTIFY_INITIATE_BOOTSTRAPPING_RESPONSE; parent_.id_ = id; parent_.status_ = status; parent_.bootstrappping_instance_id_ = bootstrapppingInstanceId; - parent_.notify(); + parent_.notify(NOTIFY_INITIATE_BOOTSTRAPPING_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyRespondToBootstrappingIndicationResponse( char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_RESPOND_TO_BOOTSTRAPPING_INDICATION_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_RESPOND_TO_BOOTSTRAPPING_INDICATION_RESPONSE); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus notifyTerminatePairingResponse(char16_t id, const NanStatus& status) override { - parent_.callback_type_ = NOTIFY_TERMINATE_PAIRING_RESPONSE; parent_.id_ = id; parent_.status_ = status; - parent_.notify(); + parent_.notify(NOTIFY_TERMINATE_PAIRING_RESPONSE); return ndk::ScopedAStatus::ok(); } @@ -441,7 +401,7 @@ class WifiNanIfaceAidlTest : public testing::TestWithParam { protected: std::shared_ptr wifi_nan_iface_; - CallbackType callback_type_; + uint64_t callback_event_bitmap_; uint16_t id_; uint8_t session_id_; uint32_t ndp_instance_id_; @@ -468,7 +428,6 @@ class WifiNanIfaceAidlTest : public testing::TestWithParam { // synchronization objects std::mutex mtx_; std::condition_variable cv_; - int count_ = 0; }; /* @@ -488,7 +447,7 @@ TEST_P(WifiNanIfaceAidlTest, FailOnIfaceInvalid) { */ TEST_P(WifiNanIfaceAidlTest, EnableRequest_InvalidArgs) { uint16_t inputCmdId = 10; - callback_type_ = INVALID; + callback_event_bitmap_ = 0; NanEnableRequest nanEnableRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; auto status = @@ -498,7 +457,7 @@ TEST_P(WifiNanIfaceAidlTest, EnableRequest_InvalidArgs) { // Wait for a callback. ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE)); - ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callback_type_); + ASSERT_TRUE(receivedCallback(NOTIFY_ENABLE_RESPONSE)); ASSERT_EQ(id_, inputCmdId); ASSERT_EQ(status_.status, NanStatusCode::INVALID_ARGS); } @@ -509,7 +468,7 @@ TEST_P(WifiNanIfaceAidlTest, EnableRequest_InvalidArgs) { */ TEST_P(WifiNanIfaceAidlTest, ConfigRequest_InvalidArgs) { uint16_t inputCmdId = 10; - callback_type_ = INVALID; + callback_event_bitmap_ = 0; NanConfigRequest nanConfigRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; auto status = @@ -520,7 +479,7 @@ TEST_P(WifiNanIfaceAidlTest, ConfigRequest_InvalidArgs) { // Wait for a callback. ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE)); - ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callback_type_); + ASSERT_TRUE(receivedCallback(NOTIFY_CONFIG_RESPONSE)); ASSERT_EQ(id_, inputCmdId); ASSERT_EQ(status_.status, NanStatusCode::INVALID_ARGS); } @@ -561,12 +520,12 @@ TEST_P(WifiNanIfaceAidlTest, ConfigRequest_InvalidShimArgs) { */ TEST_P(WifiNanIfaceAidlTest, NotifyCapabilitiesResponse) { uint16_t inputCmdId = 10; - callback_type_ = INVALID; + callback_event_bitmap_ = 0; EXPECT_TRUE(wifi_nan_iface_->getCapabilitiesRequest(inputCmdId).isOk()); // Wait for a callback. ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE)); - ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callback_type_); + ASSERT_TRUE(receivedCallback(NOTIFY_CAPABILITIES_RESPONSE)); ASSERT_EQ(id_, inputCmdId); ASSERT_EQ(status_.status, NanStatusCode::SUCCESS); @@ -654,14 +613,14 @@ TEST_P(WifiNanIfaceAidlTest, StartPublishRequest) { nanConfigRequestSupp.numberOfSpatialStreamsInDiscovery = 0; nanConfigRequestSupp.enableDiscoveryWindowEarlyTermination = false; - callback_type_ = INVALID; + callback_event_bitmap_ = 0; auto status = wifi_nan_iface_->enableRequest(inputCmdId, req, nanConfigRequestSupp); if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) { ASSERT_TRUE(status.isOk()); // Wait for a callback. ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE)); - ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callback_type_); + ASSERT_TRUE(receivedCallback(NOTIFY_ENABLE_RESPONSE)); ASSERT_EQ(id_, inputCmdId); ASSERT_EQ(status_.status, NanStatusCode::SUCCESS); } @@ -688,7 +647,7 @@ TEST_P(WifiNanIfaceAidlTest, StartPublishRequest) { // Wait for a callback. ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_START_PUBLISH_RESPONSE)); - ASSERT_EQ(NOTIFY_START_PUBLISH_RESPONSE, callback_type_); + ASSERT_TRUE(receivedCallback(NOTIFY_START_PUBLISH_RESPONSE)); ASSERT_EQ(id_, inputCmdId + 1); ASSERT_EQ(status_.status, NanStatusCode::SUCCESS); } @@ -699,7 +658,7 @@ TEST_P(WifiNanIfaceAidlTest, StartPublishRequest) { */ TEST_P(WifiNanIfaceAidlTest, RespondToDataPathIndicationRequest_InvalidArgs) { uint16_t inputCmdId = 10; - callback_type_ = INVALID; + callback_event_bitmap_ = 0; NanRespondToDataPathIndicationRequest nanRespondToDataPathIndicationRequest = {}; nanRespondToDataPathIndicationRequest.ifaceName = "AwareInterfaceNameTooLong"; auto status = wifi_nan_iface_->respondToDataPathIndicationRequest( @@ -716,7 +675,7 @@ TEST_P(WifiNanIfaceAidlTest, RespondToDataPathIndicationRequest_InvalidArgs) { */ TEST_P(WifiNanIfaceAidlTest, InitiateDataPathRequest_InvalidArgs) { uint16_t inputCmdId = 10; - callback_type_ = INVALID; + callback_event_bitmap_ = 0; NanInitiateDataPathRequest nanInitiateDataPathRequest = {}; nanInitiateDataPathRequest.ifaceName = "AwareInterfaceNameTooLong"; auto status = wifi_nan_iface_->initiateDataPathRequest(inputCmdId, nanInitiateDataPathRequest); diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp index f12d873f0c..1ea1237a2d 100644 --- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp +++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include @@ -68,6 +69,50 @@ class WifiStaIfaceAidlTest : public testing::TestWithParam { std::shared_ptr wifi_sta_iface_; + // Checks if the MdnsOffloadManagerService is installed. + bool isMdnsOffloadServicePresent() { + int status = + // --query-flags MATCH_SYSTEM_ONLY(1048576) will only return matched service + // installed on system or system_ext partition. The MdnsOffloadManagerService should + // be installed on system_ext partition. + // NOLINTNEXTLINE(cert-env33-c) + system("pm query-services --query-flags 1048576" + " com.android.tv.mdnsoffloadmanager/" + "com.android.tv.mdnsoffloadmanager.MdnsOffloadManagerService" + " | egrep -q mdnsoffloadmanager"); + return status == 0; + } + + // Detected panel TV device by using ro.oem.key1 property. + // https://docs.partner.android.com/tv/build/platform/props-vars/ro-oem-key1 + bool isPanelTvDevice() { + const std::string oem_key1 = getPropertyString("ro.oem.key1"); + if (oem_key1.size() < 9) { + return false; + } + if (oem_key1.substr(0, 3) != "ATV") { + return false; + } + const std::string psz_string = oem_key1.substr(6, 3); + // If PSZ string contains non digit, then it is not a panel TV device. + for (char ch : psz_string) { + if (!isdigit(ch)) { + return false; + } + } + // If PSZ is "000", then it is not a panel TV device. + if (psz_string == "000") { + return false; + } + return true; + } + + std::string getPropertyString(const char* property_name) { + char property_string_raw_bytes[PROPERTY_VALUE_MAX] = {}; + int len = property_get(property_name, property_string_raw_bytes, ""); + return std::string(property_string_raw_bytes, len); + } + private: const char* getInstanceName() { return GetParam().c_str(); } }; @@ -99,6 +144,11 @@ TEST_P(WifiStaIfaceAidlTest, GetFeatureSet) { */ // @VsrTest = 5.3.12 TEST_P(WifiStaIfaceAidlTest, CheckApfIsSupported) { + // Flat panel TV devices that support MDNS offload do not have to implement APF if the WiFi + // chipset does not have sufficient RAM to do so. + if (isPanelTvDevice() && isMdnsOffloadServicePresent()) { + GTEST_SKIP() << "Panel TV supports mDNS offload. It is not required to support APF"; + } int vendor_api_level = property_get_int32("ro.vendor.api_level", 0); // Before VSR 14, APF support is optional. if (vendor_api_level < __ANDROID_API_U__) { diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp index 3ae9b390c9..4c452fbd86 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp @@ -41,10 +41,9 @@ using ::android::hardware::wifi::V1_0::IWifiChip; using ::android::wifi_system::HostapdManager; using ::android::wifi_system::SupplicantManager; -namespace { // Helper function to initialize the driver and firmware to AP mode // using the vendor HAL HIDL interface. -void initilializeDriverAndFirmware(const std::string& wifi_instance_name) { +void initializeDriverAndFirmware(const std::string& wifi_instance_name) { if (getWifi(wifi_instance_name) != nullptr) { sp wifi_chip = getWifiChip(wifi_instance_name); ChipModeId mode_id; @@ -57,21 +56,20 @@ void initilializeDriverAndFirmware(const std::string& wifi_instance_name) { // Helper function to deinitialize the driver and firmware // using the vendor HAL HIDL interface. -void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) { +void deInitializeDriverAndFirmware(const std::string& wifi_instance_name) { if (getWifi(wifi_instance_name) != nullptr) { stopWifi(wifi_instance_name); } else { LOG(WARNING) << __func__ << ": Vendor HAL not supported"; } } -} // namespace void stopSupplicantIfNeeded(const std::string& instance_name) { SupplicantManager supplicant_manager; if (supplicant_manager.IsSupplicantRunning()) { LOG(INFO) << "Supplicant is running, stop supplicant first."; ASSERT_TRUE(supplicant_manager.StopSupplicant()); - deInitilializeDriverAndFirmware(instance_name); + deInitializeDriverAndFirmware(instance_name); ASSERT_FALSE(supplicant_manager.IsSupplicantRunning()); } } @@ -80,13 +78,13 @@ void stopHostapd(const std::string& instance_name) { HostapdManager hostapd_manager; ASSERT_TRUE(hostapd_manager.StopHostapd()); - deInitilializeDriverAndFirmware(instance_name); + deInitializeDriverAndFirmware(instance_name); } void startHostapdAndWaitForHidlService( const std::string& wifi_instance_name, const std::string& hostapd_instance_name) { - initilializeDriverAndFirmware(wifi_instance_name); + initializeDriverAndFirmware(wifi_instance_name); HostapdManager hostapd_manager; ASSERT_TRUE(hostapd_manager.StartHostapd()); diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h index ea7c1128e8..aa34c9a98f 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h @@ -36,5 +36,9 @@ void startHostapdAndWaitForHidlService( bool is_1_1(const android::sp& hostapd); +// Used to initialize/deinitialize the driver and firmware at the +// beginning and end of each test. +void initializeDriverAndFirmware(const std::string& wifi_instance_name); +void deInitializeDriverAndFirmware(const std::string& wifi_instance_name); #endif /* HOSTAPD_HIDL_TEST_UTILS_H */ diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp index 33318a4520..ff35056076 100644 --- a/wifi/hostapd/aidl/vts/functional/Android.bp +++ b/wifi/hostapd/aidl/vts/functional/Android.bp @@ -37,6 +37,7 @@ cc_test { "android.hardware.wifi@1.5", "android.hardware.wifi@1.6", "android.hardware.wifi-V1-ndk", + "libwifi-system", "libwifi-system-iface", "VtsHalWifiTargetTestUtil", ], diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp index efd1538c7b..137537d18b 100644 --- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp +++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp @@ -32,6 +32,7 @@ #include #include +#include "hostapd_test_utils.h" #include "wifi_aidl_test_utils.h" using aidl::android::hardware::wifi::hostapd::BandMask; @@ -56,10 +57,7 @@ const std::string kInvalidMaxPassphrase = const int kIfaceChannel = 6; const int kIfaceInvalidChannel = 567; const std::vector kTestZeroMacAddr(6, 0x0); -const Ieee80211ReasonCode kTestDisconnectReasonCode = - Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED; -const std::string kWifiAidlInstanceNameStr = std::string() + IWifi::descriptor + "/default"; -const char* kWifiAidlInstanceName = kWifiAidlInstanceNameStr.c_str(); +const Ieee80211ReasonCode kTestDisconnectReasonCode = Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED; inline BandMask operator|(BandMask a, BandMask b) { return static_cast(static_cast(a) | @@ -70,10 +68,13 @@ inline BandMask operator|(BandMask a, BandMask b) { class HostapdAidl : public testing::TestWithParam { public: virtual void SetUp() override { - hostapd = IHostapd::fromBinder(ndk::SpAIBinder( - AServiceManager_waitForService(GetParam().c_str()))); + disableHalsAndFramework(); + initializeHostapdAndVendorHal(GetParam()); + + hostapd = getHostapd(GetParam()); ASSERT_NE(hostapd, nullptr); EXPECT_TRUE(hostapd->setDebugParams(DebugLevel::EXCESSIVE).isOk()); + isAcsSupport = testing::checkSubstringInCommandOutput( "/system/bin/cmd wifi get-softap-supported-features", "wifi_softap_acs_supported"); @@ -81,81 +82,23 @@ class HostapdAidl : public testing::TestWithParam { "/system/bin/cmd wifi get-softap-supported-features", "wifi_softap_wpa3_sae_supported"); isBridgedSupport = testing::checkSubstringInCommandOutput( - "/system/bin/cmd wifi get-softap-supported-features", - "wifi_softap_bridged_ap_supported"); - if (!isAidlServiceAvailable(kWifiAidlInstanceName)) { - const std::vector instances = android::hardware::getAllHalInstanceNames( - ::android::hardware::wifi::V1_0::IWifi::descriptor); - EXPECT_NE(0, instances.size()); - wifiHidlInstanceName = instances[0]; - } + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_bridged_ap_supported"); } virtual void TearDown() override { - stopVendorHal(); hostapd->terminate(); // Wait 3 seconds to allow terminate to complete sleep(3); + stopHostapdAndVendorHal(); + startWifiFramework(); } std::shared_ptr hostapd; - std::string wifiHidlInstanceName; bool isAcsSupport; bool isWpa3SaeSupport; bool isBridgedSupport; - void stopVendorHal() { - if (isAidlServiceAvailable(kWifiAidlInstanceName)) { - // HIDL and AIDL versions of getWifi() take different arguments - // i.e. const char* vs string - if (getWifi(kWifiAidlInstanceName) != nullptr) { - stopWifiService(kWifiAidlInstanceName); - } - } else { - if (getWifi(wifiHidlInstanceName) != nullptr) { - stopWifi(wifiHidlInstanceName); - } - } - } - - std::string setupApIfaceAndGetName(bool isBridged) { - if (isAidlServiceAvailable(kWifiAidlInstanceName)) { - return setupApIfaceAndGetNameAidl(isBridged); - } else { - return setupApIfaceAndGetNameHidl(isBridged); - } - } - - std::string setupApIfaceAndGetNameAidl(bool isBridged) { - std::shared_ptr wifi_ap_iface; - if (isBridged) { - wifi_ap_iface = getBridgedWifiApIface(kWifiAidlInstanceName); - } else { - wifi_ap_iface = getWifiApIface(kWifiAidlInstanceName); - } - EXPECT_NE(nullptr, wifi_ap_iface.get()); - - std::string ap_iface_name; - auto status = wifi_ap_iface->getName(&ap_iface_name); - EXPECT_TRUE(status.isOk()); - return ap_iface_name; - } - - std::string setupApIfaceAndGetNameHidl(bool isBridged) { - android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface; - if (isBridged) { - wifi_ap_iface = getBridgedWifiApIface_1_6(wifiHidlInstanceName); - } else { - wifi_ap_iface = getWifiApIface_1_5(wifiHidlInstanceName); - } - EXPECT_NE(nullptr, wifi_ap_iface.get()); - - const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName); - EXPECT_EQ(android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS, - status_and_name.first.code); - return status_and_name.second; - } - IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) { IfaceParams iface_params; ChannelParams channelParams; diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h new file mode 100644 index 0000000000..93540b2671 --- /dev/null +++ b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 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. + */ + +#pragma once + +#include +#include + +#include "wifi_aidl_test_utils.h" + +namespace { + +const std::string kWifiInstanceNameStr = std::string() + IWifi::descriptor + "/default"; +const char* kWifiInstanceName = kWifiInstanceNameStr.c_str(); + +} // namespace + +namespace HostapdAidlTestUtils { + +bool useAidlService() { + return isAidlServiceAvailable(kWifiInstanceName); +} + +void startAndConfigureVendorHal() { + if (getWifi(kWifiInstanceName) != nullptr) { + std::shared_ptr wifi_chip = getWifiChip(kWifiInstanceName); + int mode_id; + EXPECT_TRUE(configureChipToSupportConcurrencyType(wifi_chip, IfaceConcurrencyType::AP, + &mode_id)); + } else { + LOG(ERROR) << "Unable to initialize Vendor HAL"; + } +} + +void stopVendorHal() { + if (getWifi(kWifiInstanceName) != nullptr) { + stopWifiService(kWifiInstanceName); + } else { + LOG(ERROR) << "Unable to stop Vendor HAL"; + } +} + +std::string setupApIfaceAndGetName(bool isBridged) { + std::shared_ptr wifi_ap_iface; + if (isBridged) { + wifi_ap_iface = getBridgedWifiApIface(kWifiInstanceName); + } else { + wifi_ap_iface = getWifiApIface(kWifiInstanceName); + } + + EXPECT_TRUE(wifi_ap_iface.get() != nullptr); + if (!wifi_ap_iface.get()) { + LOG(ERROR) << "Unable to create iface. isBridged=" << isBridged; + return ""; + } + + std::string ap_iface_name; + auto status = wifi_ap_iface->getName(&ap_iface_name); + EXPECT_TRUE(status.isOk()); + if (!status.isOk()) { + LOG(ERROR) << "Unable to retrieve iface name. isBridged=" << isBridged; + return ""; + } + return ap_iface_name; +} + +} // namespace HostapdAidlTestUtils diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h new file mode 100644 index 0000000000..fb59dc2858 --- /dev/null +++ b/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 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. + */ + +#pragma once + +#include + +#include "hostapd_hidl_test_utils.h" +#include "wifi_hidl_test_utils.h" + +using ::android::hardware::wifi::V1_0::WifiStatus; + +namespace { + +std::string getWifiInstanceName() { + const std::vector instances = android::hardware::getAllHalInstanceNames( + ::android::hardware::wifi::V1_0::IWifi::descriptor); + EXPECT_NE(0, instances.size()); + return instances.size() != 0 ? instances[0] : ""; +} + +} // namespace + +namespace HostapdLegacyTestUtils { + +void startAndConfigureVendorHal() { + initializeDriverAndFirmware(getWifiInstanceName()); +} + +void stopVendorHal() { + deInitializeDriverAndFirmware(getWifiInstanceName()); +} + +std::string setupApIfaceAndGetName(bool isBridged) { + android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface; + if (isBridged) { + wifi_ap_iface = getBridgedWifiApIface_1_6(getWifiInstanceName()); + } else { + wifi_ap_iface = getWifiApIface_1_5(getWifiInstanceName()); + } + + EXPECT_TRUE(wifi_ap_iface.get() != nullptr); + if (!wifi_ap_iface.get()) { + LOG(ERROR) << "Unable to create iface. isBridged=" << isBridged; + return ""; + } + + const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName); + EXPECT_TRUE(status_and_name.first.code == + android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS); + if (status_and_name.first.code != android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS) { + LOG(ERROR) << "Unable to retrieve iface name. isBridged=" << isBridged; + return ""; + } + return status_and_name.second; +} + +} // namespace HostapdLegacyTestUtils diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h new file mode 100644 index 0000000000..50a38d33fd --- /dev/null +++ b/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2023 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include "hostapd_aidl_test_utils.h" +#include "hostapd_legacy_test_utils.h" + +using aidl::android::hardware::wifi::hostapd::IHostapd; +using android::wifi_system::HostapdManager; +using android::wifi_system::SupplicantManager; + +namespace { + +void startAndConfigureVendorHal() { + if (HostapdAidlTestUtils::useAidlService()) { + HostapdAidlTestUtils::startAndConfigureVendorHal(); + } else { + HostapdLegacyTestUtils::startAndConfigureVendorHal(); + } +} + +void stopVendorHal() { + if (HostapdAidlTestUtils::useAidlService()) { + HostapdAidlTestUtils::stopVendorHal(); + } else { + HostapdLegacyTestUtils::stopVendorHal(); + } +} + +void stopHostapd() { + HostapdManager hostapd_manager; + ASSERT_TRUE(hostapd_manager.StopHostapd()); +} + +void waitForSupplicantState(bool enable) { + SupplicantManager supplicant_manager; + int count = 50; // wait at most 5 seconds + while (count-- > 0) { + if (supplicant_manager.IsSupplicantRunning() == enable) { + return; + } + usleep(100000); // 100 ms + } + LOG(ERROR) << "Unable to " << (enable ? "start" : "stop") << " supplicant"; +} + +void toggleWifiFrameworkAndScan(bool enable) { + if (enable) { + std::system("svc wifi enable"); + std::system("cmd wifi set-scan-always-available enabled"); + waitForSupplicantState(true); + } else { + std::system("svc wifi disable"); + std::system("cmd wifi set-scan-always-available disabled"); + waitForSupplicantState(false); + } +} + +} // namespace + +std::shared_ptr getHostapd(const std::string& hostapd_instance_name) { + return IHostapd::fromBinder( + ndk::SpAIBinder(AServiceManager_waitForService(hostapd_instance_name.c_str()))); +} + +/** + * Disable the Wifi framework, hostapd, and vendor HAL. + * + * Note: The framework should be disabled to avoid having + * any other clients to the HALs during testing. + */ +void disableHalsAndFramework() { + toggleWifiFrameworkAndScan(false); + stopHostapd(); + stopVendorHal(); + + // Wait for the services to stop. + sleep(3); +} + +void initializeHostapdAndVendorHal(const std::string& hostapd_instance_name) { + startAndConfigureVendorHal(); + HostapdManager hostapd_manager; + ASSERT_TRUE(hostapd_manager.StartHostapd()); + getHostapd(hostapd_instance_name); +} + +void stopHostapdAndVendorHal() { + stopHostapd(); + stopVendorHal(); +} + +void startWifiFramework() { + toggleWifiFrameworkAndScan(true); +} + +std::string setupApIfaceAndGetName(bool isBridged) { + if (HostapdAidlTestUtils::useAidlService()) { + return HostapdAidlTestUtils::setupApIfaceAndGetName(isBridged); + } else { + return HostapdLegacyTestUtils::setupApIfaceAndGetName(isBridged); + } +}