Loading services/core/java/com/android/server/vibrator/AbstractVibratorStep.java +56 −36 Original line number Diff line number Diff line Loading @@ -31,9 +31,9 @@ abstract class AbstractVibratorStep extends Step { public final VibratorController controller; public final VibrationEffect.Composed effect; public final int segmentIndex; public final long previousStepVibratorOffTimeout; long mVibratorOnResult; long mPendingVibratorOffDeadline; boolean mVibratorCompleteCallbackReceived; /** Loading @@ -43,19 +43,19 @@ abstract class AbstractVibratorStep extends Step { * @param controller The vibrator that is playing the effect. * @param effect The effect being played in this step. * @param index The index of the next segment to be played by this step * @param previousStepVibratorOffTimeout The time the vibrator is expected to complete any * @param pendingVibratorOffDeadline The time the vibrator is expected to complete any * previous vibration and turn off. This is used to allow this step to * be triggered when the completion callback is received, and can * be used to play effects back-to-back. */ AbstractVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { super(conductor, startTime); this.controller = controller; this.effect = effect; this.segmentIndex = index; this.previousStepVibratorOffTimeout = previousStepVibratorOffTimeout; mPendingVibratorOffDeadline = pendingVibratorOffDeadline; } public int getVibratorId() { Loading @@ -69,27 +69,57 @@ abstract class AbstractVibratorStep extends Step { @Override public boolean acceptVibratorCompleteCallback(int vibratorId) { boolean isSameVibrator = controller.getVibratorInfo().getId() == vibratorId; mVibratorCompleteCallbackReceived |= isSameVibrator; if (getVibratorId() != vibratorId) { return false; } // Only activate this step if a timeout was set to wait for the vibration to complete, // otherwise we are waiting for the correct time to play the next step. return isSameVibrator && (previousStepVibratorOffTimeout > SystemClock.uptimeMillis()); boolean shouldAcceptCallback = mPendingVibratorOffDeadline > SystemClock.uptimeMillis(); if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Received completion callback from " + vibratorId + ", accepted = " + shouldAcceptCallback); } // The callback indicates this vibrator has stopped, reset the timeout. mPendingVibratorOffDeadline = 0; mVibratorCompleteCallbackReceived = true; return shouldAcceptCallback; } @Override public List<Step> cancel() { return Arrays.asList(new CompleteEffectVibratorStep(conductor, SystemClock.uptimeMillis(), /* cancelled= */ true, controller, previousStepVibratorOffTimeout)); /* cancelled= */ true, controller, mPendingVibratorOffDeadline)); } @Override public void cancelImmediately() { if (previousStepVibratorOffTimeout > SystemClock.uptimeMillis()) { if (mPendingVibratorOffDeadline > SystemClock.uptimeMillis()) { // Vibrator might be running from previous steps, so turn it off while canceling. stopVibrating(); } } protected long handleVibratorOnResult(long vibratorOnResult) { mVibratorOnResult = vibratorOnResult; if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Turned on vibrator " + getVibratorId() + ", result = " + mVibratorOnResult); } if (mVibratorOnResult > 0) { // Vibrator was turned on by this step, with vibratorOnResult as the duration. // Set an extra timeout to wait for the vibrator completion callback. mPendingVibratorOffDeadline = SystemClock.uptimeMillis() + mVibratorOnResult + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT; } else { // Vibrator does not support the request or failed to turn on, reset callback deadline. mPendingVibratorOffDeadline = 0; } return mVibratorOnResult; } protected void stopVibrating() { if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, Loading @@ -97,6 +127,7 @@ abstract class AbstractVibratorStep extends Step { } controller.off(); getVibration().stats().reportVibratorOff(); mPendingVibratorOffDeadline = 0; } protected void changeAmplitude(float amplitude) { Loading @@ -109,40 +140,29 @@ abstract class AbstractVibratorStep extends Step { } /** * Return the {@link VibrationStepConductor#nextVibrateStep} with same timings, only jumping * the segments. */ protected List<Step> skipToNextSteps(int segmentsSkipped) { return nextSteps(startTime, previousStepVibratorOffTimeout, segmentsSkipped); } /** * Return the {@link VibrationStepConductor#nextVibrateStep} with same start and off timings * calculated from {@link #getVibratorOnDuration()}, jumping all played segments. * * <p>This method has same behavior as {@link #skipToNextSteps(int)} when the vibrator * result is non-positive, meaning the vibrator has either ignored or failed to turn on. * 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. */ protected List<Step> nextSteps(int segmentsPlayed) { if (mVibratorOnResult <= 0) { // Vibration was not started, so just skip the played segments and keep timings. return skipToNextSteps(segmentsPlayed); // Schedule next steps to run right away. long nextStartTime = SystemClock.uptimeMillis(); if (mVibratorOnResult > 0) { // Vibrator was turned on by this step, with mVibratorOnResult as the duration. // Schedule next steps for right after the vibration finishes. nextStartTime += mVibratorOnResult; } long nextStartTime = SystemClock.uptimeMillis() + mVibratorOnResult; long nextVibratorOffTimeout = nextStartTime + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT; return nextSteps(nextStartTime, nextVibratorOffTimeout, segmentsPlayed); return nextSteps(nextStartTime, segmentsPlayed); } /** * Return the {@link VibrationStepConductor#nextVibrateStep} with given start and off timings, * which might be calculated independently, jumping all played segments. * Return the {@link VibrationStepConductor#nextVibrateStep} with given start time, * which might be calculated independently, and jumping all played segments from the effect. * * <p>This should be used when the vibrator on/off state is not responsible for the steps * execution timings, e.g. while playing the vibrator amplitudes. * <p>This should be used when the vibrator on/off state is not responsible for the step * execution timing, e.g. while playing the vibrator amplitudes. */ protected List<Step> nextSteps(long nextStartTime, long vibratorOffTimeout, int segmentsPlayed) { protected List<Step> nextSteps(long nextStartTime, int segmentsPlayed) { int nextSegmentIndex = segmentIndex + segmentsPlayed; int effectSize = effect.getSegments().size(); int repeatIndex = effect.getRepeatIndex(); Loading @@ -154,7 +174,7 @@ abstract class AbstractVibratorStep extends Step { nextSegmentIndex = repeatIndex + ((nextSegmentIndex - effectSize) % loopSize); } Step nextStep = conductor.nextVibrateStep(nextStartTime, controller, effect, nextSegmentIndex, vibratorOffTimeout); nextSegmentIndex, mPendingVibratorOffDeadline); return nextStep == null ? VibrationStepConductor.EMPTY_STEP_LIST : Arrays.asList(nextStep); } } services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java +16 −8 Original line number Diff line number Diff line Loading @@ -34,9 +34,9 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { private final boolean mCancelled; CompleteEffectVibratorStep(VibrationStepConductor conductor, long startTime, boolean cancelled, VibratorController controller, long previousStepVibratorOffTimeout) { VibratorController controller, long pendingVibratorOffDeadline) { super(conductor, startTime, controller, /* effect= */ null, /* index= */ -1, previousStepVibratorOffTimeout); pendingVibratorOffDeadline); mCancelled = cancelled; } Loading Loading @@ -73,10 +73,11 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { return VibrationStepConductor.EMPTY_STEP_LIST; } long now = SystemClock.uptimeMillis(); float currentAmplitude = controller.getCurrentAmplitude(); long remainingOnDuration = previousStepVibratorOffTimeout - VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT - SystemClock.uptimeMillis(); mPendingVibratorOffDeadline - now - VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT; long rampDownDuration = Math.min(remainingOnDuration, conductor.vibrationSettings.getRampDownDuration()); Loading @@ -89,8 +90,10 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { stopVibrating(); return VibrationStepConductor.EMPTY_STEP_LIST; } else { // Vibration is completing normally, turn off after the deadline in case we // don't receive the callback in time (callback also triggers it right away). return Arrays.asList(new TurnOffVibratorStep( conductor, previousStepVibratorOffTimeout, controller)); conductor, mPendingVibratorOffDeadline, controller)); } } Loading @@ -100,13 +103,18 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { + " from amplitude " + currentAmplitude + " for " + rampDownDuration + "ms"); } // If we are cancelling this vibration then make sure the vibrator will be turned off // immediately after the ramp off duration. Otherwise, this is a planned ramp off for // the remaining ON duration, then just propagate the mPendingVibratorOffDeadline so the // turn off step will wait for the vibration completion callback and end gracefully. long rampOffVibratorOffDeadline = mCancelled ? (now + rampDownDuration) : mPendingVibratorOffDeadline; float amplitudeDelta = currentAmplitude / (rampDownDuration / stepDownDuration); float amplitudeTarget = currentAmplitude - amplitudeDelta; long newVibratorOffTimeout = mCancelled ? rampDownDuration : previousStepVibratorOffTimeout; return Arrays.asList( new RampOffVibratorStep(conductor, startTime, amplitudeTarget, amplitudeDelta, controller, newVibratorOffTimeout)); controller, rampOffVibratorOffDeadline)); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } Loading services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java +11 −7 Original line number Diff line number Diff line Loading @@ -40,11 +40,11 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep { ComposePrimitivesVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { // This step should wait for the last vibration to finish (with the timeout) and for the // intended step start time (to respect the effect delays). super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect, index, previousStepVibratorOffTimeout); super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect, index, pendingVibratorOffDeadline); } @Override Loading @@ -60,18 +60,22 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep { if (primitives.isEmpty()) { Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePrimitivesStep: " + effect.getSegments().get(segmentIndex)); return skipToNextSteps(/* segmentsSkipped= */ 1); // Skip this step and play the next one right away. return nextSteps(/* segmentsPlayed= */ 1); } if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Compose " + primitives + " primitives on vibrator " + controller.getVibratorInfo().getId()); + getVibratorId()); } PrimitiveSegment[] primitivesArray = primitives.toArray(new PrimitiveSegment[primitives.size()]); mVibratorOnResult = controller.on(primitivesArray, getVibration().id); getVibration().stats().reportComposePrimitives(mVibratorOnResult, primitivesArray); long vibratorOnResult = controller.on(primitivesArray, getVibration().id); handleVibratorOnResult(vibratorOnResult); getVibration().stats().reportComposePrimitives(vibratorOnResult, primitivesArray); // The next start and off times will be calculated from mVibratorOnResult. return nextSteps(/* segmentsPlayed= */ primitives.size()); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); Loading services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java +9 −6 Original line number Diff line number Diff line Loading @@ -41,11 +41,11 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep { ComposePwleVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { // This step should wait for the last vibration to finish (with the timeout) and for the // intended step start time (to respect the effect delays). super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect, index, previousStepVibratorOffTimeout); super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect, index, pendingVibratorOffDeadline); } @Override Loading @@ -61,7 +61,8 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep { if (pwles.isEmpty()) { Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePwleStep: " + effect.getSegments().get(segmentIndex)); return skipToNextSteps(/* segmentsSkipped= */ 1); // Skip this step and play the next one right away. return nextSteps(/* segmentsPlayed= */ 1); } if (VibrationThread.DEBUG) { Loading @@ -69,9 +70,11 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep { + controller.getVibratorInfo().getId()); } RampSegment[] pwlesArray = pwles.toArray(new RampSegment[pwles.size()]); mVibratorOnResult = controller.on(pwlesArray, getVibration().id); getVibration().stats().reportComposePwle(mVibratorOnResult, pwlesArray); long vibratorOnResult = controller.on(pwlesArray, getVibration().id); handleVibratorOnResult(vibratorOnResult); getVibration().stats().reportComposePwle(vibratorOnResult, pwlesArray); // The next start and off times will be calculated from mVibratorOnResult. return nextSteps(/* segmentsPlayed= */ pwles.size()); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); Loading services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java +12 −9 Original line number Diff line number Diff line Loading @@ -35,11 +35,11 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { PerformPrebakedVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { // This step should wait for the last vibration to finish (with the timeout) and for the // intended step start time (to respect the effect delays). super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect, index, previousStepVibratorOffTimeout); super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect, index, pendingVibratorOffDeadline); } @Override Loading @@ -50,7 +50,8 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { if (!(segment instanceof PrebakedSegment)) { Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a " + "PerformPrebakedVibratorStep: " + segment); return skipToNextSteps(/* segmentsSkipped= */ 1); // Skip this step and play the next one right away. return nextSteps(/* segmentsPlayed= */ 1); } PrebakedSegment prebaked = (PrebakedSegment) segment; Loading @@ -61,10 +62,11 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { } VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId()); mVibratorOnResult = controller.on(prebaked, getVibration().id); getVibration().stats().reportPerformEffect(mVibratorOnResult, prebaked); long vibratorOnResult = controller.on(prebaked, getVibration().id); handleVibratorOnResult(vibratorOnResult); getVibration().stats().reportPerformEffect(vibratorOnResult, prebaked); if (mVibratorOnResult == 0 && prebaked.shouldFallback() if (vibratorOnResult == 0 && prebaked.shouldFallback() && (fallback instanceof VibrationEffect.Composed)) { if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Playing fallback for effect " Loading @@ -72,14 +74,15 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { } AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller, replaceCurrentSegment((VibrationEffect.Composed) fallback), segmentIndex, previousStepVibratorOffTimeout); segmentIndex, mPendingVibratorOffDeadline); List<Step> fallbackResult = fallbackStep.play(); // Update the result with the fallback result so this step is seamlessly // replaced by the fallback to any outer application of this. mVibratorOnResult = fallbackStep.getVibratorOnDuration(); handleVibratorOnResult(fallbackStep.getVibratorOnDuration()); return fallbackResult; } // The next start and off times will be calculated from mVibratorOnResult. return nextSteps(/* segmentsPlayed= */ 1); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); Loading Loading
services/core/java/com/android/server/vibrator/AbstractVibratorStep.java +56 −36 Original line number Diff line number Diff line Loading @@ -31,9 +31,9 @@ abstract class AbstractVibratorStep extends Step { public final VibratorController controller; public final VibrationEffect.Composed effect; public final int segmentIndex; public final long previousStepVibratorOffTimeout; long mVibratorOnResult; long mPendingVibratorOffDeadline; boolean mVibratorCompleteCallbackReceived; /** Loading @@ -43,19 +43,19 @@ abstract class AbstractVibratorStep extends Step { * @param controller The vibrator that is playing the effect. * @param effect The effect being played in this step. * @param index The index of the next segment to be played by this step * @param previousStepVibratorOffTimeout The time the vibrator is expected to complete any * @param pendingVibratorOffDeadline The time the vibrator is expected to complete any * previous vibration and turn off. This is used to allow this step to * be triggered when the completion callback is received, and can * be used to play effects back-to-back. */ AbstractVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { super(conductor, startTime); this.controller = controller; this.effect = effect; this.segmentIndex = index; this.previousStepVibratorOffTimeout = previousStepVibratorOffTimeout; mPendingVibratorOffDeadline = pendingVibratorOffDeadline; } public int getVibratorId() { Loading @@ -69,27 +69,57 @@ abstract class AbstractVibratorStep extends Step { @Override public boolean acceptVibratorCompleteCallback(int vibratorId) { boolean isSameVibrator = controller.getVibratorInfo().getId() == vibratorId; mVibratorCompleteCallbackReceived |= isSameVibrator; if (getVibratorId() != vibratorId) { return false; } // Only activate this step if a timeout was set to wait for the vibration to complete, // otherwise we are waiting for the correct time to play the next step. return isSameVibrator && (previousStepVibratorOffTimeout > SystemClock.uptimeMillis()); boolean shouldAcceptCallback = mPendingVibratorOffDeadline > SystemClock.uptimeMillis(); if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Received completion callback from " + vibratorId + ", accepted = " + shouldAcceptCallback); } // The callback indicates this vibrator has stopped, reset the timeout. mPendingVibratorOffDeadline = 0; mVibratorCompleteCallbackReceived = true; return shouldAcceptCallback; } @Override public List<Step> cancel() { return Arrays.asList(new CompleteEffectVibratorStep(conductor, SystemClock.uptimeMillis(), /* cancelled= */ true, controller, previousStepVibratorOffTimeout)); /* cancelled= */ true, controller, mPendingVibratorOffDeadline)); } @Override public void cancelImmediately() { if (previousStepVibratorOffTimeout > SystemClock.uptimeMillis()) { if (mPendingVibratorOffDeadline > SystemClock.uptimeMillis()) { // Vibrator might be running from previous steps, so turn it off while canceling. stopVibrating(); } } protected long handleVibratorOnResult(long vibratorOnResult) { mVibratorOnResult = vibratorOnResult; if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Turned on vibrator " + getVibratorId() + ", result = " + mVibratorOnResult); } if (mVibratorOnResult > 0) { // Vibrator was turned on by this step, with vibratorOnResult as the duration. // Set an extra timeout to wait for the vibrator completion callback. mPendingVibratorOffDeadline = SystemClock.uptimeMillis() + mVibratorOnResult + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT; } else { // Vibrator does not support the request or failed to turn on, reset callback deadline. mPendingVibratorOffDeadline = 0; } return mVibratorOnResult; } protected void stopVibrating() { if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, Loading @@ -97,6 +127,7 @@ abstract class AbstractVibratorStep extends Step { } controller.off(); getVibration().stats().reportVibratorOff(); mPendingVibratorOffDeadline = 0; } protected void changeAmplitude(float amplitude) { Loading @@ -109,40 +140,29 @@ abstract class AbstractVibratorStep extends Step { } /** * Return the {@link VibrationStepConductor#nextVibrateStep} with same timings, only jumping * the segments. */ protected List<Step> skipToNextSteps(int segmentsSkipped) { return nextSteps(startTime, previousStepVibratorOffTimeout, segmentsSkipped); } /** * Return the {@link VibrationStepConductor#nextVibrateStep} with same start and off timings * calculated from {@link #getVibratorOnDuration()}, jumping all played segments. * * <p>This method has same behavior as {@link #skipToNextSteps(int)} when the vibrator * result is non-positive, meaning the vibrator has either ignored or failed to turn on. * 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. */ protected List<Step> nextSteps(int segmentsPlayed) { if (mVibratorOnResult <= 0) { // Vibration was not started, so just skip the played segments and keep timings. return skipToNextSteps(segmentsPlayed); // Schedule next steps to run right away. long nextStartTime = SystemClock.uptimeMillis(); if (mVibratorOnResult > 0) { // Vibrator was turned on by this step, with mVibratorOnResult as the duration. // Schedule next steps for right after the vibration finishes. nextStartTime += mVibratorOnResult; } long nextStartTime = SystemClock.uptimeMillis() + mVibratorOnResult; long nextVibratorOffTimeout = nextStartTime + VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT; return nextSteps(nextStartTime, nextVibratorOffTimeout, segmentsPlayed); return nextSteps(nextStartTime, segmentsPlayed); } /** * Return the {@link VibrationStepConductor#nextVibrateStep} with given start and off timings, * which might be calculated independently, jumping all played segments. * Return the {@link VibrationStepConductor#nextVibrateStep} with given start time, * which might be calculated independently, and jumping all played segments from the effect. * * <p>This should be used when the vibrator on/off state is not responsible for the steps * execution timings, e.g. while playing the vibrator amplitudes. * <p>This should be used when the vibrator on/off state is not responsible for the step * execution timing, e.g. while playing the vibrator amplitudes. */ protected List<Step> nextSteps(long nextStartTime, long vibratorOffTimeout, int segmentsPlayed) { protected List<Step> nextSteps(long nextStartTime, int segmentsPlayed) { int nextSegmentIndex = segmentIndex + segmentsPlayed; int effectSize = effect.getSegments().size(); int repeatIndex = effect.getRepeatIndex(); Loading @@ -154,7 +174,7 @@ abstract class AbstractVibratorStep extends Step { nextSegmentIndex = repeatIndex + ((nextSegmentIndex - effectSize) % loopSize); } Step nextStep = conductor.nextVibrateStep(nextStartTime, controller, effect, nextSegmentIndex, vibratorOffTimeout); nextSegmentIndex, mPendingVibratorOffDeadline); return nextStep == null ? VibrationStepConductor.EMPTY_STEP_LIST : Arrays.asList(nextStep); } }
services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java +16 −8 Original line number Diff line number Diff line Loading @@ -34,9 +34,9 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { private final boolean mCancelled; CompleteEffectVibratorStep(VibrationStepConductor conductor, long startTime, boolean cancelled, VibratorController controller, long previousStepVibratorOffTimeout) { VibratorController controller, long pendingVibratorOffDeadline) { super(conductor, startTime, controller, /* effect= */ null, /* index= */ -1, previousStepVibratorOffTimeout); pendingVibratorOffDeadline); mCancelled = cancelled; } Loading Loading @@ -73,10 +73,11 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { return VibrationStepConductor.EMPTY_STEP_LIST; } long now = SystemClock.uptimeMillis(); float currentAmplitude = controller.getCurrentAmplitude(); long remainingOnDuration = previousStepVibratorOffTimeout - VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT - SystemClock.uptimeMillis(); mPendingVibratorOffDeadline - now - VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT; long rampDownDuration = Math.min(remainingOnDuration, conductor.vibrationSettings.getRampDownDuration()); Loading @@ -89,8 +90,10 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { stopVibrating(); return VibrationStepConductor.EMPTY_STEP_LIST; } else { // Vibration is completing normally, turn off after the deadline in case we // don't receive the callback in time (callback also triggers it right away). return Arrays.asList(new TurnOffVibratorStep( conductor, previousStepVibratorOffTimeout, controller)); conductor, mPendingVibratorOffDeadline, controller)); } } Loading @@ -100,13 +103,18 @@ final class CompleteEffectVibratorStep extends AbstractVibratorStep { + " from amplitude " + currentAmplitude + " for " + rampDownDuration + "ms"); } // If we are cancelling this vibration then make sure the vibrator will be turned off // immediately after the ramp off duration. Otherwise, this is a planned ramp off for // the remaining ON duration, then just propagate the mPendingVibratorOffDeadline so the // turn off step will wait for the vibration completion callback and end gracefully. long rampOffVibratorOffDeadline = mCancelled ? (now + rampDownDuration) : mPendingVibratorOffDeadline; float amplitudeDelta = currentAmplitude / (rampDownDuration / stepDownDuration); float amplitudeTarget = currentAmplitude - amplitudeDelta; long newVibratorOffTimeout = mCancelled ? rampDownDuration : previousStepVibratorOffTimeout; return Arrays.asList( new RampOffVibratorStep(conductor, startTime, amplitudeTarget, amplitudeDelta, controller, newVibratorOffTimeout)); controller, rampOffVibratorOffDeadline)); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } Loading
services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java +11 −7 Original line number Diff line number Diff line Loading @@ -40,11 +40,11 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep { ComposePrimitivesVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { // This step should wait for the last vibration to finish (with the timeout) and for the // intended step start time (to respect the effect delays). super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect, index, previousStepVibratorOffTimeout); super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect, index, pendingVibratorOffDeadline); } @Override Loading @@ -60,18 +60,22 @@ final class ComposePrimitivesVibratorStep extends AbstractVibratorStep { if (primitives.isEmpty()) { Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePrimitivesStep: " + effect.getSegments().get(segmentIndex)); return skipToNextSteps(/* segmentsSkipped= */ 1); // Skip this step and play the next one right away. return nextSteps(/* segmentsPlayed= */ 1); } if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Compose " + primitives + " primitives on vibrator " + controller.getVibratorInfo().getId()); + getVibratorId()); } PrimitiveSegment[] primitivesArray = primitives.toArray(new PrimitiveSegment[primitives.size()]); mVibratorOnResult = controller.on(primitivesArray, getVibration().id); getVibration().stats().reportComposePrimitives(mVibratorOnResult, primitivesArray); long vibratorOnResult = controller.on(primitivesArray, getVibration().id); handleVibratorOnResult(vibratorOnResult); getVibration().stats().reportComposePrimitives(vibratorOnResult, primitivesArray); // The next start and off times will be calculated from mVibratorOnResult. return nextSteps(/* segmentsPlayed= */ primitives.size()); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); Loading
services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java +9 −6 Original line number Diff line number Diff line Loading @@ -41,11 +41,11 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep { ComposePwleVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { // This step should wait for the last vibration to finish (with the timeout) and for the // intended step start time (to respect the effect delays). super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect, index, previousStepVibratorOffTimeout); super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect, index, pendingVibratorOffDeadline); } @Override Loading @@ -61,7 +61,8 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep { if (pwles.isEmpty()) { Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a ComposePwleStep: " + effect.getSegments().get(segmentIndex)); return skipToNextSteps(/* segmentsSkipped= */ 1); // Skip this step and play the next one right away. return nextSteps(/* segmentsPlayed= */ 1); } if (VibrationThread.DEBUG) { Loading @@ -69,9 +70,11 @@ final class ComposePwleVibratorStep extends AbstractVibratorStep { + controller.getVibratorInfo().getId()); } RampSegment[] pwlesArray = pwles.toArray(new RampSegment[pwles.size()]); mVibratorOnResult = controller.on(pwlesArray, getVibration().id); getVibration().stats().reportComposePwle(mVibratorOnResult, pwlesArray); long vibratorOnResult = controller.on(pwlesArray, getVibration().id); handleVibratorOnResult(vibratorOnResult); getVibration().stats().reportComposePwle(vibratorOnResult, pwlesArray); // The next start and off times will be calculated from mVibratorOnResult. return nextSteps(/* segmentsPlayed= */ pwles.size()); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); Loading
services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java +12 −9 Original line number Diff line number Diff line Loading @@ -35,11 +35,11 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { PerformPrebakedVibratorStep(VibrationStepConductor conductor, long startTime, VibratorController controller, VibrationEffect.Composed effect, int index, long previousStepVibratorOffTimeout) { long pendingVibratorOffDeadline) { // This step should wait for the last vibration to finish (with the timeout) and for the // intended step start time (to respect the effect delays). super(conductor, Math.max(startTime, previousStepVibratorOffTimeout), controller, effect, index, previousStepVibratorOffTimeout); super(conductor, Math.max(startTime, pendingVibratorOffDeadline), controller, effect, index, pendingVibratorOffDeadline); } @Override Loading @@ -50,7 +50,8 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { if (!(segment instanceof PrebakedSegment)) { Slog.w(VibrationThread.TAG, "Ignoring wrong segment for a " + "PerformPrebakedVibratorStep: " + segment); return skipToNextSteps(/* segmentsSkipped= */ 1); // Skip this step and play the next one right away. return nextSteps(/* segmentsPlayed= */ 1); } PrebakedSegment prebaked = (PrebakedSegment) segment; Loading @@ -61,10 +62,11 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { } VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId()); mVibratorOnResult = controller.on(prebaked, getVibration().id); getVibration().stats().reportPerformEffect(mVibratorOnResult, prebaked); long vibratorOnResult = controller.on(prebaked, getVibration().id); handleVibratorOnResult(vibratorOnResult); getVibration().stats().reportPerformEffect(vibratorOnResult, prebaked); if (mVibratorOnResult == 0 && prebaked.shouldFallback() if (vibratorOnResult == 0 && prebaked.shouldFallback() && (fallback instanceof VibrationEffect.Composed)) { if (VibrationThread.DEBUG) { Slog.d(VibrationThread.TAG, "Playing fallback for effect " Loading @@ -72,14 +74,15 @@ final class PerformPrebakedVibratorStep extends AbstractVibratorStep { } AbstractVibratorStep fallbackStep = conductor.nextVibrateStep(startTime, controller, replaceCurrentSegment((VibrationEffect.Composed) fallback), segmentIndex, previousStepVibratorOffTimeout); segmentIndex, mPendingVibratorOffDeadline); List<Step> fallbackResult = fallbackStep.play(); // Update the result with the fallback result so this step is seamlessly // replaced by the fallback to any outer application of this. mVibratorOnResult = fallbackStep.getVibratorOnDuration(); handleVibratorOnResult(fallbackStep.getVibratorOnDuration()); return fallbackResult; } // The next start and off times will be calculated from mVibratorOnResult. return nextSteps(/* segmentsPlayed= */ 1); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); Loading