Merge "Add step down ramp to vibration waveforms" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-30 19:16:15 +00:00
committed by Android (Google) Code Review
9 changed files with 583 additions and 342 deletions

View File

@@ -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<VibrationEffectAdapters.SegmentsAdapter<VibratorInfo>> 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()
);
}

View File

@@ -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.
*
* <p>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.
*
* <p>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.
*
* <p>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<VibratorInfo> {
private final int mRampDownDuration;
private final int mStepDuration;
RampDownAdapter(int rampDownDuration, int stepDuration) {
mRampDownDuration = rampDownDuration;
mStepDuration = stepDuration;
}
@Override
public int apply(List<VibrationEffectSegment> 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:
*
* <ol>
* <li>Remove the OFF segment that follows a segment of non-zero amplitude;
* <li>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;
* <li>Add a zero amplitude segment following the steps, if necessary, to fill the remaining
* duration;
* </ol>
*/
private int addRampDownToZeroAmplitudeSegments(List<VibrationEffectSegment> 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<VibrationEffectSegment> 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:
*
* <ol>
* <li>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;
* <li>Skip the zero-amplitude segment by incrementing the repeat index, splitting it if
* necessary to skip the correct amount;
* </ol>
*/
private int addRampDownToLoop(List<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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;
}
}

View File

@@ -31,25 +31,9 @@ import java.util.List;
* <p>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.
*
* <p>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.
*
* <p>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<VibratorInfo> {
private final int mRampDownDuration;
StepToRampAdapter(int rampDownDuration) {
mRampDownDuration = rampDownDuration;
}
@Override
public int apply(List<VibrationEffectSegment> 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<VibrationEffectSegment> 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:
*
* <ol>
* <li>Remove the {@link VibrationEffectSegment} that starts and ends at zero amplitude
* and follows a segment that ends at non-zero amplitude;
* <li>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;
* <li>Add a zero amplitude segment following the ramp with the remaining duration, if
* necessary;
* </ol>
*/
private int addRampDownToZeroAmplitudeSegments(List<VibrationEffectSegment> 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:
*
* <ol>
* <li>Add a ramp down to zero following the last segment, with the min between the
* removed segment duration and the configured ramp down duration;
* <li>Skip the zero-amplitude segment by incrementing the repeat index, splitting it if
* necessary to skip the correct amount;
* </ol>
*/
private int addRampDownToLoop(List<VibrationEffectSegment> 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());

View File

@@ -67,11 +67,13 @@ final class VibrationSettings {
@VisibleForTesting
final UserObserver mUserReceiver;
@GuardedBy("mLock")
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
private final SparseArray<VibrationEffect> 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="

View File

@@ -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();

View File

@@ -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

View File

@@ -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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new PrebakedSegment(
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT),
new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)));
List<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 10),
new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
assertEquals(originalSegments, segments);
}
@Test
public void testStepSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() {
List<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 120),
new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30)));
List<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
assertEquals(originalSegments, segments);
}
@Test
public void testRampSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() {
List<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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);
}
}

View File

@@ -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<VibrationEffectSegment> 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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 10),
new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 1, /* duration= */ 100)));
List<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> 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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10),
new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30)));
List<VibrationEffectSegment> 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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20),
new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30)));
List<VibrationEffectSegment> 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<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 120),
new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30)));
List<VibrationEffectSegment> 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))

View File

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