From 8b89945845cde511960df00facf05a7001ccaf2d Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Wed, 30 Jun 2021 12:14:08 +0100 Subject: [PATCH] Add step down ramp to vibration waveforms Update ramp-to-step adapter to also add "step down to zero" segments to off segments in the VibrationEffect waveform. This is the step version of the same behavior implemented for PWLEs supporting "ramp down to zero", and uses the same configured duration. The StepToRampAdapter no longer converts all step waveforms into PWLEs, since now they can also smooth the abrupt amplitude transitions. Bug: 188431691 Test: RampToStepAdapterTest Change-Id: I6e77139f4f21d6c344617bebdb83241b7a951bde --- .../DeviceVibrationEffectAdapter.java | 10 +- .../server/vibrator/RampDownAdapter.java | 240 ++++++++++++++ .../server/vibrator/StepToRampAdapter.java | 181 +---------- .../server/vibrator/VibrationSettings.java | 29 +- .../vibrator/VibratorManagerService.java | 2 +- .../DeviceVibrationEffectAdapterTest.java | 6 +- .../server/vibrator/RampDownAdapterTest.java | 294 ++++++++++++++++++ .../vibrator/StepToRampAdapterTest.java | 158 +--------- .../server/vibrator/VibrationThreadTest.java | 5 +- 9 files changed, 583 insertions(+), 342 deletions(-) create mode 100644 services/core/java/com/android/server/vibrator/RampDownAdapter.java create mode 100644 services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java diff --git a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java index e8ce4f336caa4..24da261483dbf 100644 --- a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java +++ b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java @@ -16,7 +16,6 @@ package com.android.server.vibrator; -import android.content.Context; import android.os.VibrationEffect; import android.os.VibratorInfo; @@ -29,14 +28,13 @@ final class DeviceVibrationEffectAdapter private final List> mSegmentAdapters; - DeviceVibrationEffectAdapter(Context context) { + DeviceVibrationEffectAdapter(VibrationSettings settings) { mSegmentAdapters = Arrays.asList( // TODO(b/167947076): add filter that removes unsupported primitives // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback - new RampToStepAdapter(context.getResources().getInteger( - com.android.internal.R.integer.config_vibrationWaveformRampStepDuration)), - new StepToRampAdapter(context.getResources().getInteger( - com.android.internal.R.integer.config_vibrationWaveformRampDownDuration)), + new RampToStepAdapter(settings.getRampStepDuration()), + new StepToRampAdapter(), + new RampDownAdapter(settings.getRampDownDuration(), settings.getRampStepDuration()), new ClippingAmplitudeAndFrequencyAdapter() ); } diff --git a/services/core/java/com/android/server/vibrator/RampDownAdapter.java b/services/core/java/com/android/server/vibrator/RampDownAdapter.java new file mode 100644 index 0000000000000..d5cd344d93ce3 --- /dev/null +++ b/services/core/java/com/android/server/vibrator/RampDownAdapter.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import android.os.VibratorInfo; +import android.os.vibrator.RampSegment; +import android.os.vibrator.StepSegment; +import android.os.vibrator.VibrationEffectSegment; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Adapter that applies the ramp down duration config to bring down the vibrator amplitude smoothly. + * + *

This prevents the device from ringing when it cannot handle abrupt changes between ON and OFF + * states. This will not change other types of abrupt amplitude changes in the original effect. The + * effect overall duration is preserved by this transformation. + * + *

Waveforms with ON/OFF segments are handled gracefully by the ramp down changes. Each OFF + * segment preceded by an ON segment will be shortened, and a ramp or step down will be added to the + * transition between ON and OFF. The ramps/steps can be shorter than the configured duration in + * order to preserve the waveform timings, but they will still soften the ringing effect. + * + *

If the segment preceding an OFF segment a {@link RampSegment} then a new ramp segment will be + * added to bring the amplitude down. If it is a {@link StepSegment} then a sequence of steps will + * be used to bring the amplitude down to zero. This ensures that the transition from the last + * amplitude to zero will be handled by the same vibrate method. + */ +final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter { + private final int mRampDownDuration; + private final int mStepDuration; + + RampDownAdapter(int rampDownDuration, int stepDuration) { + mRampDownDuration = rampDownDuration; + mStepDuration = stepDuration; + } + + @Override + public int apply(List segments, int repeatIndex, + VibratorInfo info) { + if (mRampDownDuration <= 0) { + // Nothing to do, no ramp down duration configured. + return repeatIndex; + } + repeatIndex = addRampDownToZeroAmplitudeSegments(segments, repeatIndex); + repeatIndex = addRampDownToLoop(segments, repeatIndex); + return repeatIndex; + } + + /** + * This will add ramp or steps down to zero as follows: + * + *

    + *
  1. Remove the OFF segment that follows a segment of non-zero amplitude; + *
  2. Add a single {@link RampSegment} or a list of {@link StepSegment} starting at the + * previous segment's amplitude and frequency, with min between the configured ramp down + * duration or the removed segment's duration; + *
  3. Add a zero amplitude segment following the steps, if necessary, to fill the remaining + * duration; + *
+ */ + private int addRampDownToZeroAmplitudeSegments(List segments, + int repeatIndex) { + int newRepeatIndex = repeatIndex; + int newSegmentCount = segments.size(); + for (int i = 1; i < newSegmentCount; i++) { + VibrationEffectSegment previousSegment = segments.get(i - 1); + if (!isOffSegment(segments.get(i)) + || !endsWithNonZeroAmplitude(previousSegment)) { + continue; + } + + List replacementSegments = null; + long offDuration = segments.get(i).getDuration(); + + if (previousSegment instanceof StepSegment) { + float previousAmplitude = ((StepSegment) previousSegment).getAmplitude(); + float previousFrequency = ((StepSegment) previousSegment).getFrequency(); + + replacementSegments = + createStepsDown(previousAmplitude, previousFrequency, offDuration); + } else if (previousSegment instanceof RampSegment) { + float previousAmplitude = ((RampSegment) previousSegment).getEndAmplitude(); + float previousFrequency = ((RampSegment) previousSegment).getEndFrequency(); + + if (offDuration <= mRampDownDuration) { + // Replace the zero amplitude segment with a ramp down of same duration, to + // preserve waveform timings and still soften the transition to zero. + replacementSegments = Arrays.asList( + createRampDown(previousAmplitude, previousFrequency, offDuration)); + } else { + // Replace the zero amplitude segment with a ramp down of configured duration + // followed by a shorter off segment. + replacementSegments = Arrays.asList( + createRampDown(previousAmplitude, previousFrequency, mRampDownDuration), + createRampDown(0, previousFrequency, offDuration - mRampDownDuration)); + } + } + + if (replacementSegments != null) { + int segmentsAdded = replacementSegments.size() - 1; + + segments.remove(i); + segments.addAll(i, replacementSegments); + if (repeatIndex > i) { + newRepeatIndex += segmentsAdded; + } + i += segmentsAdded; + newSegmentCount += segmentsAdded; + } + } + return newRepeatIndex; + } + + /** + * This will ramps down to zero at the repeating index of the given effect, if set, only if + * the last segment ends at a non-zero amplitude and the repeating segment has zero amplitude. + * The update is described as: + * + *
    + *
  1. Add a ramp or sequence of steps down to zero following the last segment, with the min + * between the removed segment duration and the configured ramp down duration; + *
  2. Skip the zero-amplitude segment by incrementing the repeat index, splitting it if + * necessary to skip the correct amount; + *
+ */ + private int addRampDownToLoop(List segments, int repeatIndex) { + if (repeatIndex < 0) { + // Nothing to do, no ramp down duration configured or effect is not repeating. + return repeatIndex; + } + + int segmentCount = segments.size(); + if (!endsWithNonZeroAmplitude(segments.get(segmentCount - 1)) + || !isOffSegment(segments.get(repeatIndex))) { + // Nothing to do, not going back from a positive amplitude to a off segment. + return repeatIndex; + } + + VibrationEffectSegment lastSegment = segments.get(segmentCount - 1); + VibrationEffectSegment offSegment = segments.get(repeatIndex); + long offDuration = offSegment.getDuration(); + + if (offDuration > mRampDownDuration) { + // Split the zero amplitude segment and start repeating from the second half, to + // preserve waveform timings. This will update the waveform as follows: + // R R+1 + // | ____ | ____ + // _|__/ => __|_/ \ + segments.set(repeatIndex, updateDuration(offSegment, offDuration - mRampDownDuration)); + segments.add(repeatIndex, updateDuration(offSegment, mRampDownDuration)); + } + + // Skip the zero amplitude segment and append ramp/steps down at the end. + repeatIndex++; + if (lastSegment instanceof StepSegment) { + float previousAmplitude = ((StepSegment) lastSegment).getAmplitude(); + float previousFrequency = ((StepSegment) lastSegment).getFrequency(); + segments.addAll(createStepsDown(previousAmplitude, previousFrequency, + Math.min(offDuration, mRampDownDuration))); + } else if (lastSegment instanceof RampSegment) { + float previousAmplitude = ((RampSegment) lastSegment).getEndAmplitude(); + float previousFrequency = ((RampSegment) lastSegment).getEndFrequency(); + segments.add(createRampDown(previousAmplitude, previousFrequency, + Math.min(offDuration, mRampDownDuration))); + } + + return repeatIndex; + } + + private List createStepsDown(float amplitude, float frequency, + long duration) { + // Step down for at most the configured ramp duration. + int stepCount = (int) Math.min(duration, mRampDownDuration) / mStepDuration; + float amplitudeStep = amplitude / stepCount; + List steps = new ArrayList<>(); + for (int i = 1; i < stepCount; i++) { + steps.add(new StepSegment(amplitude - i * amplitudeStep, frequency, mStepDuration)); + } + int remainingDuration = (int) duration - mStepDuration * (stepCount - 1); + steps.add(new StepSegment(0, frequency, remainingDuration)); + return steps; + } + + private static RampSegment createRampDown(float amplitude, float frequency, long duration) { + return new RampSegment(amplitude, /* endAmplitude= */ 0, frequency, frequency, + (int) duration); + } + + private static VibrationEffectSegment updateDuration(VibrationEffectSegment segment, + long newDuration) { + if (segment instanceof RampSegment) { + RampSegment ramp = (RampSegment) segment; + return new RampSegment(ramp.getStartAmplitude(), ramp.getEndAmplitude(), + ramp.getStartFrequency(), ramp.getEndFrequency(), (int) newDuration); + } else if (segment instanceof StepSegment) { + StepSegment step = (StepSegment) segment; + return new StepSegment(step.getAmplitude(), step.getFrequency(), (int) newDuration); + } + return segment; + } + + /** Returns true if the segment is a ramp or a step that starts and ends at zero amplitude. */ + private static boolean isOffSegment(VibrationEffectSegment segment) { + if (segment instanceof StepSegment) { + StepSegment ramp = (StepSegment) segment; + return ramp.getAmplitude() == 0; + } else if (segment instanceof RampSegment) { + RampSegment ramp = (RampSegment) segment; + return ramp.getStartAmplitude() == 0 && ramp.getEndAmplitude() == 0; + } + return false; + } + + /** Returns true if the segment is a ramp or a step that ends at a non-zero amplitude. */ + private static boolean endsWithNonZeroAmplitude(VibrationEffectSegment segment) { + if (segment instanceof StepSegment) { + return ((StepSegment) segment).getAmplitude() != 0; + } else if (segment instanceof RampSegment) { + return ((RampSegment) segment).getEndAmplitude() != 0; + } + return false; + } +} diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java index 1d8c64bddd495..6f5adac33ae6e 100644 --- a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java +++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java @@ -31,25 +31,9 @@ import java.util.List; *

Each replaced {@link StepSegment} will be represented by a {@link RampSegment} with same * start and end amplitudes/frequencies, which can then be converted to PWLE compositions. This * adapter leaves the segments unchanged if the device doesn't have the PWLE composition capability. - * - *

This adapter also applies the ramp down duration config on devices with PWLE support. This - * prevents the device from ringing when it cannot handle abrupt changes between ON and OFF states. - * This will not change other types of abrupt amplitude changes in the original effect. - * - *

The effect overall duration is preserved by this transformation. Waveforms with ON/OFF - * segments are handled gracefully by the ramp down changes. Each OFF segment preceded by an ON - * segment will be shortened, and a ramp down will be added to the transition between ON and OFF. - * The ramps can be shorter than the configured duration in order to preserve the waveform timings, - * but they will still soften the ringing effect. */ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter { - private final int mRampDownDuration; - - StepToRampAdapter(int rampDownDuration) { - mRampDownDuration = rampDownDuration; - } - @Override public int apply(List segments, int repeatIndex, VibratorInfo info) { @@ -58,28 +42,17 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter return repeatIndex; } convertStepsToRamps(segments); - int newRepeatIndex = addRampDownToZeroAmplitudeSegments(segments, repeatIndex); - newRepeatIndex = addRampDownToLoop(segments, newRepeatIndex); - newRepeatIndex = splitLongRampSegments(info, segments, newRepeatIndex); - return newRepeatIndex; + repeatIndex = splitLongRampSegments(info, segments, repeatIndex); + return repeatIndex; } private void convertStepsToRamps(List segments) { int segmentCount = segments.size(); - if (mRampDownDuration > 0) { - // Convert all steps to ramps if the device requires ramp down. - for (int i = 0; i < segmentCount; i++) { - if (isStep(segments.get(i))) { - segments.set(i, apply((StepSegment) segments.get(i))); - } - } - return; - } // Convert steps that require frequency control to ramps. for (int i = 0; i < segmentCount; i++) { VibrationEffectSegment segment = segments.get(i); if (isStep(segment) && ((StepSegment) segment).getFrequency() != 0) { - segments.set(i, apply((StepSegment) segment)); + segments.set(i, convertStepToRamp((StepSegment) segment)); } } // Convert steps that are next to ramps to also become ramps, so they can be composed @@ -87,131 +60,15 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter for (int i = 0; i < segmentCount; i++) { if (segments.get(i) instanceof RampSegment) { for (int j = i - 1; j >= 0 && isStep(segments.get(j)); j--) { - segments.set(j, apply((StepSegment) segments.get(j))); + segments.set(j, convertStepToRamp((StepSegment) segments.get(j))); } for (int j = i + 1; j < segmentCount && isStep(segments.get(j)); j++) { - segments.set(j, apply((StepSegment) segments.get(j))); + segments.set(j, convertStepToRamp((StepSegment) segments.get(j))); } } } } - /** - * This will add a ramp to zero as follows: - * - *

    - *
  1. Remove the {@link VibrationEffectSegment} that starts and ends at zero amplitude - * and follows a segment that ends at non-zero amplitude; - *
  2. Add a ramp down to zero starting at the previous segment end amplitude and frequency, - * with min between the removed segment duration and the configured ramp down duration; - *
  3. Add a zero amplitude segment following the ramp with the remaining duration, if - * necessary; - *
- */ - private int addRampDownToZeroAmplitudeSegments(List segments, - int repeatIndex) { - if (mRampDownDuration <= 0) { - // Nothing to do, no ramp down duration configured. - return repeatIndex; - } - int newRepeatIndex = repeatIndex; - int newSegmentCount = segments.size(); - for (int i = 1; i < newSegmentCount; i++) { - if (!isOffRampSegment(segments.get(i)) - || !endsWithNonZeroAmplitude(segments.get(i - 1))) { - continue; - } - - // We know the previous segment is a ramp that ends at non-zero amplitude. - float previousAmplitude = ((RampSegment) segments.get(i - 1)).getEndAmplitude(); - float previousFrequency = ((RampSegment) segments.get(i - 1)).getEndFrequency(); - RampSegment ramp = (RampSegment) segments.get(i); - - if (ramp.getDuration() <= mRampDownDuration) { - // Replace the zero amplitude segment with a ramp down of same duration, to - // preserve waveform timings and still soften the transition to zero. - segments.set(i, createRampDown(previousAmplitude, previousFrequency, - ramp.getDuration())); - } else { - // Make the zero amplitude segment shorter, to preserve waveform timings, and add a - // ramp down to zero segment right before it. - segments.set(i, updateDuration(ramp, ramp.getDuration() - mRampDownDuration)); - segments.add(i, createRampDown(previousAmplitude, previousFrequency, - mRampDownDuration)); - if (repeatIndex > i) { - newRepeatIndex++; - } - i++; - newSegmentCount++; - } - } - return newRepeatIndex; - } - - /** - * This will add a ramp to zero at the repeating index of the given effect, if set, only if - * the last segment ends at a non-zero amplitude and the repeating segment starts and ends at - * zero amplitude. The update is described as: - * - *
    - *
  1. Add a ramp down to zero following the last segment, with the min between the - * removed segment duration and the configured ramp down duration; - *
  2. Skip the zero-amplitude segment by incrementing the repeat index, splitting it if - * necessary to skip the correct amount; - *
- */ - private int addRampDownToLoop(List segments, int repeatIndex) { - if (repeatIndex < 0) { - // Non-repeating compositions should remain unchanged so duration will be preserved. - return repeatIndex; - } - - int segmentCount = segments.size(); - if (mRampDownDuration <= 0 || !endsWithNonZeroAmplitude(segments.get(segmentCount - 1))) { - // Nothing to do, no ramp down duration configured or composition already ends at zero. - return repeatIndex; - } - - // We know the last segment is a ramp that ends at non-zero amplitude. - RampSegment lastRamp = (RampSegment) segments.get(segmentCount - 1); - float previousAmplitude = lastRamp.getEndAmplitude(); - float previousFrequency = lastRamp.getEndFrequency(); - - if (isOffRampSegment(segments.get(repeatIndex))) { - // Repeating from a non-zero to a zero amplitude segment, we know the next segment is a - // ramp with zero amplitudes. - RampSegment nextRamp = (RampSegment) segments.get(repeatIndex); - - if (nextRamp.getDuration() <= mRampDownDuration) { - // Skip the zero amplitude segment and append a ramp down of same duration to the - // end of the composition, to preserve waveform timings and still soften the - // transition to zero. - // This will update the waveform as follows: - // R R+1 - // | ____ | ____ - // _|_/ => __|/ \ - segments.add(createRampDown(previousAmplitude, previousFrequency, - nextRamp.getDuration())); - repeatIndex++; - } else { - // Append a ramp down to the end of the composition, split the zero amplitude - // segment and start repeating from the second half, to preserve waveform timings. - // This will update the waveform as follows: - // R R+1 - // | ____ | ____ - // _|__/ => __|_/ \ - segments.add(createRampDown(previousAmplitude, previousFrequency, - mRampDownDuration)); - segments.set(repeatIndex, updateDuration(nextRamp, - nextRamp.getDuration() - mRampDownDuration)); - segments.add(repeatIndex, updateDuration(nextRamp, mRampDownDuration)); - repeatIndex++; - } - } - - return repeatIndex; - } - /** * Split {@link RampSegment} entries that have duration longer than {@link * VibratorInfo#getPwlePrimitiveDurationMax()}. @@ -247,7 +104,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter return repeatIndex; } - private static RampSegment apply(StepSegment segment) { + private static RampSegment convertStepToRamp(StepSegment segment) { return new RampSegment(segment.getAmplitude(), segment.getAmplitude(), segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration()); } @@ -276,36 +133,10 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter return ramps; } - private static RampSegment createRampDown(float amplitude, float frequency, long duration) { - return new RampSegment(amplitude, /* endAmplitude= */ 0, frequency, frequency, - (int) duration); - } - - private static RampSegment updateDuration(RampSegment ramp, long newDuration) { - return new RampSegment(ramp.getStartAmplitude(), ramp.getEndAmplitude(), - ramp.getStartFrequency(), ramp.getEndFrequency(), (int) newDuration); - } - private static boolean isStep(VibrationEffectSegment segment) { return segment instanceof StepSegment; } - /** Returns true if the segment is a ramp that starts and ends at zero amplitude. */ - private static boolean isOffRampSegment(VibrationEffectSegment segment) { - if (segment instanceof RampSegment) { - RampSegment ramp = (RampSegment) segment; - return ramp.getStartAmplitude() == 0 && ramp.getEndAmplitude() == 0; - } - return false; - } - - private static boolean endsWithNonZeroAmplitude(VibrationEffectSegment segment) { - if (segment instanceof RampSegment) { - return ((RampSegment) segment).getEndAmplitude() != 0; - } - return false; - } - private static float interpolateAmplitude(RampSegment ramp, long duration) { return interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), duration, ramp.getDuration()); diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index 885f0e4c78ab0..c0a1d92104c57 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -67,11 +67,13 @@ final class VibrationSettings { @VisibleForTesting final UserObserver mUserReceiver; - @GuardedBy("mLock") private final List mListeners = new ArrayList<>(); private final SparseArray mFallbackEffects; + private final int mRampStepDuration; + private final int mRampDownDuration; + @GuardedBy("mLock") @Nullable private Vibrator mVibrator; @@ -102,6 +104,12 @@ final class VibrationSettings { mUidObserver = new UidObserver(); mUserReceiver = new UserObserver(); + // TODO(b/191150049): move these to vibrator static config file + mRampStepDuration = context.getResources().getInteger( + com.android.internal.R.integer.config_vibrationWaveformRampStepDuration); + mRampDownDuration = context.getResources().getInteger( + com.android.internal.R.integer.config_vibrationWaveformRampDownDuration); + VibrationEffect clickEffect = createEffectFromResource( com.android.internal.R.array.config_virtualKeyVibePattern); VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( @@ -192,6 +200,23 @@ final class VibrationSettings { } } + /** + * The duration, in milliseconds, that should be applied to convert vibration effect's + * {@link android.os.vibrator.RampSegment} to a {@link android.os.vibrator.StepSegment} on + * devices without PWLE support. + */ + public int getRampStepDuration() { + return mRampStepDuration; + } + + /** + * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator + * when a vibration is cancelled or finished at non-zero amplitude. + */ + public int getRampDownDuration() { + return mRampDownDuration; + } + /** * Return default vibration intensity for given usage. * @@ -354,6 +379,8 @@ final class VibrationSettings { + ", mZenMode=" + Settings.Global.zenModeToString(mZenMode) + ", mProcStatesCache=" + mUidObserver.mProcStatesCache + ", mHapticChannelMaxVibrationAmplitude=" + getHapticChannelMaxVibrationAmplitude() + + ", mRampStepDuration=" + mRampStepDuration + + ", mRampDownDuration=" + mRampDownDuration + ", mHapticFeedbackIntensity=" + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)) + ", mHapticFeedbackDefaultIntensity=" diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 79706ead555cb..644e451ce0e8a 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -176,7 +176,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationSettings = new VibrationSettings(mContext, mHandler); mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler); - mDeviceVibrationEffectAdapter = new DeviceVibrationEffectAdapter(mContext); + mDeviceVibrationEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings); VibrationCompleteListener listener = new VibrationCompleteListener(this); mNativeWrapper = injector.getNativeWrapper(); diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java index 14cab021edb04..b934ecb805641 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java @@ -20,8 +20,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.hardware.vibrator.IVibrator; +import android.os.Handler; import android.os.VibrationEffect; import android.os.VibratorInfo; +import android.os.test.TestLooper; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.RampSegment; @@ -62,7 +64,9 @@ public class DeviceVibrationEffectAdapterTest { @Before public void setUp() throws Exception { - mAdapter = new DeviceVibrationEffectAdapter(InstrumentationRegistry.getContext()); + VibrationSettings vibrationSettings = new VibrationSettings( + InstrumentationRegistry.getContext(), new Handler(new TestLooper().getLooper())); + mAdapter = new DeviceVibrationEffectAdapter(vibrationSettings); } @Test diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java new file mode 100644 index 0000000000000..b90df21464ca7 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import static org.junit.Assert.assertEquals; + +import android.os.VibrationEffect; +import android.os.VibratorInfo; +import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.PrimitiveSegment; +import android.os.vibrator.RampSegment; +import android.os.vibrator.StepSegment; +import android.os.vibrator.VibrationEffectSegment; +import android.platform.test.annotations.Presubmit; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Tests for {@link RampDownAdapter}. + * + * Build/Install/Run: + * atest FrameworksServicesTests:RampDownAdapterTest + */ +@Presubmit +public class RampDownAdapterTest { + private static final int TEST_RAMP_DOWN_DURATION = 20; + private static final int TEST_STEP_DURATION = 5; + private static final VibratorInfo TEST_VIBRATOR_INFO = new VibratorInfo.Builder(0).build(); + + private RampDownAdapter mAdapter; + + @Before + public void setUp() throws Exception { + mAdapter = new RampDownAdapter(TEST_RAMP_DOWN_DURATION, TEST_STEP_DURATION); + } + + @Test + public void testPrebakedAndPrimitiveSegments_keepsListUnchanged() { + List segments = new ArrayList<>(Arrays.asList( + new PrebakedSegment( + VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT), + new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); + List originalSegments = new ArrayList<>(segments); + + assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); + assertEquals(1, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO)); + + assertEquals(originalSegments, segments); + } + + @Test + public void testRampAndStepSegments_withNoOffSegment_keepsListUnchanged() { + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + List originalSegments = new ArrayList<>(segments); + + assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); + assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(originalSegments, segments); + } + + @Test + public void testRampAndStepSegments_withNoRampDownDuration_keepsOriginalSteps() { + mAdapter = new RampDownAdapter(/* rampDownDuration= */ 0, TEST_STEP_DURATION); + + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 50))); + List originalSegments = new ArrayList<>(segments); + + assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); + assertEquals(2, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); + assertEquals(originalSegments, segments); + } + + @Test + public void testStepSegments_withShortZeroSegment_replaceWithStepsDown() { + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100))); + List expectedSegments = Arrays.asList( + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)); + + assertEquals(1, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withLongZeroSegment_replaceWithStepsDown() { + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 50), + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100))); + List expectedSegments = Arrays.asList( + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35), + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)); + + // Repeat index fixed after intermediate steps added + assertEquals(5, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRepeatToNonZeroSegment_keepsOriginalSteps() { + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100))); + List originalSegments = new ArrayList<>(segments); + + assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(originalSegments, segments); + } + + @Test + public void testStepSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() { + List segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30))); + List expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5)); + + // Shift repeat index to the right to use append instead of zero segment. + assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRepeatToLongZeroSegment_splitAndAppendRampDown() { + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 120), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30))); + List expectedSegments = Arrays.asList( + // Split long zero segment to skip part of it. + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 20), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30), + new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5)); + + // Shift repeat index to the right to use append with part of the zero segment. + assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testRampSegments_withShortZeroSegment_replaceWithRampDown() { + List segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + List expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + + assertEquals(2, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testRampSegments_withLongZeroSegment_splitAndAddRampDown() { + List segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 150), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + List expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 130), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + + // Repeat index fixed after intermediate steps added + assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testRampSegments_withRepeatToNonZeroSegment_keepsOriginalSteps() { + List segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + List originalSegments = new ArrayList<>(segments); + + assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(originalSegments, segments); + } + + @Test + public void testRampSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() { + List segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 1, + /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 20))); + List expectedSegments = Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, + /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20)); + + // Shift repeat index to the right to use append instead of zero segment. + assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testRampSegments_withRepeatToLongZeroSegment_splitAndAppendRampDown() { + List segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 70), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + List expectedSegments = Arrays.asList( + // Split long zero segment to skip part of it. + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20)); + + // Shift repeat index to the right to use append with part of the zero segment. + assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); + + assertEquals(expectedSegments, segments); + } +} diff --git a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java index 32988efbab2ca..128cd2f9e0a1e 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java @@ -48,7 +48,7 @@ public class StepToRampAdapterTest { @Before public void setUp() throws Exception { - mAdapter = new StepToRampAdapter(/* rampDownDuration= */ 0); + mAdapter = new StepToRampAdapter(); } @Test @@ -101,8 +101,6 @@ public class StepToRampAdapterTest { @Test public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() { - mAdapter = new StepToRampAdapter(50); - List segments = new ArrayList<>(Arrays.asList( new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, @@ -182,160 +180,6 @@ public class StepToRampAdapterTest { assertEquals(expectedSegments, segments); } - @Test - public void testStepSegments_withRampDownEndingAtNonZero_noRampDownAdded() { - int rampDownDuration = 50; - mAdapter = new StepToRampAdapter(rampDownDuration); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 1, /* duration= */ 100))); - List expectedSegments = Arrays.asList( - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10), - new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - - @Test - public void testStepSegments_withRampDownAndShortZeroSegment_replaceWithRampDown() { - mAdapter = new StepToRampAdapter(50); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 20), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); - List expectedSegments = Arrays.asList( - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - assertEquals(2, mAdapter.apply(segments, 2, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - - @Test - public void testStepSegments_withRampDownAndLongZeroSegment_splitAndAddRampDown() { - mAdapter = new StepToRampAdapter(50); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 150), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); - List expectedSegments = Arrays.asList( - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 50), - new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - // Repeat index fixed after intermediate steps added - assertEquals(3, mAdapter.apply(segments, 2, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - - @Test - public void testStepSegments_withRampDownAndNoZeroSegment_noRampDownAdded() { - mAdapter = new StepToRampAdapter(50); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30), - new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); - List expectedSegments = Arrays.asList( - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), - new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - - @Test - public void testStepSegments_withRampDownAndRepeatToNonZeroSegment_noRampDownAdded() { - mAdapter = new StepToRampAdapter(50); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); - List expectedSegments = Arrays.asList( - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - assertEquals(0, mAdapter.apply(segments, 0, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - - @Test - public void testStepSegments_withRampDownAndRepeatToShortZeroSegment_skipAndAppendRampDown() { - mAdapter = new StepToRampAdapter(50); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); - List expectedSegments = Arrays.asList( - new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - // Shift repeat index to the right to use append instead of zero segment. - assertEquals(1, mAdapter.apply(segments, 0, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - - @Test - public void testStepSegments_withRampDownAndRepeatToLongZeroSegment_splitAndAppendRampDown() { - mAdapter = new StepToRampAdapter(50); - - List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 120), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); - List expectedSegments = Arrays.asList( - // Split long zero segment to skip part of it. - new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50), - new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 70), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50)); - - VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - // Shift repeat index to the right to use append with part of the zero segment. - assertEquals(1, mAdapter.apply(segments, 0, vibratorInfo)); - - assertEquals(expectedSegments, segments); - } - private static VibratorInfo createVibratorInfo(int... capabilities) { return new VibratorInfo.Builder(0) .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) 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 b8fdb552e4535..6d25e8c55a517 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java @@ -36,6 +36,7 @@ import android.hardware.vibrator.Braking; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorManager; import android.os.CombinedVibration; +import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.os.Process; @@ -108,7 +109,9 @@ public class VibrationThreadTest { mTestLooper = new TestLooper(); Context context = InstrumentationRegistry.getContext(); - mEffectAdapter = new DeviceVibrationEffectAdapter(context); + VibrationSettings vibrationSettings = new VibrationSettings(context, + new Handler(mTestLooper.getLooper())); + mEffectAdapter = new DeviceVibrationEffectAdapter(vibrationSettings); mWakeLock = context.getSystemService( PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");