Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d39f47f3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use vibration id as callback reference in VibratorService"

parents 4c2e2872 122f12d0
Loading
Loading
Loading
Loading
+71 −57
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class VibratorService extends IVibratorService.Stub
        implements InputManager.InputDeviceListener {
@@ -114,6 +115,9 @@ public class VibratorService extends IVibratorService.Stub
    private static final VibrationAttributes DEFAULT_ATTRIBUTES =
            new VibrationAttributes.Builder().build();

    // Used to generate globally unique vibration ids.
    private final AtomicInteger mNextVibrationId = new AtomicInteger(1); // 0 = no callback

    // A mapping from the intensity adjustment to the scaling to apply, where the intensity
    // adjustment is defined as the delta between the default intensity level and the user selected
    // intensity level. It's important that we apply the scaling on the delta between the two so
@@ -171,34 +175,34 @@ public class VibratorService extends IVibratorService.Stub
    private int mRingIntensity;
    private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>();

    static native long vibratorInit();
    static native long vibratorInit(OnCompleteListener listener);

    static native long vibratorGetFinalizer();

    static native boolean vibratorExists(long controllerPtr);
    static native boolean vibratorExists(long nativeServicePtr);

    static native void vibratorOn(long controllerPtr, long milliseconds, Vibration vibration);
    static native void vibratorOn(long nativeServicePtr, long milliseconds, long vibrationId);

    static native void vibratorOff(long controllerPtr);
    static native void vibratorOff(long nativeServicePtr);

    static native void vibratorSetAmplitude(long controllerPtr, int amplitude);
    static native void vibratorSetAmplitude(long nativeServicePtr, int amplitude);

    static native int[] vibratorGetSupportedEffects(long controllerPtr);
    static native int[] vibratorGetSupportedEffects(long nativeServicePtr);

    static native int[] vibratorGetSupportedPrimitives(long controllerPtr);
    static native int[] vibratorGetSupportedPrimitives(long nativeServicePtr);

    static native long vibratorPerformEffect(
            long controllerPtr, long effect, long strength, Vibration vibration);
            long nativeServicePtr, long effect, long strength, long vibrationId);

    static native void vibratorPerformComposedEffect(long controllerPtr,
            VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration);
    static native void vibratorPerformComposedEffect(long nativeServicePtr,
            VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId);

    static native void vibratorSetExternalControl(long controllerPtr, boolean enabled);
    static native void vibratorSetExternalControl(long nativeServicePtr, boolean enabled);

    static native long vibratorGetCapabilities(long controllerPtr);
    static native void vibratorAlwaysOnEnable(long controllerPtr, long id, long effect,
    static native long vibratorGetCapabilities(long nativeServicePtr);
    static native void vibratorAlwaysOnEnable(long nativeServicePtr, long id, long effect,
            long strength);
    static native void vibratorAlwaysOnDisable(long controllerPtr, long id);
    static native void vibratorAlwaysOnDisable(long nativeServicePtr, long id);

    private final IUidObserver mUidObserver = new IUidObserver.Stub() {
        @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
@@ -220,12 +224,19 @@ public class VibratorService extends IVibratorService.Stub
        }
    };

    /** Listener for vibration completion callbacks from native. */
    public interface OnCompleteListener {

        /** Callback triggered when vibration is complete, identified by {@link Vibration#id}. */
        void onComplete(long vibrationId);
    }

    /**
     * Holder for a vibration to be played. This class can be shared with native methods for
     * hardware callback support.
     */
    @VisibleForTesting
    public final class Vibration implements IBinder.DeathRecipient {
    private final class Vibration implements IBinder.DeathRecipient {

        public final IBinder token;
        // Start time in CLOCK_BOOTTIME base.
        public final long startTime;
@@ -234,6 +245,7 @@ public class VibratorService extends IVibratorService.Stub
        // not to be affected by discontinuities created by RTC adjustments.
        public final long startTimeDebug;
        public final VibrationAttributes attrs;
        public final long id;
        public final int uid;
        public final String opPkg;
        public final String reason;
@@ -248,6 +260,7 @@ public class VibratorService extends IVibratorService.Stub
                VibrationAttributes attrs, int uid, String opPkg, String reason) {
            this.token = token;
            this.effect = effect;
            this.id = mNextVibrationId.getAndIncrement();
            this.startTime = SystemClock.elapsedRealtime();
            this.startTimeDebug = System.currentTimeMillis();
            this.attrs = attrs;
@@ -268,19 +281,6 @@ public class VibratorService extends IVibratorService.Stub
            }
        }

        /** Callback for when vibration is complete, to be called by native. */
        @VisibleForTesting
        public void onComplete() {
            synchronized (mLock) {
                if (this == mCurrentVibration) {
                    if (DEBUG) {
                        Slog.d(TAG, "Vibration finished by callback, cleaning up");
                    }
                    doCancelVibrateLocked();
                }
            }
        }

        public boolean hasTimeoutLongerThan(long millis) {
            final long duration = effect.getDuration();
            return duration >= 0 && duration > millis;
@@ -385,14 +385,14 @@ public class VibratorService extends IVibratorService.Stub
        mNativeWrapper = injector.getNativeWrapper();
        mH = injector.createHandler(Looper.myLooper());

        long controllerPtr = mNativeWrapper.vibratorInit();
        long nativeServicePtr = mNativeWrapper.vibratorInit(this::onVibrationComplete);
        long finalizerPtr = mNativeWrapper.vibratorGetFinalizer();

        if (finalizerPtr != 0) {
            NativeAllocationRegistry registry =
                    NativeAllocationRegistry.createMalloced(
                            VibratorService.class.getClassLoader(), finalizerPtr);
            registry.registerNativeAllocation(this, controllerPtr);
            registry.registerNativeAllocation(this, nativeServicePtr);
        }

        // Reset the hardware to a default state, in case this is a runtime
@@ -549,6 +549,19 @@ public class VibratorService extends IVibratorService.Stub
        }
    }

    /** Callback for when vibration is complete, to be called by native. */
    @VisibleForTesting
    public void onVibrationComplete(long vibrationId) {
        synchronized (mLock) {
            if (mCurrentVibration != null && mCurrentVibration.id == vibrationId) {
                if (DEBUG) {
                    Slog.d(TAG, "Vibration finished by callback, cleaning up");
                }
                doCancelVibrateLocked();
            }
        }
    }

    @Override // Binder call
    public boolean hasVibrator() {
        return doVibratorExists();
@@ -1266,18 +1279,18 @@ public class VibratorService extends IVibratorService.Stub
        return mNativeWrapper.vibratorExists();
    }

    /** Vibrates with native callback trigger for {@link Vibration#onComplete()}. */
    /** Vibrates with native callback trigger for {@link #onVibrationComplete(long)}. */
    private void doVibratorOn(long millis, int amplitude, Vibration vib) {
        doVibratorOn(millis, amplitude, vib.uid, vib.attrs, vib);
        doVibratorOn(millis, amplitude, vib.uid, vib.attrs, vib.id);
    }

    /** Vibrates without native callback. */
    private void doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs) {
        doVibratorOn(millis, amplitude, uid, attrs, /* vib= */ null);
        doVibratorOn(millis, amplitude, uid, attrs, /* vibrationId= */ 0);
    }

    private void doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs,
            @Nullable Vibration vib) {
            long vibrationId) {
        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOn");
        try {
            synchronized (mInputDeviceVibrators) {
@@ -1299,7 +1312,7 @@ public class VibratorService extends IVibratorService.Stub
                    // Note: ordering is important here! Many haptic drivers will reset their
                    // amplitude when enabled, so we always have to enable first, then set the
                    // amplitude.
                    mNativeWrapper.vibratorOn(millis, vib);
                    mNativeWrapper.vibratorOn(millis, vibrationId);
                    doVibratorSetAmplitude(amplitude);
                }
            }
@@ -1348,7 +1361,7 @@ public class VibratorService extends IVibratorService.Stub
            // Input devices don't support prebaked effect, so skip trying it with them.
            if (!usingInputDeviceVibrators) {
                long duration = mNativeWrapper.vibratorPerformEffect(
                        prebaked.getId(), prebaked.getEffectStrength(), vib);
                        prebaked.getId(), prebaked.getEffectStrength(), vib.id);
                if (duration > 0) {
                    noteVibratorOnLocked(vib.uid, duration);
                    return;
@@ -1395,7 +1408,7 @@ public class VibratorService extends IVibratorService.Stub

            PrimitiveEffect[] primitiveEffects =
                    composed.getPrimitiveEffects().toArray(new PrimitiveEffect[0]);
            mNativeWrapper.vibratorPerformComposedEffect(primitiveEffects, vib);
            mNativeWrapper.vibratorPerformComposedEffect(primitiveEffects, vib.id);

            // Composed effects don't actually give us an estimated duration, so we just guess here.
            noteVibratorOnLocked(vib.uid, 10 * primitiveEffects.length);
@@ -1726,20 +1739,20 @@ public class VibratorService extends IVibratorService.Stub
    @VisibleForTesting
    public static class NativeWrapper {

        private long mNativeControllerPtr = 0;
        private long mNativeServicePtr = 0;

        /** Checks if vibrator exists on device. */
        public boolean vibratorExists() {
            return VibratorService.vibratorExists(mNativeControllerPtr);
            return VibratorService.vibratorExists(mNativeServicePtr);
        }

        /**
         * Returns native pointer to newly created controller and initializes connection to vibrator
         * HAL service.
         */
        public long vibratorInit() {
            mNativeControllerPtr = VibratorService.vibratorInit();
            return mNativeControllerPtr;
        public long vibratorInit(OnCompleteListener listener) {
            mNativeServicePtr = VibratorService.vibratorInit(listener);
            return mNativeServicePtr;
        }

        /** Returns pointer to native finalizer function to be called by GC. */
@@ -1748,60 +1761,61 @@ public class VibratorService extends IVibratorService.Stub
        }

        /** Turns vibrator on for given time. */
        public void vibratorOn(long milliseconds, @Nullable Vibration vibration) {
            VibratorService.vibratorOn(mNativeControllerPtr, milliseconds, vibration);
        public void vibratorOn(long milliseconds, long vibrationId) {
            VibratorService.vibratorOn(mNativeServicePtr, milliseconds, vibrationId);
        }

        /** Turns vibrator off. */
        public void vibratorOff() {
            VibratorService.vibratorOff(mNativeControllerPtr);
            VibratorService.vibratorOff(mNativeServicePtr);
        }

        /** Sets the amplitude for the vibrator to run. */
        public void vibratorSetAmplitude(int amplitude) {
            VibratorService.vibratorSetAmplitude(mNativeControllerPtr, amplitude);
            VibratorService.vibratorSetAmplitude(mNativeServicePtr, amplitude);
        }

        /** Returns all predefined effects supported by the device vibrator. */
        public int[] vibratorGetSupportedEffects() {
            return VibratorService.vibratorGetSupportedEffects(mNativeControllerPtr);
            return VibratorService.vibratorGetSupportedEffects(mNativeServicePtr);
        }

        /** Returns all compose primitives supported by the device vibrator. */
        public int[] vibratorGetSupportedPrimitives() {
            return VibratorService.vibratorGetSupportedPrimitives(mNativeControllerPtr);
            return VibratorService.vibratorGetSupportedPrimitives(mNativeServicePtr);
        }

        /** Turns vibrator on to perform one of the supported effects. */
        public long vibratorPerformEffect(long effect, long strength, Vibration vibration) {
        public long vibratorPerformEffect(long effect, long strength, long vibrationId) {
            return VibratorService.vibratorPerformEffect(
                    mNativeControllerPtr, effect, strength, vibration);
                    mNativeServicePtr, effect, strength, vibrationId);
        }

        /** Turns vibrator on to perform one of the supported composed effects. */
        public void vibratorPerformComposedEffect(
                VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration) {
            VibratorService.vibratorPerformComposedEffect(mNativeControllerPtr, effect, vibration);
                VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId) {
            VibratorService.vibratorPerformComposedEffect(mNativeServicePtr, effect,
                    vibrationId);
        }

        /** Enabled the device vibrator to be controlled by another service. */
        public void vibratorSetExternalControl(boolean enabled) {
            VibratorService.vibratorSetExternalControl(mNativeControllerPtr, enabled);
            VibratorService.vibratorSetExternalControl(mNativeServicePtr, enabled);
        }

        /** Returns all capabilities of the device vibrator. */
        public long vibratorGetCapabilities() {
            return VibratorService.vibratorGetCapabilities(mNativeControllerPtr);
            return VibratorService.vibratorGetCapabilities(mNativeServicePtr);
        }

        /** Enable always-on vibration with given id and effect. */
        public void vibratorAlwaysOnEnable(long id, long effect, long strength) {
            VibratorService.vibratorAlwaysOnEnable(mNativeControllerPtr, id, effect, strength);
            VibratorService.vibratorAlwaysOnEnable(mNativeServicePtr, id, effect, strength);
        }

        /** Disable always-on vibration for given id. */
        public void vibratorAlwaysOnDisable(long id) {
            VibratorService.vibratorAlwaysOnDisable(mNativeControllerPtr, id);
            VibratorService.vibratorAlwaysOnDisable(mNativeServicePtr, id);
        }
    }

+121 −111

File changed.

Preview size limit exceeded, changes collapsed.

+30 −59
Original line number Diff line number Diff line
@@ -20,12 +20,13 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.gt;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.intThat;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
@@ -167,7 +168,7 @@ public class VibratorServiceTest {
    @Test
    public void createService_initializesNativeService() {
        createService();
        verify(mNativeWrapperMock).vibratorInit();
        verify(mNativeWrapperMock).vibratorInit(notNull());
        verify(mNativeWrapperMock).vibratorOff();
    }

@@ -294,7 +295,7 @@ public class VibratorServiceTest {
        assertTrue(service.isVibrating());

        verify(mNativeWrapperMock).vibratorOff();
        verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class));
        verify(mNativeWrapperMock).vibratorOn(eq(100L), gt(0L));
        verify(mNativeWrapperMock).vibratorSetAmplitude(eq(128));
    }

@@ -307,7 +308,7 @@ public class VibratorServiceTest {
        assertTrue(service.isVibrating());

        verify(mNativeWrapperMock).vibratorOff();
        verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class));
        verify(mNativeWrapperMock).vibratorOn(eq(100L), gt(0L));
        verify(mNativeWrapperMock, never()).vibratorSetAmplitude(anyInt());
    }

