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

Commit 78a65802 authored by Lais Andrade's avatar Lais Andrade Committed by Android (Google) Code Review
Browse files

Merge "Fix VibrationThread handling of IVibrator errors" into main

parents 7649dfa9 8ecfc26c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -136,3 +136,13 @@ flag {
      purpose: PURPOSE_FEATURE
    }
}

flag {
    namespace: "haptics"
    name: "vibration_thread_handling_hal_failure"
    description: "Fixes how VibrationThread handled HAL failures"
    bug: "419572960"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -145,9 +145,10 @@ message VibrationProto {
        IGNORED_FROM_VIRTUAL_DEVICE = 26;
        IGNORED_ON_WIRELESS_CHARGER = 27;
        IGNORED_MISSING_PERMISSION = 28;
        IGNORED_INVALID_REQUEST = 31;
        CANCELLED_BY_APP_OPS = 29;
        CANCELLED_BY_FOREGROUND_USER = 30;
        IGNORED_INVALID_REQUEST = 31;
        IGNORED_ERROR_DISPATCHING = 32;
        reserved 17; // prev IGNORED_UNKNOWN_VIBRATION
    }
}
+41 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.vibrator;

import android.os.SystemClock;
import android.os.VibrationEffect;
import android.os.vibrator.Flags;

import java.util.List;

@@ -48,12 +49,45 @@ abstract class AbstractComposedVibratorStep extends AbstractVibratorStep {
        this.segmentIndex = index;
    }

    /**
     * Return the {@link VibrationStepConductor#nextVibrateStep} to start right away, skipping the
     * current segment from the effect.
     */
    protected List<Step> skipStep() {
        return Flags.vibrationThreadHandlingHalFailure()
                ? skipStep(SystemClock.uptimeMillis())
                // Preserve old behavior when fix is not enabled.
                : vibratorOnNextSteps(/* segmentsPlayed= */ 1);
    }

    /**
     * Return the {@link VibrationStepConductor#nextVibrateStep} to start at given time, skipping
     * the current segment from the effect.
     */
    protected List<Step> skipStep(long nextStartTime) {
        return nextSteps(nextStartTime, /* segmentsPlayed= */ 1);
    }

    /**
     * Return the {@link VibrationStepConductor#nextVibrateStep} with start and off timings
     * calculated from {@link #getVibratorOnDuration()} based on the current
     * {@link SystemClock#uptimeMillis()} and jumping all played segments from the effect.
     *
     * <p>This should be used when the vibrator result is responsible for the step execution timing,
     * and it will cancel the playback if the HAL result is unsupported or failure.
     */
    protected List<Step> nextSteps(int segmentsPlayed) {
    protected List<Step> vibratorOnNextSteps(int segmentsPlayed) {
        if (Flags.vibrationThreadHandlingHalFailure()) {
            if (mVibratorOnResult > 0) {
                // Vibrator was turned on by this step, with mVibratorOnResult as the duration.
                // Schedule next steps for right after the vibration finishes.
                long nextStartTime = SystemClock.uptimeMillis() + mVibratorOnResult;
                return nextSteps(nextStartTime, segmentsPlayed);
            } else {
                // Step unsupported or failed, cancel the vibration on this vibrator.
                return cancelStep();
            }
        }
        // Schedule next steps to run right away.
        long nextStartTime = SystemClock.uptimeMillis();
        if (mVibratorOnResult > 0) {
@@ -86,4 +120,10 @@ abstract class AbstractComposedVibratorStep extends AbstractVibratorStep {
                nextSegmentIndex, mPendingVibratorOffDeadline);
        return List.of(nextStep);
    }

    /** Return next steps for cancelling the vibration playback. */
    protected List<Step> cancelStep() {
        return List.of(new CompleteEffectVibratorStep(conductor, SystemClock.uptimeMillis(),
                /* cancelled= */ true, controller, /* pendingVibratorOffDeadline= */ 0));
    }
}
+2 −5
Original line number Diff line number Diff line
@@ -62,8 +62,7 @@ final class ComposePrimitivesVibratorStep extends AbstractComposedVibratorStep {
            if (primitives.isEmpty()) {
                Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePrimitivesStep: "
                        + effect.getSegments().get(segmentIndex));
                // Skip this step and play the next one right away.
                return nextSteps(/* segmentsPlayed= */ 1);
                return skipStep();
            }

            if (VibrationThread.DEBUG) {
@@ -77,9 +76,7 @@ final class ComposePrimitivesVibratorStep extends AbstractComposedVibratorStep {
            long vibratorOnResult = controller.on(primitivesArray, getVibration().id, stepId);
            handleVibratorOnResult(vibratorOnResult);
            getVibration().stats.reportComposePrimitives(vibratorOnResult, primitivesArray);

            // The next start and off times will be calculated from mVibratorOnResult.
            return nextSteps(/* segmentsPlayed= */ primitives.size());
            return vibratorOnNextSteps(/* segmentsPlayed= */ primitives.size());
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
        }
+3 −7
Original line number Diff line number Diff line
@@ -49,8 +49,7 @@ final class ComposePwleV2VibratorStep extends AbstractComposedVibratorStep {
    @Override
    public List<Step> play() {
        if (!Flags.normalizedPwleEffects()) {
            // Skip this step and play the next one right away.
            return nextSteps(/* segmentsPlayed= */ 1);
            return skipStep();
        }

        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "ComposePwleV2Step");
@@ -63,8 +62,7 @@ final class ComposePwleV2VibratorStep extends AbstractComposedVibratorStep {
            if (pwles.isEmpty()) {
                Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposeEnvelopeStep: "
                        + effect.getSegments().get(segmentIndex));
                // Skip this step and play the next one right away.
                return nextSteps(/* segmentsPlayed= */ 1);
                return skipStep();
            }

            if (VibrationThread.DEBUG) {
@@ -76,9 +74,7 @@ final class ComposePwleV2VibratorStep extends AbstractComposedVibratorStep {
            long vibratorOnResult = controller.on(pwlesArray, getVibration().id, stepId);
            handleVibratorOnResult(vibratorOnResult);
            getVibration().stats.reportComposePwle(vibratorOnResult, pwlesArray);

            // The next start and off times will be calculated from mVibratorOnResult.
            return nextSteps(/* segmentsPlayed= */ pwles.size());
            return vibratorOnNextSteps(/* segmentsPlayed= */ pwles.size());
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
        }
Loading