From 1d0e7393886ffe07b77a4f0cb82568ffa11d1766 Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Mon, 21 Mar 2022 19:18:37 +0000 Subject: [PATCH] Add cancelation reason to vibration status Add separate cancelation status enum values for Vibration to help debugging. The status is logged by the service dumpsys and can help identifying the cause for unexpectedly interrupted vibrations. Fix: 225940520 Test: manual Change-Id: I0012f2e075922f64122901894b6e8ff586c586a6 --- .../android/server/vibrator/Vibration.java | 8 ++- .../vibrator/VibrationStepConductor.java | 68 ++++++++++++------- .../vibrator/VibratorManagerService.java | 25 ++++--- .../server/vibrator/VibrationThreadTest.java | 62 +++++++++-------- 4 files changed, 100 insertions(+), 63 deletions(-) diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index f02f9f98d9332..8ecc51b3087cd 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -47,12 +47,16 @@ final class Vibration { FINISHED, FINISHED_UNEXPECTED, // Didn't terminate in the usual way. FORWARDED_TO_INPUT_DEVICES, - CANCELLED, + CANCELLED_BINDER_DIED, + CANCELLED_BY_SCREEN_OFF, + CANCELLED_BY_SETTINGS_UPDATE, + CANCELLED_BY_USER, + CANCELLED_BY_UNKNOWN_REASON, + CANCELLED_SUPERSEDED, IGNORED_ERROR_APP_OPS, IGNORED_ERROR_CANCELLING, IGNORED_ERROR_SCHEDULING, IGNORED_ERROR_TOKEN, - IGNORED, IGNORED_APP_OPS, IGNORED_BACKGROUND, IGNORED_UNKNOWN_VIBRATION, diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java index e12426b2b02c6..e3d806755c6e3 100644 --- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java +++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java @@ -79,12 +79,14 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { private final Object mLock = new Object(); @GuardedBy("mLock") private final IntArray mSignalVibratorsComplete; + @Nullable @GuardedBy("mLock") - private boolean mSignalCancel = false; + private Vibration.Status mSignalCancelStatus = null; @GuardedBy("mLock") private boolean mSignalCancelImmediate = false; - private boolean mCancelled = false; + @Nullable + private Vibration.Status mCancelStatus = null; private boolean mCancelledImmediately = false; // hard stop private int mPendingVibrateSteps; private int mRemainingStartSequentialEffectSteps; @@ -185,8 +187,8 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { expectIsVibrationThread(true); } - if (mCancelled) { - return Vibration.Status.CANCELLED; + if (mCancelStatus != null) { + return mCancelStatus; } if (mPendingVibrateSteps > 0 || mRemainingStartSequentialEffectSteps > 0) { @@ -303,7 +305,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { if (DEBUG) { Slog.d(TAG, "Binder died, cancelling vibration..."); } - notifyCancelled(/* immediate= */ false); + notifyCancelled(Vibration.Status.CANCELLED_BINDER_DIED, /* immediate= */ false); } /** @@ -312,22 +314,41 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { * * @param immediate indicates whether cancellation should abort urgently and skip cleanup steps. */ - public void notifyCancelled(boolean immediate) { + public void notifyCancelled(@NonNull Vibration.Status cancelStatus, boolean immediate) { if (Build.IS_DEBUGGABLE) { expectIsVibrationThread(false); } + if (DEBUG) { + Slog.d(TAG, "Vibration cancel requested with status=" + cancelStatus + + ", immediate=" + immediate); + } + if ((cancelStatus == null) || !cancelStatus.name().startsWith("CANCEL")) { + Slog.w(TAG, "Vibration cancel requested with bad status=" + cancelStatus + + ", using CANCELLED_UNKNOWN_REASON to ensure cancellation."); + cancelStatus = Vibration.Status.CANCELLED_BY_UNKNOWN_REASON; + } synchronized (mLock) { - if (immediate && mSignalCancelImmediate || mSignalCancel) { - // Nothing to update: already cancelled previously. + if (immediate && mSignalCancelImmediate || (mSignalCancelStatus != null)) { + if (DEBUG) { + Slog.d(TAG, "Vibration cancel request ignored as the vibration " + + mVibration.id + "is already being cancelled with status=" + + mSignalCancelStatus + ", immediate=" + mSignalCancelImmediate); + } return; } mSignalCancelImmediate |= immediate; - mSignalCancel = true; + if (mSignalCancelStatus == null) { + mSignalCancelStatus = cancelStatus; + } else { + if (DEBUG) { + Slog.d(TAG, "Vibration cancel request new status=" + cancelStatus + + " ignored as the vibration was already cancelled with status=" + + mSignalCancelStatus + ", but immediate flag was updated to " + + mSignalCancelImmediate); + } + } mLock.notify(); } - if (DEBUG) { - Slog.d(TAG, "Vibration cancel requested, immediate=" + immediate); - } } /** @@ -380,7 +401,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { if (Build.IS_DEBUGGABLE) { expectIsVibrationThread(true); // Reads VibrationThread variables as well as signals. } - return (mSignalCancel && !mCancelled) + return (mSignalCancelStatus != mCancelStatus) || (mSignalCancelImmediate && !mCancelledImmediately) || (mSignalVibratorsComplete.size() > 0); } @@ -395,7 +416,7 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { } int[] vibratorsToProcess = null; - boolean doCancel = false; + Vibration.Status doCancelStatus = null; boolean doCancelImmediate = false; // Collect signals to process, but don't keep the lock while processing them. synchronized (mLock) { @@ -405,9 +426,10 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { } // This should only happen once. doCancelImmediate = true; + doCancelStatus = mSignalCancelStatus; } - if (mSignalCancel && !mCancelled) { - doCancel = true; + if (mSignalCancelStatus != mCancelStatus) { + doCancelStatus = mSignalCancelStatus; } if (!doCancelImmediate && mSignalVibratorsComplete.size() > 0) { // Swap out the queue of completions to process. @@ -421,11 +443,11 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { // completion signals that were collected in this call, but we won't process them // anyway as all steps are cancelled. if (doCancelImmediate) { - processCancelImmediately(); + processCancelImmediately(doCancelStatus); return; } - if (doCancel) { - processCancel(); + if (doCancelStatus != null) { + processCancel(doCancelStatus); } if (vibratorsToProcess != null) { processVibratorsComplete(vibratorsToProcess); @@ -438,12 +460,12 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { *

This will remove all steps and replace them with respective results of * {@link Step#cancel()}. */ - public void processCancel() { + public void processCancel(Vibration.Status cancelStatus) { if (Build.IS_DEBUGGABLE) { expectIsVibrationThread(true); } - mCancelled = true; + mCancelStatus = cancelStatus; // Vibrator callbacks should wait until all steps from the queue are properly cancelled // and clean up steps are added back to the queue, so they can handle the callback. List cleanUpSteps = new ArrayList<>(); @@ -461,13 +483,13 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { * *

This will remove and trigger {@link Step#cancelImmediately()} in all steps, in order. */ - public void processCancelImmediately() { + public void processCancelImmediately(Vibration.Status cancelStatus) { if (Build.IS_DEBUGGABLE) { expectIsVibrationThread(true); } mCancelledImmediately = true; - mCancelled = true; + mCancelStatus = cancelStatus; Step step; while ((step = pollNext()) != null) { step.cancelImmediately(); diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 1260e5dbc9f71..96db6d30f98c7 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -162,10 +162,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // When the system is entering a non-interactive state, we want to cancel // vibrations in case a misbehaving app has abandoned them. if (shouldCancelOnScreenOffLocked(mNextVibration)) { - clearNextVibrationLocked(Vibration.Status.CANCELLED); + clearNextVibrationLocked(Vibration.Status.CANCELLED_BY_SCREEN_OFF); } if (shouldCancelOnScreenOffLocked(mCurrentVibration)) { - mCurrentVibration.notifyCancelled(/* immediate= */ false); + mCurrentVibration.notifyCancelled(Vibration.Status.CANCELLED_BY_SCREEN_OFF, + /* immediate= */ false); } } } @@ -420,7 +421,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { final long ident = Binder.clearCallingIdentity(); try { if (mCurrentVibration != null) { - mCurrentVibration.notifyCancelled(/* immediate= */ false); + mCurrentVibration.notifyCancelled(Vibration.Status.CANCELLED_SUPERSEDED, + /* immediate= */ false); } Vibration.Status status = startVibrationLocked(vib); if (status != Vibration.Status.RUNNING) { @@ -453,19 +455,20 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (mNextVibration != null && shouldCancelVibration(mNextVibration.getVibration(), usageFilter, token)) { - clearNextVibrationLocked(Vibration.Status.CANCELLED); + clearNextVibrationLocked(Vibration.Status.CANCELLED_BY_USER); } if (mCurrentVibration != null && shouldCancelVibration(mCurrentVibration.getVibration(), usageFilter, token)) { - mCurrentVibration.notifyCancelled(/* immediate= */false); + mCurrentVibration.notifyCancelled(Vibration.Status.CANCELLED_BY_USER, + /* immediate= */false); } if (mCurrentExternalVibration != null && shouldCancelVibration( mCurrentExternalVibration.externalVibration.getVibrationAttributes(), usageFilter)) { mCurrentExternalVibration.externalVibration.mute(); - endExternalVibrateLocked(Vibration.Status.CANCELLED, + endExternalVibrateLocked(Vibration.Status.CANCELLED_BY_USER, /* continueExternalControl= */ false); } } finally { @@ -594,7 +597,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Slog.d(TAG, "Canceling vibration because settings changed: " + (inputDevicesChanged ? "input devices changed" : ignoreStatus)); } - mCurrentVibration.notifyCancelled(/* immediate= */ false); + mCurrentVibration.notifyCancelled(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE, + /* immediate= */ false); } } } @@ -1313,7 +1317,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (DEBUG) { Slog.d(TAG, "External vibration finished because binder died"); } - endExternalVibrateLocked(Vibration.Status.CANCELLED, + endExternalVibrateLocked(Vibration.Status.CANCELLED_BINDER_DIED, /* continueExternalControl= */ false); } } @@ -1529,7 +1533,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // vibration that may be playing and ready the vibrator for external control. if (mCurrentVibration != null) { clearNextVibrationLocked(Vibration.Status.IGNORED_FOR_EXTERNAL); - mCurrentVibration.notifyCancelled(/* immediate= */ true); + mCurrentVibration.notifyCancelled(Vibration.Status.CANCELLED_SUPERSEDED, + /* immediate= */ true); waitForCompletion = true; } } else { @@ -1543,7 +1548,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // would need to mute the old one still if it came from a different controller. alreadyUnderExternalControl = true; mCurrentExternalVibration.externalVibration.mute(); - endExternalVibrateLocked(Vibration.Status.CANCELLED, + endExternalVibrateLocked(Vibration.Status.CANCELLED_SUPERSEDED, /* continueExternalControl= */ true); } mCurrentExternalVibration = new ExternalVibrationHolder(vib); diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java index 704729ea22c4d..9f135918daa2f 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java @@ -257,13 +257,13 @@ public class VibrationThreadTest { assertTrue(mThread.isRunningVibrationId(vibrationId)); assertTrue(mControllers.get(VIBRATOR_ID).isVibrating()); - conductor.notifyCancelled(/* immediate= */ false); + conductor.notifyCancelled(Vibration.Status.CANCELLED_SUPERSEDED, /* immediate= */ false); waitForCompletion(); assertFalse(mThread.isRunningVibrationId(vibrationId)); verify(mManagerHooks).noteVibratorOn(eq(UID), anyLong()); verify(mManagerHooks).noteVibratorOff(eq(UID)); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_SUPERSEDED); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); List playedAmplitudes = fakeVibrator.getAmplitudes(); @@ -288,10 +288,10 @@ public class VibrationThreadTest { VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect); assertTrue(waitUntil(() -> !fakeVibrator.getAmplitudes().isEmpty(), TEST_TIMEOUT_MILLIS)); - conductor.notifyCancelled(/* immediate= */ false); + conductor.notifyCancelled(Vibration.Status.CANCELLED_BY_USER, /* immediate= */ false); waitForCompletion(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); assertEquals(Arrays.asList(expectedOneShot(1000)), fakeVibrator.getEffectSegments(vibrationId)); @@ -310,10 +310,10 @@ public class VibrationThreadTest { VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect); assertTrue(waitUntil(() -> !fakeVibrator.getAmplitudes().isEmpty(), TEST_TIMEOUT_MILLIS)); - conductor.notifyCancelled(/* immediate= */ false); + conductor.notifyCancelled(Vibration.Status.CANCELLED_BY_USER, /* immediate= */ false); waitForCompletion(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); assertEquals(Arrays.asList(expectedOneShot(5550)), fakeVibrator.getEffectSegments(vibrationId)); @@ -334,10 +334,10 @@ public class VibrationThreadTest { assertTrue(waitUntil(() -> fakeVibrator.getAmplitudes().size() > 2 * amplitudes.length, 1000 + TEST_TIMEOUT_MILLIS)); - conductor.notifyCancelled(/* immediate= */ false); + conductor.notifyCancelled(Vibration.Status.CANCELLED_BY_USER, /* immediate= */ false); waitForCompletion(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); assertEquals(2, fakeVibrator.getEffectSegments(vibrationId).size()); // First time turn vibrator ON for minimum of 1s. @@ -371,13 +371,14 @@ public class VibrationThreadTest { // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. Thread cancellingThread = - new Thread(() -> conductor.notifyCancelled(/* immediate= */ false)); + new Thread(() -> conductor.notifyCancelled( + Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE, /* immediate= */ false)); cancellingThread.start(); waitForCompletion(/* timeout= */ 50); cancellingThread.join(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); } @@ -397,13 +398,14 @@ public class VibrationThreadTest { // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. Thread cancellingThread = - new Thread(() -> conductor.notifyCancelled(/* immediate= */ false)); + new Thread(() -> conductor.notifyCancelled( + Vibration.Status.CANCELLED_BY_SCREEN_OFF, /* immediate= */ false)); cancellingThread.start(); waitForCompletion(/* timeout= */ 50); cancellingThread.join(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); } @@ -647,7 +649,7 @@ public class VibrationThreadTest { waitForCompletion(); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BINDER_DIED); } @Test @@ -1043,7 +1045,8 @@ public class VibrationThreadTest { // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // fail at waitForCompletion(cancellingThread). Thread cancellingThread = new Thread( - () -> conductor.notifyCancelled(/* immediate= */ false)); + () -> conductor.notifyCancelled( + Vibration.Status.CANCELLED_BY_USER, /* immediate= */ false)); cancellingThread.start(); // Cancelling the vibration should be fast and return right away, even if the thread is @@ -1052,7 +1055,7 @@ public class VibrationThreadTest { // After the vibrator call ends the vibration is cancelled and the vibrator is turned off. waitForCompletion(/* timeout= */ latency + TEST_TIMEOUT_MILLIS); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); } @@ -1080,13 +1083,14 @@ public class VibrationThreadTest { // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. Thread cancellingThread = new Thread( - () -> conductor.notifyCancelled(/* immediate= */ false)); + () -> conductor.notifyCancelled( + Vibration.Status.CANCELLED_SUPERSEDED, /* immediate= */ false)); cancellingThread.start(); waitForCompletion(/* timeout= */ 50); cancellingThread.join(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_SUPERSEDED); assertFalse(mControllers.get(1).isVibrating()); assertFalse(mControllers.get(2).isVibrating()); } @@ -1113,13 +1117,14 @@ public class VibrationThreadTest { // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. Thread cancellingThread = - new Thread(() -> conductor.notifyCancelled(/* immediate= */ false)); + new Thread(() -> conductor.notifyCancelled( + Vibration.Status.CANCELLED_BY_SCREEN_OFF, /* immediate= */ false)); cancellingThread.start(); waitForCompletion(/* timeout= */ 50); cancellingThread.join(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_SCREEN_OFF); assertFalse(mControllers.get(1).isVibrating()); assertFalse(mControllers.get(2).isVibrating()); } @@ -1139,7 +1144,7 @@ public class VibrationThreadTest { verify(mVibrationToken).linkToDeath(same(conductor), eq(0)); verify(mVibrationToken).unlinkToDeath(same(conductor), eq(0)); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BINDER_DIED); assertFalse(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId).isEmpty()); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); } @@ -1193,12 +1198,13 @@ public class VibrationThreadTest { mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId)); // Will stop the ramp down right away. - conductor.notifyCancelled(/* immediate= */ true); + conductor.notifyCancelled( + Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE, /* immediate= */ true); waitForCompletion(); // Does not cancel already finished vibration, but releases vibrator. verify(mManagerHooks, never()).onVibrationCompleted(eq(vibrationId), - eq(Vibration.Status.CANCELLED)); + eq(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE)); verify(mManagerHooks).onVibrationThreadReleased(vibrationId); } @@ -1214,10 +1220,10 @@ public class VibrationThreadTest { VibrationStepConductor conductor = startThreadAndDispatcher(vibrationId, effect); assertTrue(waitUntil(() -> mControllers.get(VIBRATOR_ID).isVibrating(), TEST_TIMEOUT_MILLIS)); - conductor.notifyCancelled(/* immediate= */ false); + conductor.notifyCancelled(Vibration.Status.CANCELLED_BY_USER, /* immediate= */ false); waitForCompletion(); - verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED_BY_USER); // Duration extended for 10000 + 15. assertEquals(Arrays.asList(expectedOneShot(10_015)), @@ -1337,7 +1343,7 @@ public class VibrationThreadTest { VibrationStepConductor conductor2 = startThreadAndDispatcher(vibrationId2, effect2); // Effect2 won't complete on its own. Cancel it after a couple of repeats. Thread.sleep(150); // More than two TICKs. - conductor2.notifyCancelled(/* immediate= */ false); + conductor2.notifyCancelled(Vibration.Status.CANCELLED_BY_USER, /* immediate= */ false); waitForCompletion(); startThreadAndDispatcher(vibrationId3, effect3); @@ -1346,7 +1352,7 @@ public class VibrationThreadTest { // Effect4 is a long oneshot, but it gets cancelled as fast as possible. long start4 = System.currentTimeMillis(); VibrationStepConductor conductor4 = startThreadAndDispatcher(vibrationId4, effect4); - conductor4.notifyCancelled(/* immediate= */ true); + conductor4.notifyCancelled(Vibration.Status.CANCELLED_SUPERSEDED, /* immediate= */ true); waitForCompletion(); long duration4 = System.currentTimeMillis() - start4; @@ -1366,7 +1372,7 @@ public class VibrationThreadTest { // Effect2: repeating, cancelled. verify(mControllerCallbacks, atLeast(2)).onComplete(VIBRATOR_ID, vibrationId2); - verifyCallbacksTriggered(vibrationId2, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId2, Vibration.Status.CANCELLED_BY_USER); // The exact count of segments might vary, so just check that there's more than 2 and // all elements are the same segment. @@ -1384,7 +1390,7 @@ public class VibrationThreadTest { fakeVibrator.getEffectSegments(vibrationId3)); // Effect4: cancelled quickly. - verifyCallbacksTriggered(vibrationId4, Vibration.Status.CANCELLED); + verifyCallbacksTriggered(vibrationId4, Vibration.Status.CANCELLED_SUPERSEDED); assertTrue("Tested duration=" + duration4, duration4 < 2000); // Effect5: normal oneshot. Don't worry about amplitude, as effect4 may or may not have