diff options
10 files changed, 182 insertions, 59 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8dc9652db58c..0db91f5667ee 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2579,9 +2579,10 @@ package android.os { @FlaggedApi("android.os.vibrator.vendor_vibration_effects") public static final class VibrationEffect.VendorEffect extends android.os.VibrationEffect { method @Nullable public long[] computeCreateWaveformOffOnTimingsOrNull(); + method public float getAdaptiveScale(); method public long getDuration(); method public int getEffectStrength(); - method public float getLinearScale(); + method public float getScale(); method @NonNull public android.os.PersistableBundle getVendorData(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.VendorEffect> CREATOR; diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index e68b74683292..f02d4a9ce4a7 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -346,7 +346,7 @@ public abstract class VibrationEffect implements Parcelable { @RequiresPermission(android.Manifest.permission.VIBRATE_VENDOR_EFFECTS) public static VibrationEffect createVendorEffect(@NonNull PersistableBundle effect) { VibrationEffect vendorEffect = new VendorEffect(effect, VendorEffect.DEFAULT_STRENGTH, - VendorEffect.DEFAULT_SCALE); + VendorEffect.DEFAULT_SCALE, VendorEffect.DEFAULT_SCALE); vendorEffect.validate(); return vendorEffect; } @@ -623,7 +623,7 @@ public abstract class VibrationEffect implements Parcelable { * @hide */ @NonNull - public abstract VibrationEffect scaleLinearly(float scaleFactor); + public abstract VibrationEffect applyAdaptiveScale(float scaleFactor); /** * Ensures that the effect is repeating indefinitely or not. This is a lossy operation and @@ -948,7 +948,7 @@ public abstract class VibrationEffect implements Parcelable { /** @hide */ @NonNull @Override - public Composed scaleLinearly(float scaleFactor) { + public Composed applyAdaptiveScale(float scaleFactor) { return applyToSegments(VibrationEffectSegment::scaleLinearly, scaleFactor); } @@ -1100,21 +1100,23 @@ public abstract class VibrationEffect implements Parcelable { private final PersistableBundle mVendorData; private final int mEffectStrength; - private final float mLinearScale; + private final float mScale; + private final float mAdaptiveScale; /** @hide */ VendorEffect(@NonNull Parcel in) { this(Objects.requireNonNull( in.readPersistableBundle(VibrationEffect.class.getClassLoader())), - in.readInt(), in.readFloat()); + in.readInt(), in.readFloat(), in.readFloat()); } /** @hide */ public VendorEffect(@NonNull PersistableBundle vendorData, int effectStrength, - float linearScale) { + float scale, float adaptiveScale) { mVendorData = vendorData; mEffectStrength = effectStrength; - mLinearScale = linearScale; + mScale = scale; + mAdaptiveScale = adaptiveScale; } @NonNull @@ -1126,8 +1128,12 @@ public abstract class VibrationEffect implements Parcelable { return mEffectStrength; } - public float getLinearScale() { - return mLinearScale; + public float getScale() { + return mScale; + } + + public float getAdaptiveScale() { + return mAdaptiveScale; } /** @hide */ @@ -1175,7 +1181,8 @@ public abstract class VibrationEffect implements Parcelable { if (mEffectStrength == effectStrength) { return this; } - VendorEffect updated = new VendorEffect(mVendorData, effectStrength, mLinearScale); + VendorEffect updated = new VendorEffect(mVendorData, effectStrength, mScale, + mAdaptiveScale); updated.validate(); return updated; } @@ -1184,18 +1191,24 @@ public abstract class VibrationEffect implements Parcelable { @NonNull @Override public VendorEffect scale(float scaleFactor) { - // Vendor effect strength cannot be scaled with this method. - return this; + if (Float.compare(mScale, scaleFactor) == 0) { + return this; + } + VendorEffect updated = new VendorEffect(mVendorData, mEffectStrength, scaleFactor, + mAdaptiveScale); + updated.validate(); + return updated; } /** @hide */ @NonNull @Override - public VibrationEffect scaleLinearly(float scaleFactor) { - if (Float.compare(mLinearScale, scaleFactor) == 0) { + public VibrationEffect applyAdaptiveScale(float scaleFactor) { + if (Float.compare(mAdaptiveScale, scaleFactor) == 0) { return this; } - VendorEffect updated = new VendorEffect(mVendorData, mEffectStrength, scaleFactor); + VendorEffect updated = new VendorEffect(mVendorData, mEffectStrength, mScale, + scaleFactor); updated.validate(); return updated; } @@ -1216,29 +1229,31 @@ public abstract class VibrationEffect implements Parcelable { return false; } return mEffectStrength == other.mEffectStrength - && (Float.compare(mLinearScale, other.mLinearScale) == 0) + && (Float.compare(mScale, other.mScale) == 0) + && (Float.compare(mAdaptiveScale, other.mAdaptiveScale) == 0) && isPersistableBundleEquals(mVendorData, other.mVendorData); } @Override public int hashCode() { // PersistableBundle does not implement hashCode, so use its size as a shortcut. - return Objects.hash(mVendorData.size(), mEffectStrength, mLinearScale); + return Objects.hash(mVendorData.size(), mEffectStrength, mScale, mAdaptiveScale); } @Override public String toString() { return String.format(Locale.ROOT, - "VendorEffect{vendorData=%s, strength=%s, scale=%.2f}", - mVendorData, effectStrengthToString(mEffectStrength), mLinearScale); + "VendorEffect{vendorData=%s, strength=%s, scale=%.2f, adaptiveScale=%.2f}", + mVendorData, effectStrengthToString(mEffectStrength), mScale, mAdaptiveScale); } /** @hide */ @Override public String toDebugString() { - return String.format(Locale.ROOT, "vendorEffect=%s, strength=%s, scale=%.2f", + return String.format(Locale.ROOT, + "vendorEffect=%s, strength=%s, scale=%.2f, adaptiveScale=%.2f", mVendorData.toShortString(), effectStrengthToString(mEffectStrength), - mLinearScale); + mScale, mAdaptiveScale); } @Override @@ -1251,7 +1266,8 @@ public abstract class VibrationEffect implements Parcelable { out.writeInt(PARCEL_TOKEN_VENDOR_EFFECT); out.writePersistableBundle(mVendorData); out.writeInt(mEffectStrength); - out.writeFloat(mLinearScale); + out.writeFloat(mScale); + out.writeFloat(mAdaptiveScale); } /** diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java index bd3d94467ead..4f76dd636c30 100644 --- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java +++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java @@ -60,7 +60,7 @@ import java.util.Arrays; @RunWith(MockitoJUnitRunner.class) public class VibrationEffectTest { - + private static final float TOLERANCE = 1e-2f; private static final String RINGTONE_URI_1 = "content://test/system/ringtone_1"; private static final String RINGTONE_URI_2 = "content://test/system/ringtone_2"; private static final String RINGTONE_URI_3 = "content://test/system/ringtone_3"; @@ -709,7 +709,7 @@ public class VibrationEffectTest { @Test public void testScaleWaveform() { VibrationEffect scaledUp = TEST_WAVEFORM.scale(1.5f); - assertEquals(1f, getStepSegment(scaledUp, 0).getAmplitude(), 1e-5f); + assertEquals(1f, getStepSegment(scaledUp, 0).getAmplitude(), TOLERANCE); VibrationEffect scaledDown = TEST_WAVEFORM.scale(0.5f); assertTrue(1f > getStepSegment(scaledDown, 0).getAmplitude()); @@ -731,11 +731,11 @@ public class VibrationEffectTest { public void testScaleVendorEffect() { VibrationEffect effect = VibrationEffect.createVendorEffect(createNonEmptyBundle()); - VibrationEffect scaledUp = effect.scale(1.5f); - assertEquals(effect, scaledUp); + VibrationEffect.VendorEffect scaledUp = (VibrationEffect.VendorEffect) effect.scale(1.5f); + assertEquals(1.5f, scaledUp.getScale()); - VibrationEffect scaledDown = effect.scale(0.5f); - assertEquals(effect, scaledDown); + VibrationEffect.VendorEffect scaledDown = (VibrationEffect.VendorEffect) effect.scale(0.5f); + assertEquals(0.5f, scaledDown.getScale()); } @Test @@ -755,6 +755,70 @@ public class VibrationEffectTest { } @Test + public void testApplyAdaptiveScaleOneShot() { + VibrationEffect oneShot = VibrationEffect.createOneShot(TEST_TIMING, /* amplitude= */ 100); + + VibrationEffect scaledUp = oneShot.applyAdaptiveScale(1.5f); + assertThat(getStepSegment(scaledUp, 0).getAmplitude()).isWithin(TOLERANCE).of(150 / 255f); + + VibrationEffect scaledDown = oneShot.applyAdaptiveScale(0.5f); + assertThat(getStepSegment(scaledDown, 0).getAmplitude()).isWithin(TOLERANCE).of(50 / 255f); + } + + @Test + public void testApplyAdaptiveScaleWaveform() { + VibrationEffect waveform = VibrationEffect.createWaveform( + new long[] { 100, 100 }, new int[] { 10, 0 }, -1); + + VibrationEffect scaledUp = waveform.applyAdaptiveScale(1.5f); + assertThat(getStepSegment(scaledUp, 0).getAmplitude()).isWithin(TOLERANCE).of(15 / 255f); + + VibrationEffect scaledDown = waveform.applyAdaptiveScale(0.5f); + assertThat(getStepSegment(scaledDown, 0).getAmplitude()).isWithin(TOLERANCE).of(5 / 255f); + } + + @Test + public void testApplyAdaptiveScalePrebaked() { + VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); + + VibrationEffect scaledUp = effect.applyAdaptiveScale(1.5f); + assertEquals(effect, scaledUp); + + VibrationEffect scaledDown = effect.applyAdaptiveScale(0.5f); + assertEquals(effect, scaledDown); + } + + @Test + @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) + public void testApplyAdaptiveScaleVendorEffect() { + VibrationEffect effect = VibrationEffect.createVendorEffect(createNonEmptyBundle()); + + VibrationEffect.VendorEffect scaledUp = + (VibrationEffect.VendorEffect) effect.applyAdaptiveScale(1.5f); + assertEquals(1.5f, scaledUp.getAdaptiveScale()); + + VibrationEffect.VendorEffect scaledDown = + (VibrationEffect.VendorEffect) effect.applyAdaptiveScale(0.5f); + assertEquals(0.5f, scaledDown.getAdaptiveScale()); + } + + @Test + public void testApplyAdaptiveScaleComposed() { + VibrationEffect effect = VibrationEffect.startComposition() + .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 1) + .addEffect(VibrationEffect.createOneShot(TEST_TIMING, /* amplitude= */ 100)) + .compose(); + + VibrationEffect scaledUp = effect.applyAdaptiveScale(1.5f); + assertThat(getPrimitiveSegment(scaledUp, 0).getScale()).isWithin(TOLERANCE).of(0.75f); + assertThat(getStepSegment(scaledUp, 1).getAmplitude()).isWithin(TOLERANCE).of(150 / 255f); + + VibrationEffect scaledDown = effect.applyAdaptiveScale(0.5f); + assertThat(getPrimitiveSegment(scaledDown, 0).getScale()).isWithin(TOLERANCE).of(0.25f); + assertThat(getStepSegment(scaledDown, 1).getAmplitude()).isWithin(TOLERANCE).of(50 / 255f); + } + + @Test public void testApplyEffectStrengthToOneShotWaveformAndPrimitives() { VibrationEffect oneShot = VibrationEffect.createOneShot(100, 100); VibrationEffect waveform = VibrationEffect.createWaveform(new long[] { 10, 20 }, 0); diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java index a74c4e07c9ed..b3862cc51c07 100644 --- a/services/core/java/com/android/server/vibrator/VibrationScaler.java +++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java @@ -134,7 +134,8 @@ final class VibrationScaler { return effect.resolve(mDefaultVibrationAmplitude) .applyEffectStrength(newEffectStrength) .scale(scaleFactor) - .scaleLinearly(adaptiveScale); + // Make sure this is the last one so it is applied on top of the settings scaling. + .applyAdaptiveScale(adaptiveScale); } /** diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index 8cc157c2ed81..4fc0b74ecb80 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -279,8 +279,8 @@ final class VibratorController { vendorEffect.getVendorData().writeToParcel(vendorData, /* flags= */ 0); vendorData.setDataPosition(0); long duration = mNativeWrapper.performVendorEffect(vendorData, - vendorEffect.getEffectStrength(), vendorEffect.getLinearScale(), - vibrationId); + vendorEffect.getEffectStrength(), vendorEffect.getScale(), + vendorEffect.getAdaptiveScale(), vibrationId); if (duration > 0) { mCurrentAmplitude = -1; notifyListenerOnVibrating(true); @@ -459,7 +459,7 @@ final class VibratorController { long vibrationId); private static native long performVendorEffect(long nativePtr, Parcel vendorData, - long strength, float scale, long vibrationId); + long strength, float scale, float adaptiveScale, long vibrationId); private static native long performComposedEffect(long nativePtr, PrimitiveSegment[] effect, long vibrationId); @@ -518,8 +518,9 @@ final class VibratorController { /** Turns vibrator on to perform a vendor-specific effect. */ public long performVendorEffect(Parcel vendorData, long strength, float scale, - long vibrationId) { - return performVendorEffect(mNativePtr, vendorData, strength, scale, vibrationId); + float adaptiveScale, long vibrationId) { + return performVendorEffect(mNativePtr, vendorData, strength, scale, adaptiveScale, + vibrationId); } /** Turns vibrator on to perform effect composed of give primitives effect. */ diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index f12930a49ecb..5c5ac28b2169 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -198,7 +198,8 @@ static Aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primit } static Aidl::VendorEffect vendorEffectFromJavaParcel(JNIEnv* env, jobject vendorData, - jlong strength, jfloat scale) { + jlong strength, jfloat scale, + jfloat adaptiveScale) { PersistableBundle bundle; if (AParcel* parcel = AParcel_fromJavaParcel(env, vendorData); parcel != nullptr) { if (binder_status_t status = bundle.readFromParcel(parcel); status == STATUS_OK) { @@ -217,6 +218,7 @@ static Aidl::VendorEffect vendorEffectFromJavaParcel(JNIEnv* env, jobject vendor effect.vendorData = bundle; effect.strength = static_cast<Aidl::EffectStrength>(strength); effect.scale = static_cast<float>(scale); + effect.vendorScale = static_cast<float>(adaptiveScale); return effect; } @@ -319,13 +321,14 @@ static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, j static jlong vibratorPerformVendorEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jobject vendorData, jlong strength, jfloat scale, - jlong vibrationId) { + jfloat adaptiveScale, jlong vibrationId) { VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); if (wrapper == nullptr) { ALOGE("vibratorPerformVendorEffect failed because native wrapper was not initialized"); return -1; } - Aidl::VendorEffect effect = vendorEffectFromJavaParcel(env, vendorData, strength, scale); + Aidl::VendorEffect effect = + vendorEffectFromJavaParcel(env, vendorData, strength, scale, adaptiveScale); auto callback = wrapper->createCallback(vibrationId); auto performVendorEffectFn = [&effect, &callback](vibrator::HalWrapper* hal) { return hal->performVendorEffect(effect, callback); @@ -511,7 +514,7 @@ static const JNINativeMethod method_table[] = { {"off", "(J)V", (void*)vibratorOff}, {"setAmplitude", "(JF)V", (void*)vibratorSetAmplitude}, {"performEffect", "(JJJJ)J", (void*)vibratorPerformEffect}, - {"performVendorEffect", "(JLandroid/os/Parcel;JFJ)J", (void*)vibratorPerformVendorEffect}, + {"performVendorEffect", "(JLandroid/os/Parcel;JFFJ)J", (void*)vibratorPerformVendorEffect}, {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;J)J", (void*)vibratorPerformComposedEffect}, {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJ)J", diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java index 470469114dfa..9681d74eb9b3 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java @@ -281,8 +281,8 @@ public class VibrationScalerTest { @Test @EnableFlags(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) - public void scale_withVendorEffect_setsEffectStrengthBasedOnSettings() { - setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_LOW); + public void scale_withVendorEffect_setsEffectStrengthAndScaleBasedOnSettings() { + setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_MEDIUM); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); PersistableBundle vendorData = new PersistableBundle(); vendorData.putString("key", "value"); @@ -291,20 +291,27 @@ public class VibrationScalerTest { VibrationEffect.VendorEffect scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG); + // Notification scales up. + assertTrue(scaled.getScale() > 1); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_MEDIUM); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM); + // Notification does not scale. + assertEquals(1, scaled.getScale(), TOLERANCE); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT); + // Notification scales down. + assertTrue(scaled.getScale() < 1); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); // Vibration setting being bypassed will use default setting. - assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT); + assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM); + assertEquals(1, scaled.getScale(), TOLERANCE); } @Test @@ -348,7 +355,7 @@ public class VibrationScalerTest { scaled = getFirstSegment(mVibrationScaler.scale(VibrationEffect.createOneShot(128, 128), USAGE_TOUCH)); // Haptic feedback does not scale. - assertEquals(128f / 255, scaled.getAmplitude(), 1e-5); + assertEquals(128f / 255, scaled.getAmplitude(), TOLERANCE); } @Test @@ -373,7 +380,7 @@ public class VibrationScalerTest { scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_TOUCH)); // Haptic feedback does not scale. - assertEquals(0.5, scaled.getScale(), 1e-5); + assertEquals(0.5, scaled.getScale(), TOLERANCE); } @Test @@ -446,7 +453,7 @@ public class VibrationScalerTest { android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED, android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS, }) - public void scale_adaptiveHapticsOnVendorEffect_setsLinearScaleParameter() { + public void scale_adaptiveHapticsOnVendorEffect_setsAdaptiveScaleParameter() { setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_HIGH); mVibrationScaler.updateAdaptiveHapticsScale(USAGE_RINGTONE, 0.5f); @@ -457,12 +464,12 @@ public class VibrationScalerTest { VibrationEffect.VendorEffect scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_RINGTONE); - assertEquals(scaled.getLinearScale(), 0.5f); + assertEquals(scaled.getAdaptiveScale(), 0.5f); mVibrationScaler.removeAdaptiveHapticsScale(USAGE_RINGTONE); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_RINGTONE); - assertEquals(scaled.getLinearScale(), 1.0f); + assertEquals(scaled.getAdaptiveScale(), 1.0f); } private void setDefaultIntensity(@VibrationAttributes.Usage int usage, diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java index 0fbdce4ce61a..bfdaa785a669 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java @@ -34,13 +34,15 @@ import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; -import android.content.Context; +import android.content.ContentResolver; +import android.content.ContextWrapper; import android.content.pm.PackageManagerInternal; import android.hardware.vibrator.Braking; import android.hardware.vibrator.IVibrator; @@ -52,6 +54,7 @@ import android.os.PersistableBundle; import android.os.PowerManager; import android.os.Process; import android.os.SystemClock; +import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; @@ -66,11 +69,14 @@ import android.os.vibrator.VibrationEffectSegment; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.provider.Settings; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; +import com.android.internal.util.test.FakeSettingsProvider; +import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.server.LocalServices; import org.junit.After; @@ -105,10 +111,12 @@ public class VibrationThreadTest { private static final int TEST_DEFAULT_AMPLITUDE = 255; private static final float TEST_DEFAULT_SCALE_LEVEL_GAIN = 1.4f; - @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule - public final CheckFlagsRule mCheckFlagsRule = - DeviceFlagsValueProvider.createCheckFlagsRule(); + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Rule + public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); @Mock private PackageManagerInternal mPackageManagerInternalMock; @Mock private VibrationThread.VibratorManagerHooks mManagerHooks; @@ -117,6 +125,7 @@ public class VibrationThreadTest { @Mock private VibrationConfig mVibrationConfigMock; @Mock private VibratorFrameworkStatsLogger mStatsLoggerMock; + private ContextWrapper mContextSpy; private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>(); private VibrationSettings mVibrationSettings; private VibrationScaler mVibrationScaler; @@ -149,14 +158,16 @@ public class VibrationThreadTest { LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock); - Context context = InstrumentationRegistry.getContext(); - mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()), - mVibrationConfigMock); + mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); + ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); + when(mContextSpy.getContentResolver()).thenReturn(contentResolver); + mVibrationSettings = new VibrationSettings(mContextSpy, + new Handler(mTestLooper.getLooper()), mVibrationConfigMock); mVibrationScaler = new VibrationScaler(mVibrationConfigMock, mVibrationSettings); mockVibrators(VIBRATOR_ID); - PowerManager.WakeLock wakeLock = context.getSystemService( + PowerManager.WakeLock wakeLock = mContextSpy.getSystemService( PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); mThread = new VibrationThread(wakeLock, mManagerHooks); mThread.start(); @@ -254,6 +265,9 @@ public class VibrationThreadTest { @Test @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void vibrate_singleWaveformWithAdaptiveHapticsScaling_scalesAmplitudesProperly() { + // No user settings scale. + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibrationEffect effect = VibrationEffect.createWaveform( @@ -277,6 +291,9 @@ public class VibrationThreadTest { @Test @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void vibrate_withVibrationParamsRequestStalling_timeoutRequestAndApplyNoScaling() { + // No user settings scale. + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibrationEffect effect = VibrationEffect.createWaveform( new long[]{5, 5, 5}, new int[]{1, 1, 1}, -1); @@ -1864,6 +1881,13 @@ public class VibrationThreadTest { } } + private void setUserSetting(String settingName, int value) { + Settings.System.putIntForUser( + mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT); + // FakeSettingsProvider doesn't support testing triggering ContentObserver yet. + mVibrationSettings.mSettingObserver.onChange(false); + } + private long startThreadAndDispatcher(VibrationEffect effect) { return startThreadAndDispatcher(CombinedVibration.createParallel(effect)); } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index f009229e216d..40135876303b 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -1622,7 +1622,12 @@ public class VibratorManagerServiceTest { vibrateAndWaitUntilFinished(service, vendorEffect, RINGTONE_ATTRS); - assertThat(fakeVibrator.getAllVendorEffects()).containsExactly(vendorEffect); + // Compare vendor data only, ignore scale applied by device settings in this test. + assertThat(fakeVibrator.getAllVendorEffects()).hasSize(1); + assertThat(fakeVibrator.getAllVendorEffects().get(0).getVendorData().keySet()) + .containsExactly("key"); + assertThat(fakeVibrator.getAllVendorEffects().get(0).getVendorData().getString("key")) + .isEqualTo("value"); } @Test @@ -1765,7 +1770,8 @@ public class VibratorManagerServiceTest { assertThat(fakeVibrator.getAllVendorEffects()).hasSize(1); VibrationEffect.VendorEffect scaled = fakeVibrator.getAllVendorEffects().get(0); assertThat(scaled.getEffectStrength()).isEqualTo(VibrationEffect.EFFECT_STRENGTH_LIGHT); - assertThat(scaled.getLinearScale()).isEqualTo(0.4f); + assertThat(scaled.getScale()).isAtMost(1); // Scale down or none if default is LOW + assertThat(scaled.getAdaptiveScale()).isEqualTo(0.4f); } @Test diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java index 96c3e97bc819..031d1c29a215 100644 --- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java +++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java @@ -140,13 +140,13 @@ public final class FakeVibratorControllerProvider { @Override public long performVendorEffect(Parcel vendorData, long strength, float scale, - long vibrationId) { + float adaptiveScale, long vibrationId) { if ((mCapabilities & IVibrator.CAP_PERFORM_VENDOR_EFFECTS) == 0) { return 0; } PersistableBundle bundle = PersistableBundle.CREATOR.createFromParcel(vendorData); recordVendorEffect(vibrationId, - new VibrationEffect.VendorEffect(bundle, (int) strength, scale)); + new VibrationEffect.VendorEffect(bundle, (int) strength, scale, adaptiveScale)); applyLatency(mOnLatency); scheduleListener(mVendorEffectDuration, vibrationId); // HAL has unknown duration for vendor effects. |