diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl new file mode 100644 index 0000000000..de0bdb57ff --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable CompositePwleV2 { + android.hardware.vibrator.PwleV2Primitive[] pwlePrimitives; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl similarity index 97% rename from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl rename to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl index a5eda52bc7..e6743f9190 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl @@ -33,7 +33,7 @@ package android.hardware.vibrator; @VintfStability -parcelable PwleV2OutputMapEntry { +parcelable FrequencyAccelerationMapEntry { float frequencyHz; float maxOutputAccelerationGs; } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl index 0dcc657955..9fad9522e5 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl @@ -51,19 +51,40 @@ interface IVibrator { void alwaysOnDisable(in int id); float getResonantFrequency(); float getQFactor(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported. + */ float getFrequencyResolution(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported. + */ float getFrequencyMinimum(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported. + */ float[] getBandwidthAmplitudeMap(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.getPwleV2PrimitiveDurationMaxMillis` instead. + */ int getPwlePrimitiveDurationMax(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.getPwleV2CompositionSizeMax` instead. + */ int getPwleCompositionSizeMax(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. + */ android.hardware.vibrator.Braking[] getSupportedBraking(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.composePwleV2` instead. + */ void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback); void performVendorEffect(in android.hardware.vibrator.VendorEffect vendorEffect, in android.hardware.vibrator.IVibratorCallback callback); - List getPwleV2FrequencyToOutputAccelerationMap(); + List getFrequencyToOutputAccelerationMap(); int getPwleV2PrimitiveDurationMaxMillis(); int getPwleV2CompositionSizeMax(); int getPwleV2PrimitiveDurationMinMillis(); - void composePwleV2(in android.hardware.vibrator.PwleV2Primitive[] composite, in android.hardware.vibrator.IVibratorCallback callback); + void composePwleV2(in android.hardware.vibrator.CompositePwleV2 composite, in android.hardware.vibrator.IVibratorCallback callback); const int CAP_ON_CALLBACK = (1 << 0) /* 1 */; const int CAP_PERFORM_CALLBACK = (1 << 1) /* 2 */; const int CAP_AMPLITUDE_CONTROL = (1 << 2) /* 4 */; diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl new file mode 100644 index 0000000000..9662ca0b34 --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator; + +import android.hardware.vibrator.PwleV2Primitive; + +@VintfStability +parcelable CompositePwleV2 { + /** + * An array of primitives that represents the PWLE effect + */ + PwleV2Primitive[] pwlePrimitives; +} diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl similarity index 96% rename from vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl rename to vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl index a8db87cd25..470dc80fc7 100644 --- a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl +++ b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl @@ -17,7 +17,7 @@ package android.hardware.vibrator; @VintfStability -parcelable PwleV2OutputMapEntry { +parcelable FrequencyAccelerationMapEntry { /** * Absolute frequency point in the units of hertz * diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl index 11f36baf2c..a2f0017f14 100644 --- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl @@ -19,12 +19,12 @@ package android.hardware.vibrator; import android.hardware.vibrator.Braking; import android.hardware.vibrator.CompositeEffect; import android.hardware.vibrator.CompositePrimitive; +import android.hardware.vibrator.CompositePwleV2; import android.hardware.vibrator.Effect; import android.hardware.vibrator.EffectStrength; +import android.hardware.vibrator.FrequencyAccelerationMapEntry; import android.hardware.vibrator.IVibratorCallback; import android.hardware.vibrator.PrimitivePwle; -import android.hardware.vibrator.PwleV2OutputMapEntry; -import android.hardware.vibrator.PwleV2Primitive; import android.hardware.vibrator.VendorEffect; @VintfStability @@ -290,6 +290,8 @@ interface IVibrator { * * @return The frequency resolution of the bandwidth amplitude map. * Non-zero value if supported, or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented even if CAP_FREQUENCY_CONTROL capability is reported. */ float getFrequencyResolution(); @@ -301,6 +303,8 @@ interface IVibrator { * * @return The minimum frequency allowed. Non-zero value if supported, * or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented even if CAP_FREQUENCY_CONTROL capability is reported. */ float getFrequencyMinimum(); @@ -322,6 +326,8 @@ interface IVibrator { * * @return The maximum output acceleration amplitude for each supported frequency, * starting at getMinimumFrequency() + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented even if CAP_FREQUENCY_CONTROL capability is reported. */ float[] getBandwidthAmplitudeMap(); @@ -333,6 +339,8 @@ interface IVibrator { * * @return The maximum duration allowed for a single PrimitivePwle. * Non-zero value if supported, or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. Use `IVibrator.getPwleV2PrimitiveDurationMaxMillis` instead. */ int getPwlePrimitiveDurationMax(); @@ -344,6 +352,8 @@ interface IVibrator { * * @return The maximum count allowed. Non-zero value if supported, * or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. Use `IVibrator.getPwleV2CompositionSizeMax` instead. */ int getPwleCompositionSizeMax(); @@ -355,6 +365,8 @@ interface IVibrator { * Implementations are optional but encouraged if available. * * @return The braking mechanisms which are supported by the composePwle API. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. */ Braking[] getSupportedBraking(); @@ -368,6 +380,8 @@ interface IVibrator { * explicitly call off. IVibratorCallback.onComplete() support is required for this API. * * @param composite Array of PWLEs. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. Use `IVibrator.composePwleV2` instead. */ void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback); @@ -396,12 +410,12 @@ interface IVibrator { * Retrieves a mapping of vibration frequency (Hz) to the maximum achievable output * acceleration (Gs) the device can reach at that frequency. * - * The map, represented as a list of `PwleV2OutputMapEntry` (frequency, output acceleration) - * pairs, defines the device's frequency response. The platform uses the minimum and maximum - * frequency values to determine the supported input range for `IVibrator.composePwleV2`. - * Output acceleration values are used to identify a frequency range suitable to safely play - * perceivable vibrations with a simple API. The map is also exposed for developers using an - * advanced API. + * The map, represented as a list of `FrequencyAccelerationMapEntry` (frequency, output + * acceleration) pairs, defines the device's frequency response. The platform uses the minimum + * and maximum frequency values to determine the supported input range for + * `IVibrator.composePwleV2`. Output acceleration values are used to identify a frequency range + * suitable to safely play perceivable vibrations with a simple API. The map is also exposed for + * developers using an advanced API. * * The platform does not impose specific requirements on map resolution which can vary * depending on the shape of device output curve. The values will be linearly interpolated @@ -410,7 +424,7 @@ interface IVibrator { * * * This may not be supported and this support is reflected in getCapabilities - * (CAP_COMPOSE_PWLE_EFFECTS_V2). If this is supported, it's expected to be non-empty and + * (CAP_FREQUENCY_CONTROL). If this is supported, it's expected to be non-empty and * describe a valid non-empty frequency range where the simple API can be defined * (i.e. a range where the output acceleration is always above 10 db SL). * @@ -418,7 +432,7 @@ interface IVibrator { * mapping. * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities. */ - List getPwleV2FrequencyToOutputAccelerationMap(); + List getFrequencyToOutputAccelerationMap(); /** * Retrieve the maximum duration allowed for any primitive PWLE in units of @@ -436,8 +450,8 @@ interface IVibrator { * Retrieve the maximum number of PWLE primitives input supported by IVibrator.composePwleV2. * * This may not be supported and this support is reflected in - * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting PWLE effects must - * support effects with at least 16 PwleV2Primitive. + * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting + * PWLE effects must support effects with at least 16 PwleV2Primitive. * * @return The maximum count allowed. Non-zero value if supported. * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities. @@ -463,10 +477,14 @@ interface IVibrator { * This may not be supported and this support is reflected in * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). * + * Note: Devices reporting CAP_COMPOSE_PWLE_EFFECTS_V2 support MUST also have the + * CAP_FREQUENCY_CONTROL capability and provide a valid frequency to output acceleration map. + * * Doing this operation while the vibrator is already on is undefined behavior. Clients should * explicitly call off. IVibratorCallback.onComplete() support is required for this API. * - * @param composite An array of primitives that represents a PWLE (Piecewise-Linear Envelope). + * @param composite A CompositePwleV2 representing a composite vibration effect, composed of an + * array of primitives that define the PWLE (Piecewise-Linear Envelope). */ - void composePwleV2(in PwleV2Primitive[] composite, in IVibratorCallback callback); + void composePwleV2(in CompositePwleV2 composite, in IVibratorCallback callback); } diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl index bd7bec6036..1ad1a9f7b7 100644 --- a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl +++ b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl @@ -21,7 +21,7 @@ parcelable PwleV2Primitive { /** * Input amplitude ranges from 0.0 (inclusive) to 1.0 (inclusive), representing the relative * input value. Actual output acceleration depends on frequency and device response curve - * (see IVibrator.getPwleV2FrequencyToOutputAccelerationMap for max values). + * (see IVibrator.getFrequencyToOutputAccelerationMap for max values). * * Input amplitude linearly maps to output acceleration (e.g., 0.5 amplitude yields half the * max acceleration for that frequency). @@ -36,7 +36,7 @@ parcelable PwleV2Primitive { * Absolute frequency point in the units of hertz * * Values are within the continuous inclusive frequency range defined by - * IVibrator#getPwleV2FrequencyToOutputAccelerationMap. + * IVibrator#getFrequencyToOutputAccelerationMap. */ float frequencyHz; diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp index 34be00816a..165a3bf471 100644 --- a/vibrator/aidl/default/Vibrator.cpp +++ b/vibrator/aidl/default/Vibrator.cpp @@ -494,9 +494,17 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap( - std::vector* _aidl_return) { - std::vector frequencyToOutputAccelerationMap; +ndk::ScopedAStatus Vibrator::getFrequencyToOutputAccelerationMap( + std::vector* _aidl_return) { + int32_t capabilities = 0; + if (!getCapabilities(&capabilities).isOk()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + if (!(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { + return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); + } + + std::vector frequencyToOutputAccelerationMap; std::vector> frequencyToOutputAccelerationData = { {30.0f, 0.01f}, {46.0f, 0.09f}, {50.0f, 0.1f}, {55.0f, 0.12f}, {62.0f, 0.66f}, @@ -507,8 +515,8 @@ ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap( {263.0f, 1.39f}, {65.0f, 1.38f}, {278.0f, 1.37f}, {294.0f, 1.35f}, {300.0f, 1.34f}}; for (const auto& entry : frequencyToOutputAccelerationData) { frequencyToOutputAccelerationMap.push_back( - PwleV2OutputMapEntry(/*frequency=*/entry.first, - /*maxOutputAcceleration=*/entry.second)); + FrequencyAccelerationMapEntry(/*frequency=*/entry.first, + /*maxOutputAcceleration=*/entry.second)); } *_aidl_return = frequencyToOutputAccelerationMap; @@ -531,7 +539,8 @@ ndk::ScopedAStatus Vibrator::getPwleV2PrimitiveDurationMinMillis(int32_t* minDur return ndk::ScopedAStatus::ok(); } -float getPwleV2FrequencyMinHz(std::vector frequencyToOutputAccelerationMap) { +float getPwleV2FrequencyMinHz( + std::vector frequencyToOutputAccelerationMap) { if (frequencyToOutputAccelerationMap.empty()) { return 0.0f; } @@ -547,7 +556,8 @@ float getPwleV2FrequencyMinHz(std::vector frequencyToOutpu return minFrequency; } -float getPwleV2FrequencyMaxHz(std::vector frequencyToOutputAccelerationMap) { +float getPwleV2FrequencyMaxHz( + std::vector frequencyToOutputAccelerationMap) { if (frequencyToOutputAccelerationMap.empty()) { return 0.0f; } @@ -563,30 +573,31 @@ float getPwleV2FrequencyMaxHz(std::vector frequencyToOutpu return maxFrequency; } -ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector& composite, +ndk::ScopedAStatus Vibrator::composePwleV2(const CompositePwleV2& composite, const std::shared_ptr& callback) { LOG(VERBOSE) << "Vibrator compose PWLE V2"; int32_t capabilities = 0; if (!getCapabilities(&capabilities).isOk()) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } - if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) == 0) { + if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) || + !(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } int compositionSizeMax; getPwleV2CompositionSizeMax(&compositionSizeMax); - if (composite.size() <= 0 || composite.size() > compositionSizeMax) { + if (composite.pwlePrimitives.empty() || composite.pwlePrimitives.size() > compositionSizeMax) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } int32_t totalEffectDuration = 0; - std::vector frequencyToOutputAccelerationMap; - getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); + std::vector frequencyToOutputAccelerationMap; + getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); float minFrequency = getPwleV2FrequencyMinHz(frequencyToOutputAccelerationMap); float maxFrequency = getPwleV2FrequencyMaxHz(frequencyToOutputAccelerationMap); - for (auto& e : composite) { + for (auto& e : composite.pwlePrimitives) { if (e.timeMillis < 0.0f || e.timeMillis > COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MAX_MS) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h index 4637c5ab94..354ba46575 100644 --- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h +++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h @@ -59,12 +59,12 @@ class Vibrator : public BnVibrator { ndk::ScopedAStatus getSupportedBraking(std::vector* supported) override; ndk::ScopedAStatus composePwle(const std::vector &composite, const std::shared_ptr &callback) override; - ndk::ScopedAStatus getPwleV2FrequencyToOutputAccelerationMap( - std::vector* _aidl_return) override; + ndk::ScopedAStatus getFrequencyToOutputAccelerationMap( + std::vector* _aidl_return) override; ndk::ScopedAStatus getPwleV2PrimitiveDurationMaxMillis(int32_t* maxDurationMs) override; ndk::ScopedAStatus getPwleV2PrimitiveDurationMinMillis(int32_t* minDurationMs) override; ndk::ScopedAStatus getPwleV2CompositionSizeMax(int32_t* maxSize) override; - ndk::ScopedAStatus composePwleV2(const std::vector& composite, + ndk::ScopedAStatus composePwleV2(const CompositePwleV2& composite, const std::shared_ptr& callback) override; void setGlobalVibrationCallback(const std::shared_ptr& callback); diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp index bc017ae3b5..03ecb1a04e 100644 --- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp +++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp @@ -41,12 +41,13 @@ using aidl::android::hardware::vibrator::Braking; using aidl::android::hardware::vibrator::BrakingPwle; using aidl::android::hardware::vibrator::CompositeEffect; using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::CompositePwleV2; using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry; using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::IVibratorManager; using aidl::android::hardware::vibrator::PrimitivePwle; -using aidl::android::hardware::vibrator::PwleV2OutputMapEntry; using aidl::android::hardware::vibrator::PwleV2Primitive; using aidl::android::hardware::vibrator::VendorEffect; using aidl::android::os::PersistableBundle; @@ -175,11 +176,23 @@ static float getResonantFrequencyHz(const std::shared_ptr& vibrator, return resonantFrequencyHz; } +static bool shouldValidateLegacyFrequencyControlResult(int32_t capabilities, int32_t version, + ndk::ScopedAStatus& status) { + bool hasFrequencyControl = capabilities & IVibrator::CAP_FREQUENCY_CONTROL; + // Legacy frequency control APIs deprecated with PWLE V2 feature. + bool isDeprecated = version >= PWLE_V2_MIN_VERSION; + bool isUnknownOrUnsupported = status.getExceptionCode() == EX_UNSUPPORTED_OPERATION || + status.getStatus() == STATUS_UNKNOWN_TRANSACTION; + + // Validate if older HAL or if result is provided, even after deprecation. + return hasFrequencyControl && (!isDeprecated || !isUnknownOrUnsupported); +} + static float getFrequencyResolutionHz(const std::shared_ptr& vibrator, - int32_t capabilities) { - float freqResolutionHz; + int32_t capabilities, int32_t version) { + float freqResolutionHz = -1; ndk::ScopedAStatus status = vibrator->getFrequencyResolution(&freqResolutionHz); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); EXPECT_GT(freqResolutionHz, 0); } else { @@ -188,11 +201,11 @@ static float getFrequencyResolutionHz(const std::shared_ptr& vibrator return freqResolutionHz; } -static float getFrequencyMinimumHz(const std::shared_ptr& vibrator, - int32_t capabilities) { +static float getFrequencyMinimumHz(const std::shared_ptr& vibrator, int32_t capabilities, + int32_t version) { float freqMinimumHz; ndk::ScopedAStatus status = vibrator->getFrequencyMinimum(&freqMinimumHz); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities); @@ -205,19 +218,19 @@ static float getFrequencyMinimumHz(const std::shared_ptr& vibrator, return freqMinimumHz; } -static float getFrequencyMaximumHz(const std::shared_ptr& vibrator, - int32_t capabilities) { +static float getFrequencyMaximumHz(const std::shared_ptr& vibrator, int32_t capabilities, + int32_t version) { std::vector bandwidthAmplitudeMap; ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); } else { EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status)); } float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) * - getFrequencyResolutionHz(vibrator, capabilities)) + - getFrequencyMinimumHz(vibrator, capabilities); + getFrequencyResolutionHz(vibrator, capabilities, version)) + + getFrequencyMinimumHz(vibrator, capabilities, version); return freqMaximumHz; } @@ -230,12 +243,16 @@ static float getAmplitudeMax() { } static ActivePwle composeValidActivePwle(const std::shared_ptr& vibrator, - int32_t capabilities) { + int32_t capabilities, int32_t version) { float frequencyHz; if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) { frequencyHz = getResonantFrequencyHz(vibrator, capabilities); } else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { - frequencyHz = getFrequencyMinimumHz(vibrator, capabilities); + if (version < PWLE_V2_MIN_VERSION) { + frequencyHz = getFrequencyMinimumHz(vibrator, capabilities, version); + } else { + frequencyHz = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator); + } } else { frequencyHz = 150.0; // default value commonly used } @@ -846,23 +863,24 @@ TEST_P(VibratorAidl, GetQFactor) { } TEST_P(VibratorAidl, GetFrequencyResolution) { - getFrequencyResolutionHz(vibrator, capabilities); + getFrequencyResolutionHz(vibrator, capabilities, version); } TEST_P(VibratorAidl, GetFrequencyMinimum) { - getFrequencyMinimumHz(vibrator, capabilities); + getFrequencyMinimumHz(vibrator, capabilities, version); } TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) { std::vector bandwidthAmplitudeMap; ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); ASSERT_FALSE(bandwidthAmplitudeMap.empty()); int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) - - getFrequencyMinimumHz(vibrator, capabilities)) / - getFrequencyResolutionHz(vibrator, capabilities); + getFrequencyMinimumHz(vibrator, capabilities, version)) / + getFrequencyResolutionHz(vibrator, capabilities, version); ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize); for (float e : bandwidthAmplitudeMap) { @@ -911,7 +929,7 @@ TEST_P(VibratorAidl, GetSupportedBraking) { TEST_P(VibratorAidl, ComposeValidPwle) { if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { - ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities); + ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities, version); std::vector supported; EXPECT_OK(vibrator->getSupportedBraking(&supported)); @@ -921,13 +939,17 @@ TEST_P(VibratorAidl, ComposeValidPwle) { firstBraking.braking = isClabSupported ? Braking::CLAB : Braking::NONE; firstBraking.duration = 100; - ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities); + ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities, version); if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { - float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities); - float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities); - float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities); - secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f); - secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f); + float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities, version); + float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities, version); + float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities, version); + // As of API 16 these APIs are deprecated and no longer required to be implemented + // with frequency control capability. + if (minFrequencyHz >= 0 && maxFrequencyHz >= 0 && freqResolutionHz >= 0) { + secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f); + secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f); + } } BrakingPwle secondBraking; secondBraking.braking = Braking::NONE; @@ -955,7 +977,7 @@ TEST_P(VibratorAidl, ComposeValidPwleWithCallback) { uint32_t durationMs = segmentDurationMaxMs * 2 + 100; // Sum of 2 active and 1 braking below auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); std::vector supported; EXPECT_OK(vibrator->getSupportedBraking(&supported)); @@ -978,7 +1000,7 @@ TEST_P(VibratorAidl, ComposePwleSegmentBoundary) { // test empty queue EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr)); - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); PrimitivePwle pwle; pwle = active; @@ -996,7 +1018,7 @@ TEST_P(VibratorAidl, ComposePwleSegmentBoundary) { TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) { if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); active.startAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed active.endAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed @@ -1016,11 +1038,18 @@ TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) { TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) { if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) && (capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { - float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities); - float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities); - float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities); + float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities, version); + float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities, version); + float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities, version); - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + // As of API 16 these APIs are deprecated and no longer required to be implemented with + // frequency control capability. + if (freqMinimumHz < 0 || freqMaximumHz < 0 || freqResolutionHz < 0) { + GTEST_SKIP() << "PWLE V1 is not supported, skipping test"; + return; + } + + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); active.startFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed @@ -1040,7 +1069,7 @@ TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) { TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) { if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); int32_t segmentDurationMaxMs; vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs); @@ -1052,15 +1081,15 @@ TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) { } } -TEST_P(VibratorAidl, PwleV2FrequencyToOutputAccelerationMapHasValidFrequencyRange) { - if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { - GTEST_SKIP() << "PWLE V2 not supported, skipping test"; +TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapHasValidFrequencyRange) { + if (version < PWLE_V2_MIN_VERSION || !(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { + GTEST_SKIP() << "Frequency control is not supported, skipping test"; return; } - std::vector frequencyToOutputAccelerationMap; + std::vector frequencyToOutputAccelerationMap; ndk::ScopedAStatus status = - vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); + vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); EXPECT_OK(std::move(status)); ASSERT_FALSE(frequencyToOutputAccelerationMap.empty()); auto sharpnessRange = @@ -1072,6 +1101,15 @@ TEST_P(VibratorAidl, PwleV2FrequencyToOutputAccelerationMapHasValidFrequencyRang ASSERT_TRUE(sharpnessRange.first < sharpnessRange.second); } +TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapUnsupported) { + if ((capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) return; + + std::vector frequencyToOutputAccelerationMap; + + EXPECT_UNKNOWN_OR_UNSUPPORTED( + vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); +} + TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMaxMillis) { if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { GTEST_SKIP() << "PWLE V2 not supported, skipping test"; @@ -1111,6 +1149,17 @@ TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMinMillis) { ASSERT_LE(durationMs, pwle_v2_utils::COMPOSE_PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS); } +TEST_P(VibratorAidl, ValidatePwleV2DependencyOnFrequencyControl) { + if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { + GTEST_SKIP() << "PWLE V2 not supported, skipping test"; + return; + } + + // Check if frequency control is supported + bool hasFrequencyControl = (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) != 0; + ASSERT_TRUE(hasFrequencyControl) << "Frequency control MUST be supported when PWLE V2 is."; +} + TEST_P(VibratorAidl, ComposeValidPwleV2Effect) { if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { GTEST_SKIP() << "PWLE V2 not supported, skipping test"; @@ -1126,12 +1175,13 @@ TEST_P(VibratorAidl, ComposePwleV2Unsupported) { EXPECT_EQ(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2, 0) << "Vibrator version " << version << " should not report PWLE V2 capability."; } - if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) return; + if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) return; - std::vector pwleEffect{ - PwleV2Primitive(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f, /*timeMillis=*/50)}; + CompositePwleV2 composite; + composite.pwlePrimitives.emplace_back(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f, + /*timeMillis=*/50); - EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(pwleEffect, nullptr)); + EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(composite, nullptr)); } TEST_P(VibratorAidl, ComposeValidPwleV2EffectWithCallback) { @@ -1150,8 +1200,10 @@ TEST_P(VibratorAidl, ComposeValidPwleV2EffectWithCallback) { auto timeout = std::chrono::milliseconds(minDuration) + VIBRATION_CALLBACK_TIMEOUT; float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator); - EXPECT_OK(vibrator->composePwleV2( - {PwleV2Primitive(/*amplitude=*/0.5, minFrequency, minDuration)}, callback)); + CompositePwleV2 composite; + composite.pwlePrimitives.emplace_back(/*amplitude=*/0.5, minFrequency, minDuration); + + EXPECT_OK(vibrator->composePwleV2(composite, callback)); EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); EXPECT_OK(vibrator->off()); } @@ -1177,43 +1229,48 @@ TEST_P(VibratorAidl, composeInvalidPwleV2Effect) { EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs)); EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs)); - std::vector composePwle; + CompositePwleV2 composePwle; // Negative amplitude - composePwle.push_back(PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with negative amplitude should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Amplitude exceeding 1.0 - composePwle.push_back(PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with amplitude greater than 1.0 should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Duration exceeding maximum - composePwle.push_back( + composePwle.pwlePrimitives.push_back( PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, maxDurationMs + 10)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with duration exceeding maximum should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Negative duration - composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with negative duration should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Frequency below minimum float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator); - composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with frequency below minimum should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Frequency above maximum float maxFrequency = pwle_v2_utils::getPwleV2FrequencyMaxHz(vibrator); - composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with frequency above maximum should fail"; } diff --git a/vibrator/aidl/vts/pwle_v2_utils.h b/vibrator/aidl/vts/pwle_v2_utils.h index 2163908e2a..eaa024cf42 100644 --- a/vibrator/aidl/vts/pwle_v2_utils.h +++ b/vibrator/aidl/vts/pwle_v2_utils.h @@ -20,8 +20,8 @@ #include #include "test_utils.h" +using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry; using aidl::android::hardware::vibrator::IVibrator; -using aidl::android::hardware::vibrator::PwleV2OutputMapEntry; using aidl::android::hardware::vibrator::PwleV2Primitive; namespace aidl { @@ -116,9 +116,8 @@ static float convertSensitivityLevelToAcceleration(int sl, float frequency) { } static float getPwleV2FrequencyMinHz(const std::shared_ptr& vibrator) { - std::vector frequencyToOutputAccelerationMap; - EXPECT_OK( - vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); + std::vector frequencyToOutputAccelerationMap; + EXPECT_OK(vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty()); // We can't use ASSERT_TRUE() above because this is a non-void function, // but we need to return to assure we don't crash from a null dereference. @@ -134,9 +133,8 @@ static float getPwleV2FrequencyMinHz(const std::shared_ptr& vibrator) } static float getPwleV2FrequencyMaxHz(const std::shared_ptr& vibrator) { - std::vector frequencyToOutputAccelerationMap; - EXPECT_OK( - vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); + std::vector frequencyToOutputAccelerationMap; + EXPECT_OK(vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty()); // We can't use ASSERT_TRUE() above because this is a non-void function, // but we need to return to assure we don't crash from a null dereference. @@ -151,8 +149,7 @@ static float getPwleV2FrequencyMaxHz(const std::shared_ptr& vibrator) return entry->frequencyHz; } -static std::vector composeValidPwleV2Effect( - const std::shared_ptr& vibrator) { +static CompositePwleV2 composeValidPwleV2Effect(const std::shared_ptr& vibrator) { int32_t minDurationMs; EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs)); int32_t maxDurationMs; @@ -162,20 +159,20 @@ static std::vector composeValidPwleV2Effect( int32_t maxCompositionSize; EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize)); - std::vector pwleEffect; + CompositePwleV2 composite; - pwleEffect.emplace_back(0.1f, minFrequency, minDurationMs); - pwleEffect.emplace_back(0.5f, maxFrequency, maxDurationMs); + composite.pwlePrimitives.emplace_back(0.1f, minFrequency, minDurationMs); + composite.pwlePrimitives.emplace_back(0.5f, maxFrequency, maxDurationMs); float variedFrequency = (minFrequency + maxFrequency) / 2.0f; for (int i = 0; i < maxCompositionSize - 2; i++) { - pwleEffect.emplace_back(0.7f, variedFrequency, minDurationMs); + composite.pwlePrimitives.emplace_back(0.7f, variedFrequency, minDurationMs); } - return pwleEffect; + return composite; } -static std::vector composePwleV2EffectWithTooManyPoints( +static CompositePwleV2 composePwleV2EffectWithTooManyPoints( const std::shared_ptr& vibrator) { int32_t minDurationMs, maxCompositionSize; EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs)); @@ -187,12 +184,15 @@ static std::vector composePwleV2EffectWithTooManyPoints( std::fill(pwleEffect.begin(), pwleEffect.end(), PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency, minDurationMs)); - return pwleEffect; + CompositePwleV2 composite; + composite.pwlePrimitives = pwleEffect; + + return composite; } static std::pair getPwleV2SharpnessRange( const std::shared_ptr& vibrator, - std::vector freqToOutputAccelerationMap) { + std::vector freqToOutputAccelerationMap) { std::pair sharpnessRange = {-1, -1}; // Sort the entries by frequency in ascending order