diff options
| -rw-r--r-- | core/java/android/os/SystemVibrator.java | 18 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/os/VibratorTest.java | 62 |
2 files changed, 69 insertions, 11 deletions
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index 6091bf9088d3..bf72b1d7a035 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.hardware.vibrator.IVibrator; import android.util.ArrayMap; import android.util.Log; import android.util.Range; @@ -313,8 +314,14 @@ public class SystemVibrator extends Vibrator { private static final float EPSILON = 1e-5f; public MultiVibratorInfo(VibratorInfo[] vibrators) { + // Need to use an extra constructor to share the computation in super initialization. + this(vibrators, frequencyProfileIntersection(vibrators)); + } + + private MultiVibratorInfo(VibratorInfo[] vibrators, + VibratorInfo.FrequencyProfile mergedProfile) { super(/* id= */ -1, - capabilitiesIntersection(vibrators), + capabilitiesIntersection(vibrators, mergedProfile.isEmpty()), supportedEffectsIntersection(vibrators), supportedBrakingIntersection(vibrators), supportedPrimitivesAndDurationsIntersection(vibrators), @@ -323,14 +330,19 @@ public class SystemVibrator extends Vibrator { integerLimitIntersection(vibrators, VibratorInfo::getPwlePrimitiveDurationMax), integerLimitIntersection(vibrators, VibratorInfo::getPwleSizeMax), floatPropertyIntersection(vibrators, VibratorInfo::getQFactor), - frequencyProfileIntersection(vibrators)); + mergedProfile); } - private static int capabilitiesIntersection(VibratorInfo[] infos) { + private static int capabilitiesIntersection(VibratorInfo[] infos, + boolean frequencyProfileIsEmpty) { int intersection = ~0; for (VibratorInfo info : infos) { intersection &= info.getCapabilities(); } + if (frequencyProfileIsEmpty) { + // Revoke frequency control if the merged frequency profile ended up empty. + intersection &= ~IVibrator.CAP_FREQUENCY_CONTROL; + } return intersection; } diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java index 7ebebc965d8d..c59a3f518da8 100644 --- a/core/tests/coretests/src/android/os/VibratorTest.java +++ b/core/tests/coretests/src/android/os/VibratorTest.java @@ -246,10 +246,12 @@ public class VibratorTest { @Test public void getQFactorAndResonantFrequency_differentValues_returnsNaN() { VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(1f) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, null)) .build(); VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(2f) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(2, 2, 2, null)) .build(); @@ -258,6 +260,7 @@ public class VibratorTest { assertTrue(Float.isNaN(info.getQFactor())); assertTrue(Float.isNaN(info.getResonantFrequencyHz())); + assertEmptyFrequencyProfileAndControl(info); // One vibrator with values undefined. VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 3).build(); @@ -266,16 +269,19 @@ public class VibratorTest { assertTrue(Float.isNaN(info.getQFactor())); assertTrue(Float.isNaN(info.getResonantFrequencyHz())); + assertEmptyFrequencyProfileAndControl(info); } @Test public void getQFactorAndResonantFrequency_sameValues_returnsValue() { VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(10f) .setFrequencyProfile(new VibratorInfo.FrequencyProfile( /* resonantFrequencyHz= */ 11, 10, 0.5f, null)) .build(); VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(10f) .setFrequencyProfile(new VibratorInfo.FrequencyProfile( /* resonantFrequencyHz= */ 11, 5, 1, null)) @@ -285,113 +291,131 @@ public class VibratorTest { assertEquals(10f, info.getQFactor(), TEST_TOLERANCE); assertEquals(11f, info.getResonantFrequencyHz(), TEST_TOLERANCE); + + // No frequency range defined. + assertTrue(info.getFrequencyProfile().isEmpty()); + assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); } @Test public void getFrequencyProfile_noVibrator_returnsEmpty() { VibratorInfo info = new SystemVibrator.NoVibratorInfo(); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); } @Test public void getFrequencyProfile_differentResonantFrequencyOrResolutionValues_returnsEmpty() { VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo differentResonantFrequency = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(2, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, differentResonantFrequency}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); VibratorInfo differentFrequencyResolution = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 2, new float[] { 0, 1 })) .build(); info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, differentFrequencyResolution}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); } @Test public void getFrequencyProfile_missingValues_returnsEmpty() { VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo missingResonantFrequency = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(Float.NaN, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, missingResonantFrequency}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); VibratorInfo missingMinFrequency = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, Float.NaN, 1, new float[] { 0, 1 })) .build(); info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, missingMinFrequency}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); VibratorInfo missingFrequencyResolution = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, Float.NaN, new float[] { 0, 1 })) .build(); info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, missingFrequencyResolution}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); VibratorInfo missingMaxAmplitudes = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, null)) .build(); info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, missingMaxAmplitudes}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); } @Test public void getFrequencyProfile_unalignedMaxAmplitudes_returnsEmpty() { VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10, 0.5f, new float[] { 0, 1, 1, 0 })) .build(); VibratorInfo unalignedMinFrequency = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.1f, 0.5f, new float[] { 0, 1, 1, 0 })) .build(); VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0, 1, 1, 0 })) .build(); VibratorInfo info = new SystemVibrator.MultiVibratorInfo( new VibratorInfo[]{firstVibrator, unalignedMinFrequency, thirdVibrator}); - assertTrue(info.getFrequencyProfile().isEmpty()); + assertEmptyFrequencyProfileAndControl(info); } @Test public void getFrequencyProfile_alignedProfiles_returnsIntersection() { VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10, 0.5f, new float[] { 0.5f, 1, 1, 0.5f })) .build(); VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 1, 1, 1 })) .build(); VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 3) + .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.8f, 0.5f })) .build(); @@ -401,6 +425,20 @@ public class VibratorTest { assertEquals( new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.5f }), info.getFrequencyProfile()); + assertEquals(true, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); + + // Third vibrator without frequency control capability. + thirdVibrator = new VibratorInfo.Builder(/* id= */ 3) + .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, + new float[] { 0.8f, 1, 0.8f, 0.5f })) + .build(); + info = new SystemVibrator.MultiVibratorInfo( + new VibratorInfo[]{firstVibrator, secondVibrator, thirdVibrator}); + + assertEquals( + new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.5f }), + info.getFrequencyProfile()); + assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); } @Test @@ -547,4 +585,12 @@ public class VibratorTest { VibrationAttributes vibrationAttributes = captor.getValue(); assertEquals(new VibrationAttributes.Builder().build(), vibrationAttributes); } + + /** + * Asserts that the frequency profile is empty, and therefore frequency control isn't supported. + */ + void assertEmptyFrequencyProfileAndControl(VibratorInfo info) { + assertTrue(info.getFrequencyProfile().isEmpty()); + assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); + } } |