From efc9cc93be7e1ea762f6eea4a695ab38e5efae4c Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Tue, 22 Jun 2021 13:03:17 +0100 Subject: [PATCH] Fix SystemVibrator constant support checks on device without vibrator Fix the implementation of SystemVibrator to return always no support to all effect and primitive constants on devices with no vibrator. Fix: 191414125 Test: FrameworksCoreTests:VibratorTest Change-Id: I0fd9e27d6e2890df9ee206029488ea70ff50712d --- core/java/android/os/SystemVibrator.java | 27 +++- .../src/android/os/VibratorTest.java | 119 ++++++++++++++++++ 2 files changed, 144 insertions(+), 2 deletions(-) diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index fd8948cbeea8d..0c3debb1b54ec 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -26,6 +26,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Objects; @@ -254,11 +255,14 @@ public class SystemVibrator extends Vibrator { *

This uses the first vibrator on the list as the default one for all hardware spec, but * uses an intersection of all vibrators to decide the capabilities and effect/primitive * support. + * + * @hide */ - private static class AllVibratorsInfo extends VibratorInfo { + @VisibleForTesting + public static class AllVibratorsInfo extends VibratorInfo { private final VibratorInfo[] mVibratorInfos; - AllVibratorsInfo(VibratorInfo[] vibrators) { + public AllVibratorsInfo(VibratorInfo[] vibrators) { super(/* id= */ -1, capabilitiesIntersection(vibrators), vibrators.length > 0 ? vibrators[0] : VibratorInfo.EMPTY_VIBRATOR_INFO); mVibratorInfos = vibrators; @@ -266,6 +270,9 @@ public class SystemVibrator extends Vibrator { @Override public int isEffectSupported(int effectId) { + if (mVibratorInfos.length == 0) { + return Vibrator.VIBRATION_EFFECT_SUPPORT_NO; + } int supported = Vibrator.VIBRATION_EFFECT_SUPPORT_YES; for (VibratorInfo info : mVibratorInfos) { int effectSupported = info.isEffectSupported(effectId); @@ -280,6 +287,9 @@ public class SystemVibrator extends Vibrator { @Override public boolean isPrimitiveSupported(int primitiveId) { + if (mVibratorInfos.length == 0) { + return false; + } for (VibratorInfo info : mVibratorInfos) { if (!info.isPrimitiveSupported(primitiveId)) { return false; @@ -288,6 +298,19 @@ public class SystemVibrator extends Vibrator { return true; } + @Override + public int getPrimitiveDuration(int primitiveId) { + int maxDuration = 0; + for (VibratorInfo info : mVibratorInfos) { + int duration = info.getPrimitiveDuration(primitiveId); + if (duration == 0) { + return 0; + } + maxDuration = Math.max(maxDuration, duration); + } + return maxDuration; + } + private static int capabilitiesIntersection(VibratorInfo[] infos) { if (infos.length == 0) { return 0; diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java index 8f9168b581842..0ece793c8125c 100644 --- a/core/tests/coretests/src/android/os/VibratorTest.java +++ b/core/tests/coretests/src/android/os/VibratorTest.java @@ -16,6 +16,8 @@ package android.os; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -26,6 +28,7 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.platform.test.annotations.Presubmit; @@ -69,6 +72,54 @@ public class VibratorTest { VibrationEffect.EFFECT_TICK}).length); } + @Test + public void areEffectsSupported_noVibrator_returnsAlwaysNo() { + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[0]); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + } + + @Test + public void areEffectsSupported_unsupportedInOneVibrator_returnsNo() { + VibratorInfo supportedVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setSupportedEffects(VibrationEffect.EFFECT_CLICK) + .build(); + VibratorInfo unsupportedVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setSupportedEffects(new int[0]) + .build(); + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{supportedVibrator, unsupportedVibrator}); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + } + + @Test + public void areEffectsSupported_unknownInOneVibrator_returnsUnknown() { + VibratorInfo supportedVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setSupportedEffects(VibrationEffect.EFFECT_CLICK) + .build(); + VibratorInfo unknownSupportVibrator = VibratorInfo.EMPTY_VIBRATOR_INFO; + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{supportedVibrator, unknownSupportVibrator}); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + } + + @Test + public void arePrimitivesSupported_supportedInAllVibrators_returnsYes() { + VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setSupportedEffects(VibrationEffect.EFFECT_CLICK) + .build(); + VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setSupportedEffects(VibrationEffect.EFFECT_CLICK) + .build(); + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{firstVibrator, secondVibrator}); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + } + @Test public void arePrimitivesSupported_returnsArrayOfSameSize() { assertEquals(0, mVibratorSpy.arePrimitivesSupported(new int[0]).length); @@ -79,6 +130,40 @@ public class VibratorTest { VibrationEffect.Composition.PRIMITIVE_QUICK_RISE}).length); } + @Test + public void arePrimitivesSupported_noVibrator_returnsAlwaysFalse() { + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[0]); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + + @Test + public void arePrimitivesSupported_unsupportedInOneVibrator_returnsFalse() { + VibratorInfo supportedVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) + .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10) + .build(); + VibratorInfo unsupportedVibrator = VibratorInfo.EMPTY_VIBRATOR_INFO; + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{supportedVibrator, unsupportedVibrator}); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + + @Test + public void arePrimitivesSupported_supportedInAllVibrators_returnsTrue() { + VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) + .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 5) + .build(); + VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) + .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 15) + .build(); + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{firstVibrator, secondVibrator}); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + @Test public void getPrimitivesDurations_returnsArrayOfSameSize() { assertEquals(0, mVibratorSpy.getPrimitiveDurations(new int[0]).length); @@ -89,6 +174,40 @@ public class VibratorTest { VibrationEffect.Composition.PRIMITIVE_QUICK_RISE}).length); } + @Test + public void getPrimitivesDurations_noVibrator_returnsAlwaysZero() { + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[0]); + assertEquals(0, info.getPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + + @Test + public void getPrimitivesDurations_unsupportedInOneVibrator_returnsZero() { + VibratorInfo supportedVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) + .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10) + .build(); + VibratorInfo unsupportedVibrator = VibratorInfo.EMPTY_VIBRATOR_INFO; + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{supportedVibrator, unsupportedVibrator}); + assertEquals(0, info.getPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + + @Test + public void getPrimitivesDurations_supportedInAllVibrators_returnsMaxDuration() { + VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) + .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10) + .build(); + VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) + .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 20) + .build(); + SystemVibrator.AllVibratorsInfo info = new SystemVibrator.AllVibratorsInfo( + new VibratorInfo[]{firstVibrator, secondVibrator}); + assertEquals(20, info.getPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + @Test public void vibrate_withAudioAttributes_createsVibrationAttributesWithSameUsage() { VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);