Implement Envelope Effect Limitations APIs

Implement APIs to support envelope effect limits in VibratorHalWrapper.

Bug: 347034419
Flag: android.os.vibrator.normalized_pwle_effects
Test: libvibratorservice_test
Change-Id: I3d45f09740754b5e120bae2ecffa9d150e66e85d
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 3d8124b..4ac1618 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -96,6 +96,17 @@
     if (mInfoCache.mMaxAmplitudes.isFailed()) {
         mInfoCache.mMaxAmplitudes = getMaxAmplitudesInternal();
     }
+    if (mInfoCache.mMaxEnvelopeEffectSize.isFailed()) {
+        mInfoCache.mMaxEnvelopeEffectSize = getMaxEnvelopeEffectSizeInternal();
+    }
+    if (mInfoCache.mMinEnvelopeEffectControlPointDuration.isFailed()) {
+        mInfoCache.mMinEnvelopeEffectControlPointDuration =
+                getMinEnvelopeEffectControlPointDurationInternal();
+    }
+    if (mInfoCache.mMaxEnvelopeEffectControlPointDuration.isFailed()) {
+        mInfoCache.mMaxEnvelopeEffectControlPointDuration =
+                getMaxEnvelopeEffectControlPointDurationInternal();
+    }
     return mInfoCache.get();
 }
 
@@ -210,6 +221,23 @@
     ALOGV("Skipped getMaxAmplitudes because it's not available in Vibrator HAL");
     return HalResult<std::vector<float>>::unsupported();
 }
+HalResult<int32_t> HalWrapper::getMaxEnvelopeEffectSizeInternal() {
+    ALOGV("Skipped getMaxEnvelopeEffectSizeInternal because it's not available "
+          "in Vibrator HAL");
+    return HalResult<int32_t>::unsupported();
+}
+
+HalResult<milliseconds> HalWrapper::getMinEnvelopeEffectControlPointDurationInternal() {
+    ALOGV("Skipped getMinEnvelopeEffectControlPointDurationInternal because it's not "
+          "available in Vibrator HAL");
+    return HalResult<milliseconds>::unsupported();
+}
+
+HalResult<milliseconds> HalWrapper::getMaxEnvelopeEffectControlPointDurationInternal() {
+    ALOGV("Skipped getMaxEnvelopeEffectControlPointDurationInternal because it's not "
+          "available in Vibrator HAL");
+    return HalResult<milliseconds>::unsupported();
+}
 
 // -------------------------------------------------------------------------------------------------
 
@@ -441,6 +469,24 @@
     return HalResultFactory::fromStatus<std::vector<float>>(std::move(status), amplitudes);
 }
 
+HalResult<int32_t> AidlHalWrapper::getMaxEnvelopeEffectSizeInternal() {
+    int32_t size = 0;
+    auto status = getHal()->getPwleV2CompositionSizeMax(&size);
+    return HalResultFactory::fromStatus<int32_t>(std::move(status), size);
+}
+
+HalResult<milliseconds> AidlHalWrapper::getMinEnvelopeEffectControlPointDurationInternal() {
+    int32_t durationMs = 0;
+    auto status = getHal()->getPwleV2PrimitiveDurationMinMillis(&durationMs);
+    return HalResultFactory::fromStatus<milliseconds>(std::move(status), milliseconds(durationMs));
+}
+
+HalResult<milliseconds> AidlHalWrapper::getMaxEnvelopeEffectControlPointDurationInternal() {
+    int32_t durationMs = 0;
+    auto status = getHal()->getPwleV2PrimitiveDurationMaxMillis(&durationMs);
+    return HalResultFactory::fromStatus<milliseconds>(std::move(status), milliseconds(durationMs));
+}
+
 std::shared_ptr<Aidl::IVibrator> AidlHalWrapper::getHal() {
     std::lock_guard<std::mutex> lock(mHandleMutex);
     return mHandle;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index ae0d9ab..4938b15 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -258,6 +258,9 @@
     const HalResult<float> frequencyResolution;
     const HalResult<float> qFactor;
     const HalResult<std::vector<float>> maxAmplitudes;
+    const HalResult<int32_t> maxEnvelopeEffectSize;
+    const HalResult<std::chrono::milliseconds> minEnvelopeEffectControlPointDuration;
+    const HalResult<std::chrono::milliseconds> maxEnvelopeEffectControlPointDuration;
 
     void logFailures() const {
         logFailure<Capabilities>(capabilities, "getCapabilities");
@@ -276,6 +279,11 @@
         logFailure<float>(frequencyResolution, "getFrequencyResolution");
         logFailure<float>(qFactor, "getQFactor");
         logFailure<std::vector<float>>(maxAmplitudes, "getMaxAmplitudes");
+        logFailure<int32_t>(maxEnvelopeEffectSize, "getMaxEnvelopeEffectSize");
+        logFailure<std::chrono::milliseconds>(minEnvelopeEffectControlPointDuration,
+                                              "getMinEnvelopeEffectControlPointDuration");
+        logFailure<std::chrono::milliseconds>(maxEnvelopeEffectControlPointDuration,
+                                              "getMaxEnvelopeEffectControlPointDuration");
     }
 
     bool shouldRetry() const {
@@ -285,7 +293,10 @@
                 pwlePrimitiveDurationMax.shouldRetry() || compositionSizeMax.shouldRetry() ||
                 pwleSizeMax.shouldRetry() || minFrequency.shouldRetry() ||
                 resonantFrequency.shouldRetry() || frequencyResolution.shouldRetry() ||
-                qFactor.shouldRetry() || maxAmplitudes.shouldRetry();
+                qFactor.shouldRetry() || maxAmplitudes.shouldRetry() ||
+                maxEnvelopeEffectSize.shouldRetry() ||
+                minEnvelopeEffectControlPointDuration.shouldRetry() ||
+                maxEnvelopeEffectControlPointDuration.shouldRetry();
     }
 
 private:
@@ -313,7 +324,10 @@
                 mResonantFrequency,
                 mFrequencyResolution,
                 mQFactor,
-                mMaxAmplitudes};
+                mMaxAmplitudes,
+                mMaxEnvelopeEffectSize,
+                mMinEnvelopeEffectControlPointDuration,
+                mMaxEnvelopeEffectControlPointDuration};
     }
 
 private:
@@ -340,6 +354,11 @@
     HalResult<float> mQFactor = HalResult<float>::transactionFailed(MSG);
     HalResult<std::vector<float>> mMaxAmplitudes =
             HalResult<std::vector<float>>::transactionFailed(MSG);
+    HalResult<int32_t> mMaxEnvelopeEffectSize = HalResult<int>::transactionFailed(MSG);
+    HalResult<std::chrono::milliseconds> mMinEnvelopeEffectControlPointDuration =
+            HalResult<std::chrono::milliseconds>::transactionFailed(MSG);
+    HalResult<std::chrono::milliseconds> mMaxEnvelopeEffectControlPointDuration =
+            HalResult<std::chrono::milliseconds>::transactionFailed(MSG);
 
     friend class HalWrapper;
 };
@@ -420,6 +439,9 @@
     virtual HalResult<float> getFrequencyResolutionInternal();
     virtual HalResult<float> getQFactorInternal();
     virtual HalResult<std::vector<float>> getMaxAmplitudesInternal();
+    virtual HalResult<int32_t> getMaxEnvelopeEffectSizeInternal();
+    virtual HalResult<std::chrono::milliseconds> getMinEnvelopeEffectControlPointDurationInternal();
+    virtual HalResult<std::chrono::milliseconds> getMaxEnvelopeEffectControlPointDurationInternal();
 
 private:
     std::mutex mInfoMutex;
@@ -495,6 +517,13 @@
     HalResult<float> getFrequencyResolutionInternal() override final;
     HalResult<float> getQFactorInternal() override final;
     HalResult<std::vector<float>> getMaxAmplitudesInternal() override final;
+    HalResult<int32_t> getMaxEnvelopeEffectSizeInternal() override final;
+
+    HalResult<std::chrono::milliseconds> getMinEnvelopeEffectControlPointDurationInternal()
+            override final;
+
+    HalResult<std::chrono::milliseconds> getMaxEnvelopeEffectControlPointDurationInternal()
+            override final;
 
 private:
     const reconnect_fn mReconnectFn;
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index ba7e1f0..17f384d 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -235,6 +235,9 @@
     constexpr int32_t PWLE_SIZE_MAX = 20;
     constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
     constexpr int32_t PWLE_DURATION_MAX = 200;
+    constexpr int32_t PWLE_V2_COMPOSITION_SIZE_MAX = 16;
+    constexpr int32_t PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS = 20;
+    constexpr int32_t PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS = 1000;
     std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
     std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
     std::vector<Braking> supportedBraking = {Braking::CLAB};
@@ -305,6 +308,21 @@
             .Times(Exactly(2))
             .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
             .WillOnce(DoAll(SetArgPointee<0>(amplitudes), Return(ndk::ScopedAStatus::ok())));
