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

Commit 7c85c529 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add support for vibration in session playback" into main

parents 4f2d2366 eb8f25c0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -112,6 +112,14 @@ abstract class AbstractVibratorStep extends Step {
    }

    protected void stopVibrating() {
        if (conductor.isInSession) {
            if (VibrationThread.DEBUG) {
                Slog.d(VibrationThread.TAG,
                        "Vibration in session, skipping request to turn off vibrator "
                                + getVibratorId());
            }
            return;
        }
        if (VibrationThread.DEBUG) {
            Slog.d(VibrationThread.TAG,
                    "Turning off vibrator " + getVibratorId());
+8 −3
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ final class VibrationStepConductor {
    // Used within steps.
    public final VibrationSettings vibrationSettings;
    public final VibrationThread.VibratorManagerHooks vibratorManagerHooks;
    public final boolean isInSession;

    private final DeviceAdapter mDeviceAdapter;
    private final VibrationScaler mVibrationScaler;
@@ -105,12 +106,13 @@ final class VibrationStepConductor {
    private int mRemainingStartSequentialEffectSteps;
    private int mSuccessfulVibratorOnSteps;

    VibrationStepConductor(HalVibration vib, VibrationSettings vibrationSettings,
            DeviceAdapter deviceAdapter, VibrationScaler vibrationScaler,
            VibratorFrameworkStatsLogger statsLogger,
    VibrationStepConductor(HalVibration vib, boolean isInSession,
            VibrationSettings vibrationSettings, DeviceAdapter deviceAdapter,
            VibrationScaler vibrationScaler, VibratorFrameworkStatsLogger statsLogger,
            CompletableFuture<Void> requestVibrationParamsFuture,
            VibrationThread.VibratorManagerHooks vibratorManagerHooks) {
        this.mVibration = vib;
        this.isInSession = isInSession;
        this.vibrationSettings = vibrationSettings;
        this.mDeviceAdapter = deviceAdapter;
        mVibrationScaler = vibrationScaler;
@@ -286,6 +288,9 @@ final class VibrationStepConductor {
        if (nextStep == null) {
            return true;  // Finished
        }
        if (isInSession) {
            return true;  // Don't wait to play session vibration steps
        }
        long waitMillis = nextStep.calculateWaitTime();
        if (waitMillis <= 0) {
            return true;  // Regular step ready
+3 −2
Original line number Diff line number Diff line
@@ -1114,8 +1114,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
                            mVibrationSettings.getRequestVibrationParamsTimeoutMs());
        }

        return new VibrationStepConductor(vib, mVibrationSettings, mDeviceAdapter, mVibrationScaler,
                mFrameworkStatsLogger, requestVibrationParamsFuture, mVibrationThreadCallbacks);
        return new VibrationStepConductor(vib, /* isInSession= */ false, mVibrationSettings,
                mDeviceAdapter, mVibrationScaler, mFrameworkStatsLogger,
                requestVibrationParamsFuture, mVibrationThreadCallbacks);
    }

    private Status startVibrationOnInputDevicesLocked(HalVibration vib) {
+62 −5
Original line number Diff line number Diff line
@@ -1913,6 +1913,55 @@ public class VibrationThreadTest {
                fakeVibrator.getEffectSegments(vibration5.id));
    }

    @Test
    public void vibrate_multipleVibratorsSequentialInSession_runsInOrderWithoutDelaysAndNoOffs() {
        mockVibrators(1, 2, 3);
        mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
        mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
        mVibratorProviders.get(2).setSupportedPrimitives(
                VibrationEffect.Composition.PRIMITIVE_CLICK);
        mVibratorProviders.get(3).setSupportedEffects(VibrationEffect.EFFECT_CLICK);

        CombinedVibration effect = CombinedVibration.startSequential()
                .addNext(3,
                        VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
                        /* delay= */ TEST_TIMEOUT_MILLIS)
                .addNext(1,
                        VibrationEffect.createWaveform(
                                new long[] {TEST_TIMEOUT_MILLIS, TEST_TIMEOUT_MILLIS},
                                /* repeat= */ -1),
                        /* delay= */ TEST_TIMEOUT_MILLIS)
                .addNext(2,
                        VibrationEffect.startComposition()
                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1,
                                        /* delay= */ TEST_TIMEOUT_MILLIS)
                                .compose(),
                        /* delay= */ TEST_TIMEOUT_MILLIS)
                .combine();
        HalVibration vibration = startThreadAndDispatcher(effect, /* isInSession= */ true);

        // Should not timeout as delays will not affect in session playback time.
        waitForCompletion();

        // Vibrating state remains ON until session resets it.
        verifyCallbacksTriggered(vibration, Status.FINISHED);
        assertTrue(mControllers.get(1).isVibrating());
        assertTrue(mControllers.get(2).isVibrating());
        assertTrue(mControllers.get(3).isVibrating());

        assertEquals(0, mVibratorProviders.get(1).getOffCount());
        assertEquals(0, mVibratorProviders.get(2).getOffCount());
        assertEquals(0, mVibratorProviders.get(3).getOffCount());
        assertEquals(Arrays.asList(expectedOneShot(TEST_TIMEOUT_MILLIS)),
                mVibratorProviders.get(1).getEffectSegments(vibration.id));
        assertEquals(expectedAmplitudes(255), mVibratorProviders.get(1).getAmplitudes());
        assertEquals(Arrays.asList(expectedPrimitive(
                VibrationEffect.Composition.PRIMITIVE_CLICK, 1, TEST_TIMEOUT_MILLIS)),
                mVibratorProviders.get(2).getEffectSegments(vibration.id));
        assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
                mVibratorProviders.get(3).getEffectSegments(vibration.id));
    }

    private void mockVibrators(int... vibratorIds) {
        for (int vibratorId : vibratorIds) {
            mVibratorProviders.put(vibratorId,
@@ -1935,8 +1984,14 @@ public class VibrationThreadTest {
        return startThreadAndDispatcher(createVibration(effect));
    }

    private HalVibration startThreadAndDispatcher(CombinedVibration effect, boolean isInSession) {
        return startThreadAndDispatcher(createVibration(effect), isInSession,
                /* requestVibrationParamsFuture= */ null);
    }

    private HalVibration startThreadAndDispatcher(HalVibration vib) {
        return startThreadAndDispatcher(vib, /* requestVibrationParamsFuture= */ null);
        return startThreadAndDispatcher(vib, /* isInSession= */ false,
                /* requestVibrationParamsFuture= */ null);
    }

    private HalVibration startThreadAndDispatcher(VibrationEffect effect,
@@ -1947,15 +2002,17 @@ public class VibrationThreadTest {
        HalVibration vib = new HalVibration(
                new CallerInfo(attrs, UID, DEVICE_ID, PACKAGE_NAME, "reason"),
                CombinedVibration.createParallel(effect));
        return startThreadAndDispatcher(vib, requestVibrationParamsFuture);
        return startThreadAndDispatcher(vib, /* isInSession= */ false,
                requestVibrationParamsFuture);
    }

    private HalVibration startThreadAndDispatcher(HalVibration vib,
    private HalVibration startThreadAndDispatcher(HalVibration vib, boolean isInSession,
            CompletableFuture<Void> requestVibrationParamsFuture) {
        mControllers = createVibratorControllers();
        DeviceAdapter deviceAdapter = new DeviceAdapter(mVibrationSettings, mControllers);
        mVibrationConductor = new VibrationStepConductor(vib, mVibrationSettings, deviceAdapter,
                mVibrationScaler, mStatsLoggerMock, requestVibrationParamsFuture, mManagerHooks);
        mVibrationConductor = new VibrationStepConductor(vib, isInSession, mVibrationSettings,
                deviceAdapter, mVibrationScaler, mStatsLoggerMock, requestVibrationParamsFuture,
                mManagerHooks);
        assertTrue(mThread.runVibrationOnVibrationThread(mVibrationConductor));
        return mVibrationConductor.getVibration();
    }