@@ -321,10 +322,8 @@ public class VibratorServiceTest {
        vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));

        verify(mNativeWrapperMock).vibratorOff();
        verify(mNativeWrapperMock).vibratorPerformEffect(
                eq((long) VibrationEffect.EFFECT_CLICK),
                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG),
                any(VibratorService.Vibration.class));
        verify(mNativeWrapperMock).vibratorPerformEffect(eq((long) VibrationEffect.EFFECT_CLICK),
                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), gt(0L));
    }

    @Test
@@ -343,7 +342,7 @@ public class VibratorServiceTest {

        verify(mNativeWrapperMock).vibratorOff();
        verify(mNativeWrapperMock).vibratorPerformComposedEffect(
                primitivesCaptor.capture(), any(VibratorService.Vibration.class));
                primitivesCaptor.capture(), gt(0L));

        // Check all primitive effect fields are passed down to the HAL.
        assertEquals(1, primitivesCaptor.getValue().length);
@@ -368,7 +367,7 @@ public class VibratorServiceTest {

        // Wait for VibrateThread to turn vibrator ON with total timing and no callback.
        Thread.sleep(5);
        verify(mNativeWrapperMock).vibratorOn(eq(30L), isNull());
        verify(mNativeWrapperMock).vibratorOn(eq(30L), eq(0L));

        // First amplitude set right away.
        verify(mNativeWrapperMock).vibratorSetAmplitude(eq(100));
@@ -384,11 +383,11 @@ public class VibratorServiceTest {

    @Test
    public void vibrate_withOneShotAndNativeCallbackTriggered_finishesVibration() {
        VibratorService service = createService();
        doAnswer(invocation -> {
            ((VibratorService.Vibration) invocation.getArgument(1)).onComplete();
            service.onVibrationComplete(invocation.getArgument(1));
            return null;
        }).when(mNativeWrapperMock).vibratorOn(anyLong(), any(VibratorService.Vibration.class));
        VibratorService service = createService();
        }).when(mNativeWrapperMock).vibratorOn(anyLong(), anyLong());
        Mockito.clearInvocations(mNativeWrapperMock);

        vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
@@ -396,7 +395,7 @@ public class VibratorServiceTest {
        InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(100L),
                any(VibratorService.Vibration.class));
                gt(0L));
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
    }

