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*");