Create parcelable VibratorInfo to expose HAL profile
This parcelable will replace the separated methods hasAmplitudeControl,
areEffectsSupported and arePrimitiveSupported from VibratorService.
VibratorManagerService will return this single parcelable, per vibator
id, to represent the HAL profile of that individual vibrator and be used
by Vibrator.java to explose some of that to the public API.
Bug: 167946816
Test: atest VibratorInfoTest
atest VibratorManagerServiceTest
Change-Id: I09c191dd15a3cf38122ec6dc87b2d73f46c8cde6
This commit is contained in:
@@ -18,10 +18,12 @@ package android.os;
|
||||
|
||||
import android.os.CombinedVibrationEffect;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibratorInfo;
|
||||
|
||||
/** {@hide} */
|
||||
interface IVibratorManagerService {
|
||||
int[] getVibratorIds();
|
||||
VibratorInfo getVibratorInfo(int vibratorId);
|
||||
boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
|
||||
in CombinedVibrationEffect effect, in VibrationAttributes attributes);
|
||||
void vibrate(int uid, String opPkg, in CombinedVibrationEffect effect,
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.os;
|
||||
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibratorInfo;
|
||||
import android.os.IVibratorStateListener;
|
||||
|
||||
/** {@hide} */
|
||||
@@ -25,11 +26,10 @@ interface IVibratorService
|
||||
{
|
||||
boolean hasVibrator();
|
||||
boolean isVibrating();
|
||||
VibratorInfo getVibratorInfo();
|
||||
boolean registerVibratorStateListener(in IVibratorStateListener listener);
|
||||
boolean unregisterVibratorStateListener(in IVibratorStateListener listener);
|
||||
boolean hasAmplitudeControl();
|
||||
int[] areEffectsSupported(in int[] effectIds);
|
||||
boolean[] arePrimitivesSupported(in int[] primitiveIds);
|
||||
void vibrate(int uid, String opPkg, in VibrationEffect effect,
|
||||
in VibrationAttributes attributes, String reason, IBinder token);
|
||||
void cancelVibrate(IBinder token);
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.os;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.media.AudioAttributes;
|
||||
@@ -39,8 +40,11 @@ public class SystemVibrator extends Vibrator {
|
||||
|
||||
private final IVibratorService mService;
|
||||
private final IVibratorManagerService mManagerService;
|
||||
private final Object mLock = new Object();
|
||||
private final Binder mToken = new Binder();
|
||||
private final Context mContext;
|
||||
@GuardedBy("mLock")
|
||||
private VibratorInfo mVibratorInfo;
|
||||
|
||||
@GuardedBy("mDelegates")
|
||||
private final ArrayMap<OnVibratorStateChangedListener,
|
||||
@@ -242,23 +246,26 @@ public class SystemVibrator extends Vibrator {
|
||||
|
||||
@Override
|
||||
public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) {
|
||||
try {
|
||||
return mService.areEffectsSupported(effectIds);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to query effect support");
|
||||
throw e.rethrowAsRuntimeException();
|
||||
VibratorInfo vibratorInfo = getVibratorInfo();
|
||||
int[] supported = new int[effectIds.length];
|
||||
for (int i = 0; i < effectIds.length; i++) {
|
||||
supported[i] = vibratorInfo == null
|
||||
? Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN
|
||||
: vibratorInfo.isEffectSupported(effectIds[i]);
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] arePrimitivesSupported(
|
||||
@NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
|
||||
try {
|
||||
return mService.arePrimitivesSupported(primitiveIds);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to query effect support");
|
||||
throw e.rethrowAsRuntimeException();
|
||||
VibratorInfo vibratorInfo = getVibratorInfo();
|
||||
boolean[] supported = new boolean[primitiveIds.length];
|
||||
for (int i = 0; i < primitiveIds.length; i++) {
|
||||
supported[i] = vibratorInfo == null
|
||||
? false : vibratorInfo.isPrimitiveSupported(primitiveIds[i]);
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -272,4 +279,22 @@ public class SystemVibrator extends Vibrator {
|
||||
Log.w(TAG, "Failed to cancel vibration.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VibratorInfo getVibratorInfo() {
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
if (mVibratorInfo != null) {
|
||||
return mVibratorInfo;
|
||||
}
|
||||
if (mService == null) {
|
||||
return null;
|
||||
}
|
||||
return mVibratorInfo = mService.getVibratorInfo();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to query vibrator info");
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,6 +476,28 @@ public abstract class VibrationEffect implements Parcelable {
|
||||
return a * fx;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static String effectIdToString(int effectId) {
|
||||
switch (effectId) {
|
||||
case EFFECT_CLICK:
|
||||
return "CLICK";
|
||||
case EFFECT_TICK:
|
||||
return "TICK";
|
||||
case EFFECT_HEAVY_CLICK:
|
||||
return "HEAVY_CLICK";
|
||||
case EFFECT_DOUBLE_CLICK:
|
||||
return "DOUBLE_CLICK";
|
||||
case EFFECT_POP:
|
||||
return "POP";
|
||||
case EFFECT_THUD:
|
||||
return "THUD";
|
||||
case EFFECT_TEXTURE_TICK:
|
||||
return "TEXTURE_TICK";
|
||||
default:
|
||||
return Integer.toString(effectId);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@TestApi
|
||||
public static class OneShot extends VibrationEffect implements Parcelable {
|
||||
@@ -1201,10 +1223,8 @@ public abstract class VibrationEffect implements Parcelable {
|
||||
return "PRIMITIVE_QUICK_FALL";
|
||||
case PRIMITIVE_TICK:
|
||||
return "PRIMITIVE_TICK";
|
||||
|
||||
default:
|
||||
return Integer.toString(id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
core/java/android/os/VibratorInfo.aidl
Normal file
19
core/java/android/os/VibratorInfo.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 android.os;
|
||||
|
||||
parcelable VibratorInfo;
|
||||
229
core/java/android/os/VibratorInfo.java
Normal file
229
core/java/android/os/VibratorInfo.java
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 android.os;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A VibratorInfo describes the capabilities of a {@link Vibrator}.
|
||||
*
|
||||
* This description includes its capabilities, list of supported effects and composition primitives.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class VibratorInfo implements Parcelable {
|
||||
|
||||
/**
|
||||
* Capability to set amplitude values to vibrations.
|
||||
* @hide
|
||||
*/
|
||||
// Internally this maps to the HAL constant IVibrator::CAP_AMPLITUDE_CONTROL
|
||||
public static final int CAPABILITY_AMPLITUDE_CONTROL = 4;
|
||||
|
||||
/**
|
||||
* Capability to compose primitives into a single effect.
|
||||
* @hide
|
||||
*/
|
||||
// Internally this maps to the HAL constant IVibrator::CAP_COMPOSE_EFFECTS
|
||||
public static final int CAPABILITY_COMPOSE_EFFECTS = 32;
|
||||
|
||||
private final int mId;
|
||||
private final long mCapabilities;
|
||||
@Nullable
|
||||
private final SparseBooleanArray mSupportedEffects;
|
||||
@Nullable
|
||||
private final SparseBooleanArray mSupportedPrimitives;
|
||||
|
||||
VibratorInfo(Parcel in) {
|
||||
mId = in.readInt();
|
||||
mCapabilities = in.readLong();
|
||||
mSupportedEffects = in.readSparseBooleanArray();
|
||||
mSupportedPrimitives = in.readSparseBooleanArray();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public VibratorInfo(int id, long capabilities, int[] supportedEffects,
|
||||
int[] supportedPrimitives) {
|
||||
mId = id;
|
||||
mCapabilities = capabilities;
|
||||
mSupportedEffects = toSparseBooleanArray(supportedEffects);
|
||||
mSupportedPrimitives = toSparseBooleanArray(supportedPrimitives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mId);
|
||||
dest.writeLong(mCapabilities);
|
||||
dest.writeSparseBooleanArray(mSupportedEffects);
|
||||
dest.writeSparseBooleanArray(mSupportedPrimitives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof VibratorInfo)) {
|
||||
return false;
|
||||
}
|
||||
VibratorInfo that = (VibratorInfo) o;
|
||||
return mId == that.mId && mCapabilities == that.mCapabilities
|
||||
&& Objects.equals(mSupportedEffects, that.mSupportedEffects)
|
||||
&& Objects.equals(mSupportedPrimitives, that.mSupportedPrimitives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VibratorInfo{"
|
||||
+ "mId=" + mId
|
||||
+ ", mCapabilities=" + Arrays.toString(getCapabilitiesNames())
|
||||
+ ", mCapabilities flags=" + mCapabilities
|
||||
+ ", mSupportedEffects=" + Arrays.toString(getSupportedEffectsNames())
|
||||
+ ", mSupportedPrimitives=" + Arrays.toString(getSupportedPrimitivesNames())
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/** Return the id of this vibrator. */
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the vibrator has amplitude control.
|
||||
*
|
||||
* @return True if the hardware can control the amplitude of the vibrations, otherwise false.
|
||||
*/
|
||||
public boolean hasAmplitudeControl() {
|
||||
return hasCapability(CAPABILITY_AMPLITUDE_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query whether the vibrator supports the given effect.
|
||||
*
|
||||
* @param effectId Which effects to query for.
|
||||
* @return {@link Vibrator#VIBRATION_EFFECT_SUPPORT_YES} if the effect is supported,
|
||||
* {@link Vibrator#VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or
|
||||
* {@link Vibrator#VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's
|
||||
* supported or not.
|
||||
*/
|
||||
@Vibrator.VibrationEffectSupport
|
||||
public int isEffectSupported(@VibrationEffect.EffectType int effectId) {
|
||||
if (mSupportedEffects == null) {
|
||||
return Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN;
|
||||
}
|
||||
return mSupportedEffects.get(effectId, false) ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES
|
||||
: Vibrator.VIBRATION_EFFECT_SUPPORT_NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query whether the vibrator supports the given primitive.
|
||||
*
|
||||
* @param primitiveId Which primitives to query for.
|
||||
* @return Whether the primitive is supported.
|
||||
*/
|
||||
public boolean isPrimitiveSupported(@VibrationEffect.Composition.Primitive int primitiveId) {
|
||||
return hasCapability(CAPABILITY_COMPOSE_EFFECTS) && mSupportedPrimitives != null
|
||||
&& mSupportedPrimitives.get(primitiveId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check against this vibrator capabilities.
|
||||
*
|
||||
* @param capability one of IVibrator.CAP_*
|
||||
* @return true if this vibrator has this capability, false otherwise
|
||||
* @hide
|
||||
*/
|
||||
public boolean hasCapability(long capability) {
|
||||
return (mCapabilities & capability) == capability;
|
||||
}
|
||||
|
||||
private String[] getCapabilitiesNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
if (hasCapability(CAPABILITY_AMPLITUDE_CONTROL)) {
|
||||
names.add("AMPLITUDE_CONTROL");
|
||||
}
|
||||
if (hasCapability(CAPABILITY_COMPOSE_EFFECTS)) {
|
||||
names.add("COMPOSE_EFFECTS");
|
||||
}
|
||||
return names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
private String[] getSupportedEffectsNames() {
|
||||
if (mSupportedEffects == null) {
|
||||
return new String[0];
|
||||
}
|
||||
String[] names = new String[mSupportedEffects.size()];
|
||||
for (int i = 0; i < mSupportedEffects.size(); i++) {
|
||||
names[i] = VibrationEffect.effectIdToString(mSupportedEffects.keyAt(i));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
private String[] getSupportedPrimitivesNames() {
|
||||
if (mSupportedPrimitives == null) {
|
||||
return new String[0];
|
||||
}
|
||||
String[] names = new String[mSupportedPrimitives.size()];
|
||||
for (int i = 0; i < mSupportedPrimitives.size(); i++) {
|
||||
names[i] = VibrationEffect.Composition.primitiveToString(mSupportedPrimitives.keyAt(i));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SparseBooleanArray toSparseBooleanArray(int[] values) {
|
||||
if (values == null) {
|
||||
return null;
|
||||
}
|
||||
SparseBooleanArray array = new SparseBooleanArray();
|
||||
for (int value : values) {
|
||||
array.put(value, true);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<VibratorInfo> CREATOR =
|
||||
new Creator<VibratorInfo>() {
|
||||
@Override
|
||||
public VibratorInfo createFromParcel(Parcel in) {
|
||||
return new VibratorInfo(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VibratorInfo[] newArray(int size) {
|
||||
return new VibratorInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
112
core/tests/coretests/src/android/os/VibratorInfoTest.java
Normal file
112
core/tests/coretests/src/android/os/VibratorInfoTest.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 android.os;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
@Presubmit
|
||||
@RunWith(JUnit4.class)
|
||||
public class VibratorInfoTest {
|
||||
|
||||
@Test
|
||||
public void testHasAmplitudeControl() {
|
||||
assertFalse(createInfo(/* capabilities= */ 0).hasAmplitudeControl());
|
||||
assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS
|
||||
| VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL).hasAmplitudeControl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasCapabilities() {
|
||||
assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS)
|
||||
.hasCapability(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS));
|
||||
assertFalse(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS)
|
||||
.hasCapability(VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEffectSupported() {
|
||||
VibratorInfo info = new VibratorInfo(/* id= */ 0, /* capabilities= */0,
|
||||
new int[]{VibrationEffect.EFFECT_CLICK}, null);
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN,
|
||||
createInfo(/* capabilities= */ 0).isEffectSupported(VibrationEffect.EFFECT_CLICK));
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
|
||||
info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
|
||||
info.isEffectSupported(VibrationEffect.EFFECT_TICK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPrimitiveSupported() {
|
||||
VibratorInfo info = new VibratorInfo(/* id= */ 0, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS,
|
||||
null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
|
||||
assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
|
||||
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
|
||||
|
||||
// Returns false when there is no compose capability.
|
||||
info = new VibratorInfo(/* id= */ 0, /* capabilities= */ 0,
|
||||
null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
|
||||
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
VibratorInfo empty = new VibratorInfo(1, 0, null, null);
|
||||
VibratorInfo complete = new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
|
||||
new int[]{VibrationEffect.EFFECT_CLICK},
|
||||
new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
|
||||
|
||||
assertEquals(complete, complete);
|
||||
assertEquals(complete, new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
|
||||
new int[]{VibrationEffect.EFFECT_CLICK},
|
||||
new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}));
|
||||
|
||||
assertFalse(empty.equals(new VibratorInfo(1, 0, new int[]{}, new int[]{})));
|
||||
assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS,
|
||||
new int[]{VibrationEffect.EFFECT_CLICK},
|
||||
new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})));
|
||||
assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
|
||||
new int[]{}, new int[]{})));
|
||||
assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
|
||||
null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})));
|
||||
assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
|
||||
new int[]{VibrationEffect.EFFECT_CLICK}, null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerialization() {
|
||||
VibratorInfo original = new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS,
|
||||
new int[]{VibrationEffect.EFFECT_CLICK}, null);
|
||||
|
||||
Parcel parcel = Parcel.obtain();
|
||||
original.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
VibratorInfo restored = VibratorInfo.CREATOR.createFromParcel(parcel);
|
||||
assertEquals(original, restored);
|
||||
}
|
||||
|
||||
private static VibratorInfo createInfo(long capabilities) {
|
||||
return new VibratorInfo(/* id= */ 0, capabilities, null, null);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,26 @@ public class VibratorTest {
|
||||
mVibratorSpy = spy(InstrumentationRegistry.getContext().getSystemService(Vibrator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areEffectsSupported_returnsArrayOfSameSize() {
|
||||
assertEquals(0, mVibratorSpy.areEffectsSupported(new int[0]).length);
|
||||
assertEquals(1,
|
||||
mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}).length);
|
||||
assertEquals(2,
|
||||
mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK,
|
||||
VibrationEffect.EFFECT_TICK}).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_returnsArrayOfSameSize() {
|
||||
assertEquals(0, mVibratorSpy.arePrimitivesSupported(new int[0]).length);
|
||||
assertEquals(1, mVibratorSpy.arePrimitivesSupported(
|
||||
new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}).length);
|
||||
assertEquals(2, mVibratorSpy.arePrimitivesSupported(
|
||||
new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE}).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vibrate_withAudioAttributes_createsVibrationAttributesWithSameUsage() {
|
||||
VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.os.Trace;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorInfo;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
|
||||
@@ -165,6 +166,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@Nullable
|
||||
public VibratorInfo getVibratorInfo(int vibratorId) {
|
||||
VibratorController controller = mVibrators.get(vibratorId);
|
||||
return controller == null ? null : controller.getVibratorInfo();
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int[] getVibratorIds() {
|
||||
return Arrays.copyOf(mVibratorIds, mVibratorIds.length);
|
||||
|
||||
@@ -51,6 +51,7 @@ import android.os.Trace;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorInfo;
|
||||
import android.os.WorkSource;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -343,6 +344,11 @@ public class VibratorService extends IVibratorService.Stub {
|
||||
return mVibratorController.isVibrating();
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public VibratorInfo getVibratorInfo() {
|
||||
return mVibratorController.getVibratorInfo();
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public boolean registerVibratorStateListener(IVibratorStateListener listener) {
|
||||
if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) {
|
||||
@@ -367,16 +373,6 @@ public class VibratorService extends IVibratorService.Stub {
|
||||
|| mVibratorController.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int[] areEffectsSupported(int[] effectIds) {
|
||||
return mVibratorController.areEffectsSupported(effectIds);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public boolean[] arePrimitivesSupported(int[] primitiveIds) {
|
||||
return mVibratorController.arePrimitivesSupported(primitiveIds);
|
||||
}
|
||||
|
||||
private void verifyIncomingUid(int uid) {
|
||||
if (uid == Binder.getCallingUid()) {
|
||||
return;
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.os.IVibratorStateListener;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorInfo;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -31,10 +31,6 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import libcore.util.NativeAllocationRegistry;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/** Controls a single vibrator. */
|
||||
// TODO(b/159207608): Make this package-private once vibrator services are moved to this package
|
||||
public final class VibratorController {
|
||||
@@ -42,12 +38,7 @@ public final class VibratorController {
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final NativeWrapper mNativeWrapper;
|
||||
private final int mVibratorId;
|
||||
private final long mCapabilities;
|
||||
@Nullable
|
||||
private final Set<Integer> mSupportedEffects;
|
||||
@Nullable
|
||||
private final Set<Integer> mSupportedPrimitives;
|
||||
private final VibratorInfo mVibratorInfo;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners =
|
||||
@@ -115,13 +106,11 @@ public final class VibratorController {
|
||||
@VisibleForTesting
|
||||
public VibratorController(int vibratorId, OnVibrationCompleteListener listener,
|
||||
NativeWrapper nativeWrapper) {
|
||||
mVibratorId = vibratorId;
|
||||
mNativeWrapper = nativeWrapper;
|
||||
mNativeWrapper.init(vibratorId, listener);
|
||||
|
||||
nativeWrapper.init(vibratorId, listener);
|
||||
mCapabilities = nativeWrapper.getCapabilities();
|
||||
mSupportedEffects = asSet(nativeWrapper.getSupportedEffects());
|
||||
mSupportedPrimitives = asSet(nativeWrapper.getSupportedPrimitives());
|
||||
mVibratorInfo = new VibratorInfo(vibratorId, nativeWrapper.getCapabilities(),
|
||||
nativeWrapper.getSupportedEffects(), nativeWrapper.getSupportedPrimitives());
|
||||
}
|
||||
|
||||
/** Register state listener for this vibrator. */
|
||||
@@ -153,9 +142,9 @@ public final class VibratorController {
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the id of the vibrator controlled by this instance. */
|
||||
public int getVibratorId() {
|
||||
return mVibratorId;
|
||||
/** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */
|
||||
public VibratorInfo getVibratorInfo() {
|
||||
return mVibratorInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,43 +173,7 @@ public final class VibratorController {
|
||||
* @return true if this vibrator has this capability, false otherwise
|
||||
*/
|
||||
public boolean hasCapability(long capability) {
|
||||
return (mCapabilities & capability) == capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check against this vibrator supported effects.
|
||||
*
|
||||
* @param effectIds list of effects, one of VibrationEffect.EFFECT_*
|
||||
* @return one entry per requested effectId, with one of Vibrator.VIBRATION_EFFECT_SUPPORT_*
|
||||
*/
|
||||
public int[] areEffectsSupported(int[] effectIds) {
|
||||
int[] supported = new int[effectIds.length];
|
||||
if (mSupportedEffects == null) {
|
||||
Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN);
|
||||
} else {
|
||||
for (int i = 0; i < effectIds.length; i++) {
|
||||
supported[i] = mSupportedEffects.contains(effectIds[i])
|
||||
? Vibrator.VIBRATION_EFFECT_SUPPORT_YES
|
||||
: Vibrator.VIBRATION_EFFECT_SUPPORT_NO;
|
||||
}
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check against this vibrator supported primitives.
|
||||
*
|
||||
* @param primitiveIds list of primitives, one of VibrationEffect.Composition.EFFECT_*
|
||||
* @return one entry per requested primitiveId, with true if it is supported
|
||||
*/
|
||||
public boolean[] arePrimitivesSupported(int[] primitiveIds) {
|
||||
boolean[] supported = new boolean[primitiveIds.length];
|
||||
if (mSupportedPrimitives != null && hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
|
||||
for (int i = 0; i < primitiveIds.length; i++) {
|
||||
supported[i] = mSupportedPrimitives.contains(primitiveIds[i]);
|
||||
}
|
||||
}
|
||||
return supported;
|
||||
return mVibratorInfo.hasCapability(capability);
|
||||
}
|
||||
|
||||
/** Return {@code true} if the underlying vibrator is currently available, false otherwise. */
|
||||
@@ -234,7 +187,7 @@ public final class VibratorController {
|
||||
* <p>This will affect the state of {@link #isUnderExternalControl()}.
|
||||
*/
|
||||
public void setExternalControl(boolean externalControl) {
|
||||
if (!hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
|
||||
if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
|
||||
return;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
@@ -248,7 +201,7 @@ public final class VibratorController {
|
||||
* if given {@code effect} is {@code null}.
|
||||
*/
|
||||
public void updateAlwaysOn(int id, @Nullable VibrationEffect.Prebaked effect) {
|
||||
if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
|
||||
if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
|
||||
return;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
@@ -263,7 +216,7 @@ public final class VibratorController {
|
||||
/** Set the vibration amplitude. This will NOT affect the state of {@link #isVibrating()}. */
|
||||
public void setAmplitude(int amplitude) {
|
||||
synchronized (mLock) {
|
||||
if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
|
||||
if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
|
||||
mNativeWrapper.setAmplitude(amplitude);
|
||||
}
|
||||
}
|
||||
@@ -306,7 +259,7 @@ public final class VibratorController {
|
||||
* <p>This will affect the state of {@link #isVibrating()}.
|
||||
*/
|
||||
public void on(VibrationEffect.Composed effect, long vibrationId) {
|
||||
if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
|
||||
if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
|
||||
return;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
@@ -327,10 +280,7 @@ public final class VibratorController {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VibratorController{"
|
||||
+ "mVibratorId=" + mVibratorId
|
||||
+ ", mCapabilities=" + mCapabilities
|
||||
+ ", mSupportedEffects=" + mSupportedEffects
|
||||
+ ", mSupportedPrimitives=" + mSupportedPrimitives
|
||||
+ "mVibratorInfo=" + mVibratorInfo
|
||||
+ ", mIsVibrating=" + mIsVibrating
|
||||
+ ", mIsUnderExternalControl=" + mIsUnderExternalControl
|
||||
+ ", mVibratorStateListeners count="
|
||||
@@ -375,18 +325,6 @@ public final class VibratorController {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Set<Integer> asSet(int[] values) {
|
||||
if (values == null) {
|
||||
return null;
|
||||
}
|
||||
HashSet<Integer> set = new HashSet<>();
|
||||
for (int value : values) {
|
||||
set.add(value);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/** Wrapper around the static-native methods of {@link VibratorController} for tests. */
|
||||
@VisibleForTesting
|
||||
public static class NativeWrapper {
|
||||
|
||||
@@ -19,7 +19,10 @@ package com.android.server;
|
||||
import static com.android.server.testutils.TestUtils.assertExpectException;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -38,6 +41,8 @@ import android.os.PowerSaveState;
|
||||
import android.os.Process;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorInfo;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
@@ -134,17 +139,48 @@ public class VibratorManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() {
|
||||
mNativeWrappers.put(1, mockVibrator(0));
|
||||
mNativeWrappers.put(2, mockVibrator(0));
|
||||
mNativeWrappers.put(1, mockVibrator(/* capabilities= */ 0));
|
||||
mNativeWrappers.put(2, mockVibrator(/* capabilities= */ 0));
|
||||
when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{2, 1});
|
||||
assertArrayEquals(new int[]{2, 1}, createService().getVibratorIds());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVibratorInfo_withMissingVibratorId_returnsNull() {
|
||||
mockVibrators(mockVibrator(/* capabilities= */ 0));
|
||||
assertNull(createService().getVibratorInfo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVibratorInfo_withExistingVibratorId_returnsHalInfoForVibrator() {
|
||||
VibratorController.NativeWrapper vibratorMock = mockVibrator(
|
||||
IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
when(vibratorMock.getSupportedEffects()).thenReturn(
|
||||
new int[]{VibrationEffect.EFFECT_CLICK});
|
||||
when(vibratorMock.getSupportedPrimitives()).thenReturn(
|
||||
new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
|
||||
mNativeWrappers.put(1, vibratorMock);
|
||||
when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1});
|
||||
VibratorInfo info = createService().getVibratorInfo(1);
|
||||
|
||||
assertNotNull(info);
|
||||
assertEquals(1, info.getId());
|
||||
assertTrue(info.hasAmplitudeControl());
|
||||
assertTrue(info.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS));
|
||||
assertFalse(info.hasCapability(IVibrator.CAP_ON_CALLBACK));
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
|
||||
info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
|
||||
info.isEffectSupported(VibrationEffect.EFFECT_TICK));
|
||||
assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
|
||||
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAlwaysOnEffect_withMono_enablesAlwaysOnEffectToAllVibratorsWithCapability() {
|
||||
VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] {
|
||||
VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[]{
|
||||
mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
|
||||
mockVibrator(0),
|
||||
mockVibrator(/* capabilities= */ 0),
|
||||
mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
|
||||
};
|
||||
mockVibrators(vibratorMocks);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -62,6 +61,7 @@ import android.os.UserHandle;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorInfo;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings;
|
||||
@@ -235,56 +235,21 @@ public class VibratorServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() {
|
||||
when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null);
|
||||
assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN},
|
||||
createService().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() {
|
||||
int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK};
|
||||
|
||||
public void getVibratorInfo_returnsSameInfoFromNative() {
|
||||
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
when(mNativeWrapperMock.getSupportedEffects())
|
||||
.thenReturn(new int[]{VibrationEffect.EFFECT_CLICK});
|
||||
assertArrayEquals(
|
||||
new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
|
||||
Vibrator.VIBRATION_EFFECT_SUPPORT_NO},
|
||||
createService().areEffectsSupported(effects));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() {
|
||||
assertArrayEquals(new boolean[]{false, false},
|
||||
createService().arePrimitivesSupported(new int[]{
|
||||
VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_TICK
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() {
|
||||
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
|
||||
when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null);
|
||||
|
||||
assertArrayEquals(new boolean[]{false, false},
|
||||
createService().arePrimitivesSupported(new int[]{
|
||||
VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() {
|
||||
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
|
||||
when(mNativeWrapperMock.getSupportedPrimitives())
|
||||
.thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
|
||||
|
||||
assertArrayEquals(new boolean[]{true, false},
|
||||
createService().arePrimitivesSupported(new int[]{
|
||||
VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
|
||||
}));
|
||||
VibratorInfo info = createService().getVibratorInfo();
|
||||
assertTrue(info.hasAmplitudeControl());
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
|
||||
info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
|
||||
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
|
||||
info.isEffectSupported(VibrationEffect.EFFECT_TICK));
|
||||
assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
|
||||
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server.vibrator;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -38,7 +37,6 @@ import android.hardware.vibrator.IVibrator;
|
||||
import android.os.IBinder;
|
||||
import android.os.IVibratorStateListener;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
@@ -100,7 +98,7 @@ public class VibratorControllerTest {
|
||||
public void createController_initializesNativeWrapper() {
|
||||
int vibratorId = 13;
|
||||
VibratorController controller = createController(vibratorId);
|
||||
assertEquals(vibratorId, controller.getVibratorId());
|
||||
assertEquals(vibratorId, controller.getVibratorInfo().getId());
|
||||
verify(mNativeWrapperMock).init(eq(vibratorId), notNull());
|
||||
}
|
||||
|
||||
@@ -131,59 +129,6 @@ public class VibratorControllerTest {
|
||||
assertFalse(createController().hasCapability(IVibrator.CAP_ON_CALLBACK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() {
|
||||
when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null);
|
||||
assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN},
|
||||
createController().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() {
|
||||
int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK};
|
||||
|
||||
when(mNativeWrapperMock.getSupportedEffects())
|
||||
.thenReturn(new int[]{VibrationEffect.EFFECT_CLICK});
|
||||
assertArrayEquals(
|
||||
new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
|
||||
Vibrator.VIBRATION_EFFECT_SUPPORT_NO},
|
||||
createController().areEffectsSupported(effects));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() {
|
||||
assertArrayEquals(new boolean[]{false, false},
|
||||
createController().arePrimitivesSupported(new int[]{
|
||||
VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_TICK
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() {
|
||||
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
|
||||
when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null);
|
||||
|
||||
assertArrayEquals(new boolean[]{false, false},
|
||||
createController().arePrimitivesSupported(new int[]{
|
||||
VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() {
|
||||
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
|
||||
when(mNativeWrapperMock.getSupportedPrimitives())
|
||||
.thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
|
||||
|
||||
assertArrayEquals(new boolean[]{true, false},
|
||||
createController().arePrimitivesSupported(new int[]{
|
||||
VibrationEffect.Composition.PRIMITIVE_CLICK,
|
||||
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExternalControl_withCapability_enablesExternalControl() {
|
||||
mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
|
||||
|
||||
Reference in New Issue
Block a user