diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java index a4817ae27fa5d..27ff036320e4d 100644 --- a/core/java/android/hardware/input/InputDeviceVibrator.java +++ b/core/java/android/hardware/input/InputDeviceVibrator.java @@ -20,11 +20,13 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.app.ActivityThread; import android.content.Context; +import android.hardware.vibrator.IVibrator; import android.os.Binder; import android.os.IVibratorStateListener; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorInfo; import android.util.ArrayMap; import android.util.Log; @@ -41,7 +43,7 @@ final class InputDeviceVibrator extends Vibrator { // mDeviceId represents InputDevice ID the vibrator belongs to private final int mDeviceId; - private final int mVibratorId; + private final VibratorInfo mVibratorInfo; private final Binder mToken; private final InputManager mInputManager; @@ -52,7 +54,13 @@ final class InputDeviceVibrator extends Vibrator { InputDeviceVibrator(InputManager inputManager, int deviceId, int vibratorId) { mInputManager = inputManager; mDeviceId = deviceId; - mVibratorId = vibratorId; + mVibratorInfo = new VibratorInfo.Builder(vibratorId) + .setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL) + // Set predefined support to empty as we know input devices do not support them. + .setSupportedEffects() + .setSupportedPrimitives() + .setSupportedBraking() + .build(); mToken = new Binder(); } @@ -74,8 +82,8 @@ final class InputDeviceVibrator extends Vibrator { } @Override - public int getId() { - return mVibratorId; + protected VibratorInfo getInfo() { + return mVibratorInfo; } @Override @@ -159,7 +167,7 @@ final class InputDeviceVibrator extends Vibrator { @Override public boolean hasAmplitudeControl() { - return true; + return mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL); } /** diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index 2e8ecb59b0d35..e270857e2d356 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -28,7 +28,6 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import java.util.ArrayList; -import java.util.Arrays; import java.util.Objects; import java.util.concurrent.Executor; @@ -50,6 +49,9 @@ public class SystemVibrator extends Vibrator { private final ArrayMap mRegisteredListeners = new ArrayMap<>(); + private final Object mLock = new Object(); + private AllVibratorsInfo mVibratorInfo; + @UnsupportedAppUsage public SystemVibrator(Context context) { super(context); @@ -57,6 +59,25 @@ public class SystemVibrator extends Vibrator { mVibratorManager = mContext.getSystemService(VibratorManager.class); } + @Override + protected VibratorInfo getInfo() { + synchronized (mLock) { + if (mVibratorInfo != null) { + return mVibratorInfo; + } + if (mVibratorManager == null) { + Log.w(TAG, "Failed to retrieve vibrator info; no vibrator manager."); + return VibratorInfo.EMPTY_VIBRATOR_INFO; + } + int[] vibratorIds = mVibratorManager.getVibratorIds(); + VibratorInfo[] vibratorInfos = new VibratorInfo[vibratorIds.length]; + for (int i = 0; i < vibratorIds.length; i++) { + vibratorInfos[i] = mVibratorManager.getVibrator(vibratorIds[i]).getInfo(); + } + return mVibratorInfo = new AllVibratorsInfo(vibratorInfos); + } + } + @Override public boolean hasVibrator() { if (mVibratorManager == null) { @@ -144,20 +165,7 @@ public class SystemVibrator extends Vibrator { @Override public boolean hasAmplitudeControl() { - if (mVibratorManager == null) { - Log.w(TAG, "Failed to check vibrator has amplitude control; no vibrator manager."); - return false; - } - int[] vibratorIds = mVibratorManager.getVibratorIds(); - if (vibratorIds.length == 0) { - return false; - } - for (int vibratorId : vibratorIds) { - if (!mVibratorManager.getVibrator(vibratorId).hasAmplitudeControl()) { - return false; - } - } - return true; + return getInfo().hasAmplitudeControl(); } @Override @@ -183,70 +191,6 @@ public class SystemVibrator extends Vibrator { mVibratorManager.vibrate(uid, opPkg, combinedEffect, reason, attributes); } - @Override - public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) { - int[] supported = new int[effectIds.length]; - if (mVibratorManager == null) { - Log.w(TAG, "Failed to check supported effects; no vibrator manager."); - Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_NO); - return supported; - } - int[] vibratorIds = mVibratorManager.getVibratorIds(); - if (vibratorIds.length == 0) { - Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_NO); - return supported; - } - int[][] vibratorSupportMap = new int[vibratorIds.length][effectIds.length]; - for (int i = 0; i < vibratorIds.length; i++) { - vibratorSupportMap[i] = mVibratorManager.getVibrator( - vibratorIds[i]).areEffectsSupported(effectIds); - } - Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_YES); - for (int effectIdx = 0; effectIdx < effectIds.length; effectIdx++) { - for (int vibratorIdx = 0; vibratorIdx < vibratorIds.length; vibratorIdx++) { - int effectSupported = vibratorSupportMap[vibratorIdx][effectIdx]; - if (effectSupported == Vibrator.VIBRATION_EFFECT_SUPPORT_NO) { - supported[effectIdx] = Vibrator.VIBRATION_EFFECT_SUPPORT_NO; - break; - } else if (effectSupported == Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN) { - supported[effectIdx] = Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN; - } - } - } - return supported; - } - - @Override - public boolean[] arePrimitivesSupported( - @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { - boolean[] supported = new boolean[primitiveIds.length]; - if (mVibratorManager == null) { - Log.w(TAG, "Failed to check supported primitives; no vibrator manager."); - Arrays.fill(supported, false); - return supported; - } - int[] vibratorIds = mVibratorManager.getVibratorIds(); - if (vibratorIds.length == 0) { - Arrays.fill(supported, false); - return supported; - } - boolean[][] vibratorSupportMap = new boolean[vibratorIds.length][primitiveIds.length]; - for (int i = 0; i < vibratorIds.length; i++) { - vibratorSupportMap[i] = mVibratorManager.getVibrator( - vibratorIds[i]).arePrimitivesSupported(primitiveIds); - } - Arrays.fill(supported, true); - for (int primitiveIdx = 0; primitiveIdx < primitiveIds.length; primitiveIdx++) { - for (int vibratorIdx = 0; vibratorIdx < vibratorIds.length; vibratorIdx++) { - if (!vibratorSupportMap[vibratorIdx][primitiveIdx]) { - supported[primitiveIdx] = false; - break; - } - } - } - return supported; - } - @Override public void cancel() { if (mVibratorManager == null) { @@ -295,6 +239,58 @@ public class SystemVibrator extends Vibrator { } } + /** + * Represents all the vibrators information as a single {@link VibratorInfo}. + * + *

This uses the first vibrator on the list as the default one for all hardware spec, but + * uses an intersection of all vibrators to decide the capabilities and effect/primitive + * support. + */ + private static class AllVibratorsInfo extends VibratorInfo { + private final VibratorInfo[] mVibratorInfos; + + AllVibratorsInfo(VibratorInfo[] vibrators) { + super(/* id= */ -1, capabilitiesIntersection(vibrators), + vibrators.length > 0 ? vibrators[0] : VibratorInfo.EMPTY_VIBRATOR_INFO); + mVibratorInfos = vibrators; + } + + @Override + public int isEffectSupported(int effectId) { + int supported = Vibrator.VIBRATION_EFFECT_SUPPORT_YES; + for (VibratorInfo info : mVibratorInfos) { + int effectSupported = info.isEffectSupported(effectId); + if (effectSupported == Vibrator.VIBRATION_EFFECT_SUPPORT_NO) { + return effectSupported; + } else if (effectSupported == Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN) { + supported = effectSupported; + } + } + return supported; + } + + @Override + public boolean isPrimitiveSupported(int primitiveId) { + for (VibratorInfo info : mVibratorInfos) { + if (!info.isPrimitiveSupported(primitiveId)) { + return false; + } + } + return true; + } + + private static int capabilitiesIntersection(VibratorInfo[] infos) { + if (infos.length == 0) { + return 0; + } + int intersection = ~0; + for (VibratorInfo info : infos) { + intersection &= info.getCapabilities(); + } + return intersection; + } + } + /** Listener for all vibrators state change. */ private static class AllVibratorsStateListener { private final Object mLock = new Object(); diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java index 84a1016e33640..d94b6f4e488a7 100644 --- a/core/java/android/os/SystemVibratorManager.java +++ b/core/java/android/os/SystemVibratorManager.java @@ -185,8 +185,8 @@ public class SystemVibratorManager extends VibratorManager { } @Override - public int getId() { - return mVibratorInfo.getId(); + protected VibratorInfo getInfo() { + return mVibratorInfo; } @Override @@ -199,36 +199,6 @@ public class SystemVibratorManager extends VibratorManager { return mVibratorInfo.hasAmplitudeControl(); } - @Override - public float getResonantFrequency() { - return mVibratorInfo.getResonantFrequency(); - } - - @Override - public float getQFactor() { - return mVibratorInfo.getQFactor(); - } - - @NonNull - @Override - public int[] areEffectsSupported(@NonNull int... effectIds) { - int[] supported = new int[effectIds.length]; - for (int i = 0; i < effectIds.length; i++) { - supported[i] = mVibratorInfo.isEffectSupported(effectIds[i]); - } - return supported; - } - - @Override - public boolean[] arePrimitivesSupported( - @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { - boolean[] supported = new boolean[primitiveIds.length]; - for (int i = 0; i < primitiveIds.length; i++) { - supported[i] = mVibratorInfo.isPrimitiveSupported(primitiveIds[i]); - } - return supported; - } - @Override public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) { diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index a0f70c8fa5260..dcc4911c538e9 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -17,6 +17,7 @@ package android.os; import android.annotation.CallbackExecutor; +import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -26,12 +27,13 @@ import android.annotation.SystemService; import android.app.ActivityThread; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.util.Log; +import android.util.Range; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.Arrays; import java.util.concurrent.Executor; /** @@ -156,6 +158,11 @@ public abstract class Vibrator { return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM; } + /** @hide */ + protected VibratorInfo getInfo() { + return VibratorInfo.EMPTY_VIBRATOR_INFO; + } + /** * Get the default vibration intensity for haptic feedback. * @@ -190,7 +197,7 @@ public abstract class Vibrator { * service, or -1 this service is not attached to any physical vibrator. */ public int getId() { - return -1; + return getInfo().getId(); } /** @@ -207,15 +214,27 @@ public abstract class Vibrator { */ public abstract boolean hasAmplitudeControl(); + /** + * Check whether the vibrator has independent frequency control. + * + * @return True if the hardware can control the frequency of the vibrations, otherwise false. + * @hide + */ + public boolean hasFrequencyControl() { + // We currently can only control frequency of the vibration using the compose PWLE method. + return getInfo().hasCapability( + IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + } + /** * Gets the resonant frequency of the vibrator. * * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown or - * this vibrator is a composite of multiple physical devices. + * this vibrator is a composite of multiple physical devices. * @hide */ public float getResonantFrequency() { - return Float.NaN; + return getInfo().getResonantFrequency(); } /** @@ -226,7 +245,44 @@ public abstract class Vibrator { * @hide */ public float getQFactor() { - return Float.NaN; + return getInfo().getQFactor(); + } + + /** + * Return a range of relative frequency values supported by the vibrator. + * + *

These values can be used to create waveforms that controls the vibration frequency via + * {@link VibrationEffect.WaveformBuilder}. + * + * @return A range of relative frequency values supported. The range will always contain the + * value 0, representing the device resonant frequency. Devices without frequency control will + * return the range [0,0]. Devices with frequency control will always return a range containing + * the safe range [-1, 1]. + * @hide + */ + public Range getRelativeFrequencyRange() { + return getInfo().getFrequencyRange(); + } + + /** + * Return the maximum amplitude the vibrator can play at given relative frequency. + * + *

Devices without frequency control will return 1 for the input zero (resonant frequency), + * and 0 to any other input. + * + *

Devices with frequency control will return the supported value, for input in + * {@link #getRelativeFrequencyRange()}, and 0 for any other input. + * + *

These values can be used to create waveforms that plays vibrations outside the resonant + * frequency via {@link VibrationEffect.WaveformBuilder}. + * + * @return a value in [0,1] representing the maximum amplitude the device can play at given + * relative frequency. + * @hide + */ + @FloatRange(from = 0, to = 1) + public float getMaximumAmplitude(float relativeFrequency) { + return getInfo().getMaxAmplitude(relativeFrequency); } /** @@ -414,9 +470,12 @@ public abstract class Vibrator { @VibrationEffectSupport public int[] areEffectsSupported( @NonNull @VibrationEffect.EffectType int... effectIds) { - final int[] support = new int[effectIds.length]; - Arrays.fill(support, VIBRATION_EFFECT_SUPPORT_NO); - return support; + VibratorInfo info = getInfo(); + int[] supported = new int[effectIds.length]; + for (int i = 0; i < effectIds.length; i++) { + supported[i] = info.isEffectSupported(effectIds[i]); + } + return supported; } /** @@ -468,7 +527,12 @@ public abstract class Vibrator { @NonNull public boolean[] arePrimitivesSupported( @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { - return new boolean[primitiveIds.length]; + VibratorInfo info = getInfo(); + boolean[] supported = new boolean[primitiveIds.length]; + for (int i = 0; i < primitiveIds.length; i++) { + supported[i] = info.isPrimitiveSupported(primitiveIds[i]); + } + return supported; } /** diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java index 671daa0f0f819..c7d66f0dccdc5 100644 --- a/core/java/android/os/VibratorInfo.java +++ b/core/java/android/os/VibratorInfo.java @@ -38,9 +38,12 @@ import java.util.Objects; * * @hide */ -public final class VibratorInfo implements Parcelable { +public class VibratorInfo implements Parcelable { private static final String TAG = "VibratorInfo"; + /** @hide */ + public static final VibratorInfo EMPTY_VIBRATOR_INFO = new VibratorInfo.Builder(-1).build(); + private final int mId; private final long mCapabilities; @Nullable @@ -74,6 +77,23 @@ public final class VibratorInfo implements Parcelable { mFrequencyMapping = frequencyMapping; } + protected VibratorInfo(int id, int capabilities, VibratorInfo baseVibrator) { + mId = id; + mCapabilities = capabilities; + mSupportedEffects = baseVibrator.mSupportedEffects == null ? null : + baseVibrator.mSupportedEffects.clone(); + mSupportedBraking = baseVibrator.mSupportedBraking == null ? null : + baseVibrator.mSupportedBraking.clone(); + mSupportedPrimitives = baseVibrator.mSupportedPrimitives == null ? null : + baseVibrator.mSupportedPrimitives.clone(); + mQFactor = baseVibrator.mQFactor; + mFrequencyMapping = new FrequencyMapping(baseVibrator.mFrequencyMapping.mMinFrequencyHz, + baseVibrator.mFrequencyMapping.mResonantFrequencyHz, + baseVibrator.mFrequencyMapping.mFrequencyResolutionHz, + baseVibrator.mFrequencyMapping.mSuggestedSafeRangeHz, + baseVibrator.mFrequencyMapping.mMaxAmplitudes); + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mId); @@ -145,6 +165,7 @@ public final class VibratorInfo implements Parcelable { * Returns a default value to be applied to composed PWLE effects for braking. * * @return a supported braking value, one of android.hardware.vibrator.Braking.* + * @hide */ public int getDefaultBraking() { if (mSupportedBraking != null) { @@ -265,6 +286,10 @@ public final class VibratorInfo implements Parcelable { return mFrequencyMapping.toHertz(relativeFrequency); } + protected long getCapabilities() { + return mCapabilities; + } + private String[] getCapabilitiesNames() { List names = new ArrayList<>(); if (hasCapability(IVibrator.CAP_ON_CALLBACK)) { @@ -370,7 +395,7 @@ public final class VibratorInfo implements Parcelable { *

The mapping is defined linearly by the following points: * *

    - *
  1. {@code toHertz(relativeMinFrequency} = minFrequency + *
  2. {@code toHertz(relativeMinFrequency) = minFrequency} *
  3. {@code toHertz(-1) = resonantFrequency - safeRange / 2} *
  4. {@code toHertz(0) = resonantFrequency} *
  5. {@code toHertz(1) = resonantFrequency + safeRange / 2} @@ -555,6 +580,75 @@ public final class VibratorInfo implements Parcelable { }; } + /** @hide */ + public static final class Builder { + private final int mId; + private int mCapabilities = 0; + private int[] mSupportedEffects = null; + private int[] mSupportedBraking = null; + private int[] mSupportedPrimitives = null; + private float mQFactor = Float.NaN; + private FrequencyMapping mFrequencyMapping = + new FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null); + + /** A builder class for a {@link VibratorInfo}. */ + public Builder(int id) { + mId = id; + } + + /** Configure the vibrator capabilities with a combination of IVibrator.CAP_* values. */ + @NonNull + public Builder setCapabilities(int capabilities) { + mCapabilities = capabilities; + return this; + } + + /** Configure the effects supported with {@link android.hardware.vibrator.Effect} values. */ + @NonNull + public Builder setSupportedEffects(int... supportedEffects) { + mSupportedEffects = supportedEffects; + return this; + } + + /** Configure braking supported with {@link android.hardware.vibrator.Braking} values. */ + @NonNull + public Builder setSupportedBraking(int... supportedBraking) { + mSupportedBraking = supportedBraking; + return this; + } + + /** + * Configure the primitives supported with + * {@link android.hardware.vibrator.CompositePrimitive} values. + */ + @NonNull + public Builder setSupportedPrimitives(int... supportedPrimitives) { + mSupportedPrimitives = supportedPrimitives; + return this; + } + + /** Configure the vibrator quality factor. */ + @NonNull + public Builder setQFactor(float qFactor) { + mQFactor = qFactor; + return this; + } + + /** Configure the vibrator frequency information like resonant frequency and bandwidth. */ + @NonNull + public Builder setFrequencyMapping(FrequencyMapping frequencyMapping) { + mFrequencyMapping = frequencyMapping; + return this; + } + + /** Build the configured {@link VibratorInfo}. */ + @NonNull + public VibratorInfo build() { + return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedBraking, + mSupportedPrimitives, mQFactor, mFrequencyMapping); + } + } + @NonNull public static final Creator CREATOR = new Creator() { diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java index 2521f7551a3c6..3a804641c3f9a 100644 --- a/core/tests/coretests/src/android/os/VibratorInfoTest.java +++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java @@ -35,6 +35,7 @@ import org.junit.runners.JUnit4; public class VibratorInfoTest { private static final float TEST_TOLERANCE = 1e-5f; + private static final int TEST_VIBRATOR_ID = 1; private static final float TEST_MIN_FREQUENCY = 50; private static final float TEST_RESONANT_FREQUENCY = 150; private static final float TEST_FREQUENCY_RESOLUTION = 25; @@ -50,9 +51,9 @@ public class VibratorInfoTest { @Test public void testHasAmplitudeControl() { - VibratorInfo noCapabilities = new InfoBuilder().build(); + VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertFalse(noCapabilities.hasAmplitudeControl()); - VibratorInfo composeAndAmplitudeControl = new InfoBuilder() + VibratorInfo composeAndAmplitudeControl = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL) .build(); @@ -61,7 +62,7 @@ public class VibratorInfoTest { @Test public void testHasCapabilities() { - VibratorInfo info = new InfoBuilder() + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) .build(); assertTrue(info.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)); @@ -70,8 +71,8 @@ public class VibratorInfoTest { @Test public void testIsEffectSupported() { - VibratorInfo noEffects = new InfoBuilder().build(); - VibratorInfo canClick = new InfoBuilder() + VibratorInfo noEffects = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); + VibratorInfo canClick = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setSupportedEffects(VibrationEffect.EFFECT_CLICK) .build(); assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN, @@ -84,7 +85,7 @@ public class VibratorInfoTest { @Test public void testIsPrimitiveSupported() { - VibratorInfo info = new InfoBuilder() + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK) .build(); @@ -92,7 +93,7 @@ public class VibratorInfoTest { assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); // Returns false when there is no compose capability. - info = new InfoBuilder() + info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK) .build(); assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); @@ -100,9 +101,10 @@ public class VibratorInfoTest { @Test public void testGetDefaultBraking_returnsFirstSupportedBraking() { - assertEquals(Braking.NONE, new InfoBuilder().build().getDefaultBraking()); + assertEquals(Braking.NONE, new VibratorInfo.Builder( + TEST_VIBRATOR_ID).build().getDefaultBraking()); assertEquals(Braking.CLAB, - new InfoBuilder() + new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setSupportedBraking(Braking.NONE, Braking.CLAB) .build() .getDefaultBraking()); @@ -111,33 +113,34 @@ public class VibratorInfoTest { @Test public void testGetFrequencyRange_invalidFrequencyMappingReturnsEmptyRange() { // Invalid, contains NaN values or empty array. - assertEquals(Range.create(0f, 0f), new InfoBuilder().build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder( + TEST_VIBRATOR_ID).build().getFrequencyRange()); + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( Float.NaN, 150, 25, 50, TEST_AMPLITUDE_MAP)) .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( 50, Float.NaN, 25, 50, TEST_AMPLITUDE_MAP)) .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( 50, 150, Float.NaN, 50, TEST_AMPLITUDE_MAP)) .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( 50, 150, 25, Float.NaN, TEST_AMPLITUDE_MAP)) .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping(50, 150, 25, 50, null)) .build().getFrequencyRange()); // Invalid, minFrequency > resonantFrequency - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( /* minFrequencyHz= */ 250, /* resonantFrequency= */ 150, 25, 50, null)) .build().getFrequencyRange()); // Invalid, maxFrequency < resonantFrequency by changing resolution. - assertEquals(Range.create(0f, 0f), new InfoBuilder() + assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( 50, 150, /* frequencyResolutionHz= */10, 50, null)) .build().getFrequencyRange()); @@ -145,7 +148,7 @@ public class VibratorInfoTest { @Test public void testGetFrequencyRange_safeRangeLimitedByMaxFrequency() { - VibratorInfo info = new InfoBuilder() + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, /* frequencyResolutionHz= */ 25, /* suggestedSafeRangeHz= */ 200, @@ -159,7 +162,7 @@ public class VibratorInfoTest { @Test public void testGetFrequencyRange_safeRangeLimitedByMinFrequency() { - VibratorInfo info = new InfoBuilder() + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, /* frequencyResolutionHz= */ 50, /* suggestedSafeRangeHz= */ 200, @@ -173,7 +176,7 @@ public class VibratorInfoTest { @Test public void testGetFrequencyRange_validMappingReturnsFullRelativeRange() { - VibratorInfo info = new InfoBuilder() + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, /* frequencyResolutionHz= */ 50, /* suggestedSafeRangeHz= */ 100, @@ -187,7 +190,7 @@ public class VibratorInfoTest { @Test public void testAbsoluteFrequency_emptyMappingReturnsNaN() { - VibratorInfo info = new InfoBuilder().build(); + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertTrue(Float.isNaN(info.getAbsoluteFrequency(-1))); assertTrue(Float.isNaN(info.getAbsoluteFrequency(0))); assertTrue(Float.isNaN(info.getAbsoluteFrequency(1))); @@ -195,7 +198,8 @@ public class VibratorInfoTest { @Test public void testAbsoluteFrequency_validRangeReturnsOriginalValue() { - VibratorInfo info = new InfoBuilder().setFrequencyMapping(TEST_FREQUENCY_MAPPING).build(); + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).setFrequencyMapping( + TEST_FREQUENCY_MAPPING).build(); assertEquals(TEST_RESONANT_FREQUENCY, info.getAbsoluteFrequency(0), TEST_TOLERANCE); // Safe range [-1, 1] = [125Hz, 175Hz] defined by suggested safe range 100Hz @@ -213,7 +217,7 @@ public class VibratorInfoTest { @Test public void testGetMaxAmplitude_emptyMappingReturnsOnlyResonantFrequency() { - VibratorInfo info = new InfoBuilder().build(); + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertEquals(1f, info.getMaxAmplitude(0), TEST_TOLERANCE); assertEquals(0f, info.getMaxAmplitude(0.1f), TEST_TOLERANCE); assertEquals(0f, info.getMaxAmplitude(-1), TEST_TOLERANCE); @@ -221,7 +225,7 @@ public class VibratorInfoTest { @Test public void testGetMaxAmplitude_validMappingReturnsMappedValues() { - VibratorInfo info = new InfoBuilder() + VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping(/* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, /* frequencyResolutionHz= */ 25, /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP)) @@ -243,8 +247,7 @@ public class VibratorInfoTest { @Test public void testEquals() { - InfoBuilder completeBuilder = new InfoBuilder() - .setId(1) + VibratorInfo.Builder completeBuilder = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL) .setSupportedEffects(VibrationEffect.EFFECT_CLICK) .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK) @@ -298,9 +301,8 @@ public class VibratorInfoTest { .build(); assertNotEquals(complete, completeWithDifferentQFactor); - VibratorInfo empty = new InfoBuilder().setId(1).build(); - VibratorInfo emptyWithKnownSupport = new InfoBuilder() - .setId(1) + VibratorInfo empty = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); + VibratorInfo emptyWithKnownSupport = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setSupportedEffects() .setSupportedPrimitives() .build(); @@ -309,8 +311,7 @@ public class VibratorInfoTest { @Test public void testParceling() { - VibratorInfo original = new InfoBuilder() - .setId(1) + VibratorInfo original = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS) .setSupportedEffects(VibrationEffect.EFFECT_CLICK) .setSupportedPrimitives(null) @@ -324,54 +325,4 @@ public class VibratorInfoTest { VibratorInfo restored = VibratorInfo.CREATOR.createFromParcel(parcel); assertEquals(original, restored); } - - private static class InfoBuilder { - private int mId = 0; - private int mCapabilities = 0; - private int[] mSupportedEffects = null; - private int[] mSupportedBraking = null; - private int[] mSupportedPrimitives = null; - private float mQFactor = Float.NaN; - private VibratorInfo.FrequencyMapping mFrequencyMapping = EMPTY_FREQUENCY_MAPPING; - - public InfoBuilder setId(int id) { - mId = id; - return this; - } - - public InfoBuilder setCapabilities(int capabilities) { - mCapabilities = capabilities; - return this; - } - - public InfoBuilder setSupportedEffects(int... supportedEffects) { - mSupportedEffects = supportedEffects; - return this; - } - - public InfoBuilder setSupportedBraking(int... supportedBraking) { - mSupportedBraking = supportedBraking; - return this; - } - - public InfoBuilder setSupportedPrimitives(int... supportedPrimitives) { - mSupportedPrimitives = supportedPrimitives; - return this; - } - - public InfoBuilder setQFactor(float qFactor) { - mQFactor = qFactor; - return this; - } - - public InfoBuilder setFrequencyMapping(VibratorInfo.FrequencyMapping frequencyMapping) { - mFrequencyMapping = frequencyMapping; - return this; - } - - public VibratorInfo build() { - return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedBraking, - mSupportedPrimitives, mQFactor, mFrequencyMapping); - } - } } diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java index 575a1be905f2a..6213285b068ad 100644 --- a/core/tests/coretests/src/android/os/VibratorTest.java +++ b/core/tests/coretests/src/android/os/VibratorTest.java @@ -54,6 +54,11 @@ public class VibratorTest { mVibratorSpy = spy(InstrumentationRegistry.getContext().getSystemService(Vibrator.class)); } + @Test + public void getId_returnsDefaultId() { + assertEquals(-1, mVibratorSpy.getId()); + } + @Test public void areEffectsSupported_returnsArrayOfSameSize() { assertEquals(0, mVibratorSpy.areEffectsSupported(new int[0]).length); 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 c29593f4bd9af..f65969833521c 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java @@ -182,7 +182,9 @@ public class DeviceVibrationEffectAdapterTest { private static VibratorInfo createVibratorInfo(VibratorInfo.FrequencyMapping frequencyMapping, int... capabilities) { int cap = IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0); - return new VibratorInfo(/* id= */ 0, cap, null, null, null, /* qFactor= */ Float.NaN, - frequencyMapping); + return new VibratorInfo.Builder(0) + .setCapabilities(cap) + .setFrequencyMapping(frequencyMapping) + .build(); } } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java index 2e9aad11f16bc..59370e2106528 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java @@ -298,8 +298,10 @@ public class VibratorControllerTest { VibratorInfo.FrequencyMapping frequencyMapping = new VibratorInfo.FrequencyMapping( Float.NaN, Float.NaN, Float.NaN, Float.NaN, null); when(mNativeWrapperMock.getInfo(/* suggestedFrequencyRange= */ 100)).thenReturn( - new VibratorInfo(VIBRATOR_ID, capabilities, null, null, null, Float.NaN, - frequencyMapping)); + new VibratorInfo.Builder(VIBRATOR_ID) + .setCapabilities(capabilities) + .setFrequencyMapping(frequencyMapping) + .build()); } private PrebakedSegment createPrebaked(int effectId, int effectStrength) {