+    EXPECT_CALL(*mMockHal.get(), getPwleV2CompositionSizeMax(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+            .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_COMPOSITION_SIZE_MAX),
+                            Return(ndk::ScopedAStatus::ok())));
+    EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMinMillis(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+            .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
+                            Return(ndk::ScopedAStatus::ok())));
+    EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMaxMillis(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+            .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
+                            Return(ndk::ScopedAStatus::ok())));
 
     vibrator::Info failed = mWrapper->getInfo();
     ASSERT_TRUE(failed.capabilities.isFailed());
@@ -321,6 +339,9 @@
     ASSERT_TRUE(failed.frequencyResolution.isFailed());
     ASSERT_TRUE(failed.qFactor.isFailed());
     ASSERT_TRUE(failed.maxAmplitudes.isFailed());
+    ASSERT_TRUE(failed.maxEnvelopeEffectSize.isFailed());
+    ASSERT_TRUE(failed.minEnvelopeEffectControlPointDuration.isFailed());
+    ASSERT_TRUE(failed.maxEnvelopeEffectControlPointDuration.isFailed());
 
     vibrator::Info successful = mWrapper->getInfo();
     ASSERT_EQ(vibrator::Capabilities::ON_CALLBACK, successful.capabilities.value());
@@ -338,6 +359,11 @@
     ASSERT_EQ(F_RESOLUTION, successful.frequencyResolution.value());
     ASSERT_EQ(Q_FACTOR, successful.qFactor.value());
     ASSERT_EQ(amplitudes, successful.maxAmplitudes.value());
+    ASSERT_EQ(PWLE_V2_COMPOSITION_SIZE_MAX, successful.maxEnvelopeEffectSize.value());
+    ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
+              successful.minEnvelopeEffectControlPointDuration.value());
+    ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
+              successful.maxEnvelopeEffectControlPointDuration.value());
 }
 
 TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
@@ -347,6 +373,9 @@
     constexpr int32_t PWLE_SIZE_MAX = 20;
     constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
     constexpr int32_t PWLE_DURATION_MAX = 200;
+    constexpr int32_t PWLE_V2_COMPOSITION_SIZE_MAX = 16;
+    constexpr int32_t PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS = 20;
+    constexpr int32_t PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS = 1000;
     std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
 
     EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
@@ -391,6 +420,18 @@
     EXPECT_CALL(*mMockHal.get(), getSupportedBraking(_))
             .Times(Exactly(1))
             .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
+    EXPECT_CALL(*mMockHal.get(), getPwleV2CompositionSizeMax(_))
+            .Times(Exactly(1))
+            .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_COMPOSITION_SIZE_MAX),
+                            Return(ndk::ScopedAStatus::ok())));
+    EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMinMillis(_))
+            .Times(Exactly(1))
+            .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
+                            Return(ndk::ScopedAStatus::ok())));
+    EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMaxMillis(_))
+            .Times(Exactly(1))
+            .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
+                            Return(ndk::ScopedAStatus::ok())));
 
     std::vector<std::thread> threads;
     for (int i = 0; i < 10; i++) {
@@ -414,6 +455,11 @@
     ASSERT_TRUE(info.frequencyResolution.isUnsupported());
     ASSERT_TRUE(info.qFactor.isUnsupported());
     ASSERT_TRUE(info.maxAmplitudes.isUnsupported());
+    ASSERT_EQ(PWLE_V2_COMPOSITION_SIZE_MAX, info.maxEnvelopeEffectSize.value());
+    ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
+              info.minEnvelopeEffectControlPointDuration.value());
+    ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
+              info.maxEnvelopeEffectControlPointDuration.value());
 }
 
 TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithCallbackSupport) {
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
index 83430d7..a09ddec 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
@@ -220,6 +220,9 @@
     ASSERT_TRUE(info.frequencyResolution.isUnsupported());
     ASSERT_TRUE(info.qFactor.isUnsupported());
     ASSERT_TRUE(info.maxAmplitudes.isUnsupported());
+    ASSERT_TRUE(info.maxEnvelopeEffectSize.isUnsupported());
+    ASSERT_TRUE(info.minEnvelopeEffectControlPointDuration.isUnsupported());
+    ASSERT_TRUE(info.maxEnvelopeEffectControlPointDuration.isUnsupported());
 }
 
 TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoWithoutAmplitudeControl) {
@@ -253,6 +256,9 @@
     ASSERT_TRUE(info.frequencyResolution.isUnsupported());
     ASSERT_TRUE(info.qFactor.isUnsupported());
     ASSERT_TRUE(info.maxAmplitudes.isUnsupported());
+    ASSERT_TRUE(info.maxEnvelopeEffectSize.isUnsupported());
+    ASSERT_TRUE(info.minEnvelopeEffectControlPointDuration.isUnsupported());
+    ASSERT_TRUE(info.maxEnvelopeEffectControlPointDuration.isUnsupported());
 }
 
 TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformEffect) {