Merge "Modify composePwleV2 parameters and getPwleV2FrequencyToOutputAccelerationMap dependency" into main

This commit is contained in:
Ahmad Khalil
2024-10-22 11:20:45 +00:00
committed by Android (Google) Code Review
11 changed files with 282 additions and 110 deletions

View File

@@ -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 <name>-update-api`.
//
// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.vibrator;
@VintfStability
parcelable CompositePwleV2 {
android.hardware.vibrator.PwleV2Primitive[] pwlePrimitives;
}

View File

@@ -33,7 +33,7 @@
package android.hardware.vibrator;
@VintfStability
parcelable PwleV2OutputMapEntry {
parcelable FrequencyAccelerationMapEntry {
float frequencyHz;
float maxOutputAccelerationGs;
}

View File

@@ -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<android.hardware.vibrator.PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
List<android.hardware.vibrator.FrequencyAccelerationMapEntry> 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 */;

View File

@@ -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;
}

View File

@@ -17,7 +17,7 @@
package android.hardware.vibrator;
@VintfStability
parcelable PwleV2OutputMapEntry {
parcelable FrequencyAccelerationMapEntry {
/**
* Absolute frequency point in the units of hertz
*

View File

@@ -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<PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
List<FrequencyAccelerationMapEntry> 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);
}

View File

@@ -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;

View File

@@ -494,9 +494,17 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &compo
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap(
std::vector<PwleV2OutputMapEntry>* _aidl_return) {
std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
ndk::ScopedAStatus Vibrator::getFrequencyToOutputAccelerationMap(
std::vector<FrequencyAccelerationMapEntry>* _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<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
std::vector<std::pair<float, float>> 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<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
float getPwleV2FrequencyMinHz(
std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap) {
if (frequencyToOutputAccelerationMap.empty()) {
return 0.0f;
}
@@ -547,7 +556,8 @@ float getPwleV2FrequencyMinHz(std::vector<PwleV2OutputMapEntry> frequencyToOutpu
return minFrequency;
}
float getPwleV2FrequencyMaxHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
float getPwleV2FrequencyMaxHz(
std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap) {
if (frequencyToOutputAccelerationMap.empty()) {
return 0.0f;
}
@@ -563,30 +573,31 @@ float getPwleV2FrequencyMaxHz(std::vector<PwleV2OutputMapEntry> frequencyToOutpu
return maxFrequency;
}
ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector<PwleV2Primitive>& composite,
ndk::ScopedAStatus Vibrator::composePwleV2(const CompositePwleV2& composite,
const std::shared_ptr<IVibratorCallback>& 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<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
std::vector<FrequencyAccelerationMapEntry> 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);
}

View File

@@ -59,12 +59,12 @@ class Vibrator : public BnVibrator {
ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle> &composite,
const std::shared_ptr<IVibratorCallback> &callback) override;
ndk::ScopedAStatus getPwleV2FrequencyToOutputAccelerationMap(
std::vector<PwleV2OutputMapEntry>* _aidl_return) override;
ndk::ScopedAStatus getFrequencyToOutputAccelerationMap(
std::vector<FrequencyAccelerationMapEntry>* _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<PwleV2Primitive>& composite,
ndk::ScopedAStatus composePwleV2(const CompositePwleV2& composite,
const std::shared_ptr<IVibratorCallback>& callback) override;
void setGlobalVibrationCallback(const std::shared_ptr<IVibratorCallback>& callback);

View File

@@ -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<IVibrator>& 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<IVibrator>& 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<IVibrator>& vibrator
return freqResolutionHz;
}
static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator,
int32_t capabilities) {
static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& 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<IVibrator>& vibrator,
return freqMinimumHz;
}
static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator,
int32_t capabilities) {
static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator, int32_t capabilities,
int32_t version) {
std::vector<float> 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<IVibrator>& 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<float> 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<Braking> 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<Braking> 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<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
std::vector<FrequencyAccelerationMapEntry> 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<FrequencyAccelerationMapEntry> 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<PwleV2Primitive> 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<PwleV2Primitive> 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";
}

View File

@@ -20,8 +20,8 @@
#include <aidl/android/hardware/vibrator/IVibrator.h>
#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<IVibrator>& vibrator) {
std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
EXPECT_OK(
vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
std::vector<FrequencyAccelerationMapEntry> 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<IVibrator>& vibrator)
}
static float getPwleV2FrequencyMaxHz(const std::shared_ptr<IVibrator>& vibrator) {
std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
EXPECT_OK(
vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
std::vector<FrequencyAccelerationMapEntry> 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<IVibrator>& vibrator)
return entry->frequencyHz;
}
static std::vector<PwleV2Primitive> composeValidPwleV2Effect(
const std::shared_ptr<IVibrator>& vibrator) {
static CompositePwleV2 composeValidPwleV2Effect(const std::shared_ptr<IVibrator>& vibrator) {
int32_t minDurationMs;
EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
int32_t maxDurationMs;
@@ -162,20 +159,20 @@ static std::vector<PwleV2Primitive> composeValidPwleV2Effect(
int32_t maxCompositionSize;
EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize));
std::vector<PwleV2Primitive> 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<PwleV2Primitive> composePwleV2EffectWithTooManyPoints(
static CompositePwleV2 composePwleV2EffectWithTooManyPoints(
const std::shared_ptr<IVibrator>& vibrator) {
int32_t minDurationMs, maxCompositionSize;
EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
@@ -187,12 +184,15 @@ static std::vector<PwleV2Primitive> 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<float, float> getPwleV2SharpnessRange(
const std::shared_ptr<IVibrator>& vibrator,
std::vector<PwleV2OutputMapEntry> freqToOutputAccelerationMap) {
std::vector<FrequencyAccelerationMapEntry> freqToOutputAccelerationMap) {
std::pair<float, float> sharpnessRange = {-1, -1};
// Sort the entries by frequency in ascending order