Fix usage filter over UNKNOWN vibration
The usageFilter parameter added to Vibrator.cancel is always cancelling UNKNOWN vibrations (usage = 0). The filter should only cancel them if the value is the same usage, or if all usages are being cancelled. Fix: 182440404 Test: VibratorManagerServiceTest Change-Id: Ibf33fe24e5253501e751b027cbf4b68564d82929
This commit is contained in:
@@ -146,7 +146,7 @@ public class SystemVibratorManager extends VibratorManager {
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelVibration(/* usageFilter= */ -1);
|
||||
cancelVibration(VibrationAttributes.USAGE_FILTER_MATCH_ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -62,6 +62,11 @@ public final class VibrationAttributes implements Parcelable {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Usage{}
|
||||
|
||||
/**
|
||||
* Vibration usage filter value to match all usages.
|
||||
* @hide
|
||||
*/
|
||||
public static final int USAGE_FILTER_MATCH_ALL = -1;
|
||||
/**
|
||||
* Vibration usage class value to use when the vibration usage class is unknown.
|
||||
*/
|
||||
|
||||
@@ -723,6 +723,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
|
||||
* VibrationAttributes.USAGE_* values.
|
||||
*/
|
||||
private boolean shouldCancelVibration(VibrationAttributes attrs, int usageFilter) {
|
||||
if (attrs.getUsage() == VibrationAttributes.USAGE_UNKNOWN) {
|
||||
// Special case, usage UNKNOWN would match all filters. Instead it should only match if
|
||||
// it's cancelling that usage specifically, or if cancelling all usages.
|
||||
return usageFilter == VibrationAttributes.USAGE_UNKNOWN
|
||||
|| usageFilter == VibrationAttributes.USAGE_FILTER_MATCH_ALL;
|
||||
}
|
||||
return (usageFilter & attrs.getUsage()) == attrs.getUsage();
|
||||
}
|
||||
|
||||
@@ -1535,7 +1541,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
|
||||
}
|
||||
|
||||
private int runCancel() {
|
||||
cancelVibrate(/* usageFilter= */ -1, mToken);
|
||||
cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, mToken);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ public class VibratorManagerServiceTest {
|
||||
CombinedVibration effect = CombinedVibration.createParallel(
|
||||
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
|
||||
vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS);
|
||||
service.cancelVibrate(/* usageFilter= */ -1, service);
|
||||
service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
|
||||
|
||||
assertTrue(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
|
||||
|
||||
@@ -889,13 +889,13 @@ public class VibratorManagerServiceTest {
|
||||
mockVibrators(1);
|
||||
VibratorManagerService service = createSystemReadyService();
|
||||
|
||||
service.cancelVibrate(/* usageFilter= */ -1, service);
|
||||
service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
|
||||
assertFalse(service.isVibrating(1));
|
||||
|
||||
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), ALARM_ATTRS);
|
||||
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
service.cancelVibrate(/* usageFilter= */ -1, service);
|
||||
service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
|
||||
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
}
|
||||
|
||||
@@ -924,6 +924,39 @@ public class VibratorManagerServiceTest {
|
||||
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelVibrate_withoutUnknownUsage_onlyStopsIfFilteringUnknownOrAllUsages()
|
||||
throws Exception {
|
||||
mockVibrators(1);
|
||||
VibrationAttributes attrs = new VibrationAttributes.Builder()
|
||||
.setUsage(VibrationAttributes.USAGE_UNKNOWN)
|
||||
.build();
|
||||
VibratorManagerService service = createSystemReadyService();
|
||||
|
||||
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), attrs);
|
||||
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
// Do not cancel UNKNOWN vibration when filter is being applied for other usages.
|
||||
service.cancelVibrate(VibrationAttributes.USAGE_RINGTONE, service);
|
||||
assertFalse(waitUntil(s -> !s.isVibrating(1), service, /* timeout= */ 50));
|
||||
|
||||
service.cancelVibrate(
|
||||
VibrationAttributes.USAGE_CLASS_ALARM | ~VibrationAttributes.USAGE_CLASS_MASK,
|
||||
service);
|
||||
assertFalse(waitUntil(s -> !s.isVibrating(1), service, /* timeout= */ 50));
|
||||
|
||||
// Cancel UNKNOWN vibration when filtered for that vibration specifically.
|
||||
service.cancelVibrate(VibrationAttributes.USAGE_UNKNOWN, service);
|
||||
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
vibrate(service, VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100), attrs);
|
||||
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
// Cancel UNKNOWN vibration when all vibrations are being cancelled.
|
||||
service.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, service);
|
||||
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
}
|
||||
|
||||
private void mockCapabilities(long... capabilities) {
|
||||
when(mNativeWrapperMock.getCapabilities()).thenReturn(
|
||||
Arrays.stream(capabilities).reduce(0, (a, b) -> a | b));
|
||||
|
||||
Reference in New Issue
Block a user