@@ -404,12 +403,11 @@ public class VibratorServiceTest {
    public void vibrate_withPrebakedAndNativeCallbackTriggered_finishesVibration() {
        when(mNativeWrapperMock.vibratorGetSupportedEffects())
                .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK});
        VibratorService service = createService();
        doAnswer(invocation -> {
            ((VibratorService.Vibration) invocation.getArgument(2)).onComplete();
            service.onVibrationComplete(invocation.getArgument(2));
            return 10_000L; // 10s
        }).when(mNativeWrapperMock).vibratorPerformEffect(
                anyLong(), anyLong(), any(VibratorService.Vibration.class));
        VibratorService service = createService();
        }).when(mNativeWrapperMock).vibratorPerformEffect(anyLong(), anyLong(), anyLong());
        Mockito.clearInvocations(mNativeWrapperMock);

        vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
@@ -419,7 +417,7 @@ public class VibratorServiceTest {
        inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformEffect(
                eq((long) VibrationEffect.EFFECT_CLICK),
                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG),
                any(VibratorService.Vibration.class));
                gt(0L));
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
    }

@@ -436,44 +434,19 @@ public class VibratorServiceTest {
        Thread.sleep(15);
        InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(3L), isNull());
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(2L), isNull());
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(3L), eq(0L));
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(2L), eq(0L));
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
    }

    @Test
    public void vibrate_withComposedAndNativeCallbackTriggered_finishesVibration() {
        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
        doAnswer(invocation -> {
            ((VibratorService.Vibration) invocation.getArgument(1)).onComplete();
            return null;
        }).when(mNativeWrapperMock).vibratorPerformComposedEffect(
                any(), any(VibratorService.Vibration.class));
        VibratorService service = createService();
        Mockito.clearInvocations(mNativeWrapperMock);

        VibrationEffect effect = VibrationEffect.startComposition()
                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 10)
                .compose();
        vibrate(service, effect);

        InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
        inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformComposedEffect(
                any(VibrationEffect.Composition.PrimitiveEffect[].class),
                any(VibratorService.Vibration.class));
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
    }

    @Test
    public void vibrate_whenBinderDies_cancelsVibration() {
        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
        doAnswer(invocation -> {
            ((VibratorService.Vibration) invocation.getArgument(1)).binderDied();
            service.onVibrationComplete(invocation.getArgument(1));
            return null;
        }).when(mNativeWrapperMock).vibratorPerformComposedEffect(
                any(), any(VibratorService.Vibration.class));
        VibratorService service = createService();
        }).when(mNativeWrapperMock).vibratorPerformComposedEffect(any(), anyLong());
        Mockito.clearInvocations(mNativeWrapperMock);

        VibrationEffect effect = VibrationEffect.startComposition()
