Merge "Create CombinedVibrationEffect.aidl"
This commit is contained in:
committed by
Android (Google) Code Review
commit
6c7012413e
19
core/java/android/os/CombinedVibrationEffect.aidl
Normal file
19
core/java/android/os/CombinedVibrationEffect.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 CombinedVibrationEffect;
|
||||
150
core/java/android/os/CombinedVibrationEffect.java
Normal file
150
core/java/android/os/CombinedVibrationEffect.java
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 java.util.Objects;
|
||||
|
||||
/**
|
||||
* A CombinedVibrationEffect describes a haptic effect to be performed by one or more {@link
|
||||
* Vibrator Vibrators}.
|
||||
*
|
||||
* These effects may be any number of things, from single shot vibrations to complex waveforms.
|
||||
*
|
||||
* @hide
|
||||
* @see VibrationEffect
|
||||
*/
|
||||
public abstract class CombinedVibrationEffect implements Parcelable {
|
||||
private static final int PARCEL_TOKEN_MONO = 1;
|
||||
|
||||
/** @hide to prevent subclassing from outside of the framework */
|
||||
public CombinedVibrationEffect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a synced vibration effect.
|
||||
*
|
||||
* A synced vibration effect should be performed by multiple vibrators at the same time.
|
||||
*
|
||||
* @param effect The {@link VibrationEffect} to perform
|
||||
* @return The desired combined effect.
|
||||
*/
|
||||
@NonNull
|
||||
public static CombinedVibrationEffect createSynced(@NonNull VibrationEffect effect) {
|
||||
CombinedVibrationEffect combined = new Mono(effect);
|
||||
combined.validate();
|
||||
return combined;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public abstract void validate();
|
||||
|
||||
/**
|
||||
* Represents a single {@link VibrationEffect} that should be executed in all vibrators in sync.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final class Mono extends CombinedVibrationEffect {
|
||||
private final VibrationEffect mEffect;
|
||||
|
||||
public Mono(Parcel in) {
|
||||
mEffect = VibrationEffect.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
public Mono(@NonNull VibrationEffect effect) {
|
||||
mEffect = effect;
|
||||
}
|
||||
|
||||
public VibrationEffect getEffect() {
|
||||
return mEffect;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public void validate() {
|
||||
mEffect.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof CombinedVibrationEffect.Mono)) {
|
||||
return false;
|
||||
}
|
||||
CombinedVibrationEffect.Mono other = (CombinedVibrationEffect.Mono) o;
|
||||
return other.mEffect.equals(other.mEffect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mEffect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mono{mEffect=" + mEffect + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(PARCEL_TOKEN_MONO);
|
||||
mEffect.writeToParcel(out, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<Mono> CREATOR =
|
||||
new Parcelable.Creator<Mono>() {
|
||||
@Override
|
||||
public Mono createFromParcel(@NonNull Parcel in) {
|
||||
// Skip the type token
|
||||
in.readInt();
|
||||
return new Mono(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Mono[] newArray(int size) {
|
||||
return new Mono[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<CombinedVibrationEffect> CREATOR =
|
||||
new Parcelable.Creator<CombinedVibrationEffect>() {
|
||||
@Override
|
||||
public CombinedVibrationEffect createFromParcel(Parcel in) {
|
||||
int token = in.readInt();
|
||||
if (token == PARCEL_TOKEN_MONO) {
|
||||
return new CombinedVibrationEffect.Mono(in);
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"Unexpected combined vibration event type token in parcel.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinedVibrationEffect[] newArray(int size) {
|
||||
return new CombinedVibrationEffect[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.os.CombinedVibrationEffect;
|
||||
import android.os.VibrationAttributes;
|
||||
|
||||
/** {@hide} */
|
||||
interface IVibratorManagerService {
|
||||
int[] getVibratorIds();
|
||||
void vibrate(int uid, String opPkg, in CombinedVibrationEffect effect,
|
||||
in VibrationAttributes attributes, String reason, IBinder token);
|
||||
void cancelVibrate(IBinder token);
|
||||
}
|
||||
|
||||
@@ -983,6 +983,8 @@ public abstract class VibrationEffect implements Parcelable {
|
||||
Composition.checkPrimitive(effect.id);
|
||||
Preconditions.checkArgumentInRange(
|
||||
effect.scale, 0.0f, 1.0f, "scale");
|
||||
Preconditions.checkArgumentNonNegative(effect.delay,
|
||||
"Primitive delay must be zero or positive");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 org.testng.Assert.assertThrows;
|
||||
|
||||
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 CombinedVibrationEffectTest {
|
||||
|
||||
@Test
|
||||
public void testValidateMono() {
|
||||
CombinedVibrationEffect.createSynced(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> CombinedVibrationEffect.createSynced(new VibrationEffect.OneShot(-1, -1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationMono() {
|
||||
CombinedVibrationEffect original = CombinedVibrationEffect.createSynced(
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
|
||||
|
||||
Parcel parcel = Parcel.obtain();
|
||||
original.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
CombinedVibrationEffect restored = CombinedVibrationEffect.CREATOR.createFromParcel(parcel);
|
||||
assertEquals(original, restored);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.content.ContentInterface;
|
||||
import android.content.ContentResolver;
|
||||
@@ -99,6 +100,73 @@ public class VibrationEffectTest {
|
||||
assertEquals(expectedEffect, effect);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateOneShot() {
|
||||
VibrationEffect.createOneShot(1, 255).validate();
|
||||
VibrationEffect.createOneShot(1, VibrationEffect.DEFAULT_AMPLITUDE).validate();
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createOneShot(-1, 255).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createOneShot(0, 255).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createOneShot(1, -2).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createOneShot(1, 256).validate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidatePrebaked() {
|
||||
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK).validate();
|
||||
VibrationEffect.createPredefined(VibrationEffect.RINGTONES[1]).validate();
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createPredefined(-1).validate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateWaveform() {
|
||||
VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1).validate();
|
||||
VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, 0).validate();
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createWaveform(new long[0], new int[0], -1).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createWaveform(TEST_TIMINGS, new int[0], -1).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createWaveform(
|
||||
new long[]{0, 0, 0}, TEST_AMPLITUDES, -1).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createWaveform(
|
||||
TEST_TIMINGS, new int[]{-1, -1, -2}, -1).validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.createWaveform(
|
||||
TEST_TIMINGS, TEST_AMPLITUDES, TEST_TIMINGS.length).validate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateComposed() {
|
||||
VibrationEffect.startComposition()
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10)
|
||||
.compose()
|
||||
.validate();
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.startComposition().addPrimitive(-1).compose().validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.startComposition()
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, -1, 10)
|
||||
.compose()
|
||||
.validate());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> VibrationEffect.startComposition()
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1)
|
||||
.compose()
|
||||
.validate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScalePrebaked_ignoresScaleAndReturnsSameEffect() {
|
||||
VibrationEffect initial = VibrationEffect.get(VibrationEffect.RINGTONES[1]);
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.CombinedVibrationEffect;
|
||||
import android.os.IBinder;
|
||||
import android.os.IVibratorManagerService;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.VibrationAttributes;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
@@ -66,6 +69,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
|
||||
return Arrays.copyOf(mVibratorIds, mVibratorIds.length);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void vibrate(int uid, String opPkg, CombinedVibrationEffect effect,
|
||||
@Nullable VibrationAttributes attrs, String reason, IBinder token) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelVibrate(IBinder token) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
|
||||
String[] args, ShellCallback cb, ResultReceiver resultReceiver) {
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import static com.android.server.testutils.TestUtils.assertExpectException;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.os.CombinedVibrationEffect;
|
||||
import android.os.Process;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
@@ -40,9 +46,16 @@ import org.mockito.junit.MockitoRule;
|
||||
@Presubmit
|
||||
public class VibratorManagerServiceTest {
|
||||
|
||||
@Rule public MockitoRule rule = MockitoJUnit.rule();
|
||||
private static final int UID = Process.ROOT_UID;
|
||||
private static final String PACKAGE_NAME = "package";
|
||||
private static final VibrationAttributes ALARM_ATTRS =
|
||||
new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build();
|
||||
|
||||
@Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock;
|
||||
@Rule
|
||||
public MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private VibratorManagerService.NativeWrapper mNativeWrapperMock;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -72,7 +85,26 @@ public class VibratorManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() {
|
||||
when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{ 1, 2 });
|
||||
assertArrayEquals(new int[]{ 1, 2 }, createService().getVibratorIds());
|
||||
when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1, 2});
|
||||
assertArrayEquals(new int[]{1, 2}, createService().getVibratorIds());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vibrate_isUnsupported() {
|
||||
VibratorManagerService service = createService();
|
||||
CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced(
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
|
||||
assertExpectException(UnsupportedOperationException.class,
|
||||
"Not implemented",
|
||||
() -> service.vibrate(UID, PACKAGE_NAME, effect, ALARM_ATTRS, "reason", service));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelVibrate_isUnsupported() {
|
||||
VibratorManagerService service = createService();
|
||||
CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced(
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
|
||||
assertExpectException(UnsupportedOperationException.class,
|
||||
"Not implemented", () -> service.cancelVibrate(service));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user