@@ -484,8 +457,7 @@ public class VibratorServiceTest {
        InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
        inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformComposedEffect(
                any(VibrationEffect.Composition.PrimitiveEffect[].class),
                any(VibratorService.Vibration.class));
                any(VibrationEffect.Composition.PrimitiveEffect[].class), gt(0L));
        inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
    }

@@ -513,12 +485,11 @@ public class VibratorServiceTest {

    @Test
    public void registerVibratorStateListener_callbacksAreTriggered() throws Exception {
        VibratorService service = createService();
        doAnswer(invocation -> {
            ((VibratorService.Vibration) invocation.getArgument(1)).onComplete();
            service.onVibrationComplete(invocation.getArgument(1));
            return null;
        }).when(mNativeWrapperMock).vibratorOn(anyLong(), any(VibratorService.Vibration.class));
        VibratorService service = createService();

        }).when(mNativeWrapperMock).vibratorOn(anyLong(), anyLong());
        service.registerVibratorStateListener(mVibratorStateListenerMock);
        verify(mVibratorStateListenerMock).onVibrating(false);
        Mockito.clearInvocations(mVibratorStateListenerMock);
@@ -569,15 +540,15 @@ public class VibratorServiceTest {

        verify(mNativeWrapperMock).vibratorPerformEffect(
                eq((long) VibrationEffect.EFFECT_CLICK),
                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), any());
                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), anyLong());
        verify(mNativeWrapperMock).vibratorPerformEffect(
                eq((long) VibrationEffect.EFFECT_TICK),
                eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), any());
                eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), anyLong());
        verify(mNativeWrapperMock).vibratorPerformEffect(
                eq((long) VibrationEffect.EFFECT_DOUBLE_CLICK),
                eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), any());
                eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), anyLong());
        verify(mNativeWrapperMock, never()).vibratorPerformEffect(
                eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), any());
                eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), anyLong());
    }

    @Test
@@ -644,7 +615,7 @@ public class VibratorServiceTest {

        // Ringtone vibration is off, so only the other 3 are propagated to native.
        verify(mNativeWrapperMock, times(3)).vibratorPerformComposedEffect(
                primitivesCaptor.capture(), any());
                primitivesCaptor.capture(), anyLong());

        List<VibrationEffect.Composition.PrimitiveEffect[]> values =
                primitivesCaptor.getAllValues();