diff options
| author | Michael Wright <michaelwr@google.com> | 2017-01-31 18:33:54 +0000 |
|---|---|---|
| committer | Michael Wright <michaelwr@google.com> | 2017-03-20 16:09:51 +0000 |
| commit | 7121697a5e2d4458f6f63e9eb3b5deec62ee6202 (patch) | |
| tree | 62b6318b0535f6429b4b0b23b203fe97ef48bfde /core/java/android | |
| parent | 66dc7be9e69158e44bd933d9dc6eedded67cea3d (diff) | |
BZZZZZZT! BZZZZZT! New Vibrator APIs
Replace the existing Vibrator APIs with a new class to encapsulate the
haptic effect information, and add the ability to control the vibration
strength.
Test: cts-tradefed run commandAndExit cts-dev -m CtsOsTestCases -t android.os.cts.VibratorTest
cts-tradefed run commandAndExit cts-dev -m CtsOsTestCases -t android.os.cts.VibrationEffectTest
runtest systemui-notification
Manual testing with $T/google_experimental/users/michaelwr/Vibrator
Bug: 30961353
Change-Id: Idbb9864a7b084c85e7b7de3257a0e6b40d9d91d6
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/hardware/input/InputManager.java | 29 | ||||
| -rw-r--r-- | core/java/android/os/IVibratorService.aidl | 6 | ||||
| -rw-r--r-- | core/java/android/os/NullVibrator.java | 16 | ||||
| -rw-r--r-- | core/java/android/os/SystemVibrator.java | 42 | ||||
| -rw-r--r-- | core/java/android/os/VibrationEffect.aidl | 22 | ||||
| -rw-r--r-- | core/java/android/os/VibrationEffect.java | 444 | ||||
| -rw-r--r-- | core/java/android/os/Vibrator.java | 52 |
7 files changed, 546 insertions, 65 deletions
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 6e202b00274f..631b77d4132c 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.Vibrator; +import android.os.VibrationEffect; import android.os.ServiceManager.ServiceNotFoundException; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -1154,23 +1155,33 @@ public final class InputManager { return true; } - /** - * @hide - */ @Override - public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) { - vibrate(new long[] { 0, milliseconds}, -1); + public boolean hasAmplitudeControl() { + return false; } /** * @hide */ @Override - public void vibrate(int uid, String opPkg, long[] pattern, int repeat, - AudioAttributes attributes) { - if (repeat >= pattern.length) { - throw new ArrayIndexOutOfBoundsException(); + public void vibrate(int uid, String opPkg, + VibrationEffect effect, AudioAttributes attributes) { + long[] pattern; + int repeat; + if (effect instanceof VibrationEffect.OneShot) { + VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect; + pattern = new long[] { 0, oneShot.getTiming() }; + repeat = -1; + } else if (effect instanceof VibrationEffect.Waveform) { + VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect; + pattern = waveform.getTimings(); + repeat = waveform.getRepeatIndex(); + } else { + // TODO: Add support for prebaked effects + Log.w(TAG, "Pre-baked effects aren't supported on input devices"); + return; } + try { mIm.vibrate(mDeviceId, pattern, repeat, mToken); } catch (RemoteException ex) { diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl index 6f2857d46625..e59c3ae16ef7 100644 --- a/core/java/android/os/IVibratorService.aidl +++ b/core/java/android/os/IVibratorService.aidl @@ -16,12 +16,14 @@ package android.os; +import android.os.VibrationEffect; + /** {@hide} */ interface IVibratorService { boolean hasVibrator(); - void vibrate(int uid, String opPkg, long milliseconds, int usageHint, IBinder token); - void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int usageHint, IBinder token); + boolean hasAmplitudeControl(); + void vibrate(int uid, String opPkg, in VibrationEffect effect, int usageHint, IBinder token); void cancelVibrate(IBinder token); } diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java index 19b452f323ce..b8bdc89a2f72 100644 --- a/core/java/android/os/NullVibrator.java +++ b/core/java/android/os/NullVibrator.java @@ -38,22 +38,14 @@ public class NullVibrator extends Vibrator { return false; } - /** - * @hide - */ @Override - public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) { + public boolean hasAmplitudeControl() { + return false; } - /** - * @hide - */ @Override - public void vibrate(int uid, String opPkg, long[] pattern, int repeat, - AudioAttributes attributes) { - if (repeat >= pattern.length) { - throw new ArrayIndexOutOfBoundsException(); - } + public void vibrate(int uid, String opPkg, + VibrationEffect effect, AudioAttributes attributes) { } @Override diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index c4888111d0ef..f776c17e56be 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -32,14 +32,12 @@ public class SystemVibrator extends Vibrator { private final Binder mToken = new Binder(); public SystemVibrator() { - mService = IVibratorService.Stub.asInterface( - ServiceManager.getService("vibrator")); + mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")); } public SystemVibrator(Context context) { super(context); - mService = IVibratorService.Stub.asInterface( - ServiceManager.getService("vibrator")); + mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")); } @Override @@ -55,44 +53,30 @@ public class SystemVibrator extends Vibrator { return false; } - /** - * @hide - */ @Override - public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) { + public boolean hasAmplitudeControl() { if (mService == null) { - Log.w(TAG, "Failed to vibrate; no vibrator service."); - return; + Log.w(TAG, "Failed to check amplitude control; no vibrator service."); + return false; } try { - mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken); + return mService.hasAmplitudeControl(); } catch (RemoteException e) { - Log.w(TAG, "Failed to vibrate.", e); } + return false; } - /** - * @hide - */ @Override - public void vibrate(int uid, String opPkg, long[] pattern, int repeat, - AudioAttributes attributes) { + public void vibrate(int uid, String opPkg, + VibrationEffect effect, AudioAttributes attributes) { if (mService == null) { Log.w(TAG, "Failed to vibrate; no vibrator service."); return; } - // catch this here because the server will do nothing. pattern may - // not be null, let that be checked, because the server will drop it - // anyway - if (repeat < pattern.length) { - try { - mService.vibratePattern(uid, opPkg, pattern, repeat, usageForAttributes(attributes), - mToken); - } catch (RemoteException e) { - Log.w(TAG, "Failed to vibrate.", e); - } - } else { - throw new ArrayIndexOutOfBoundsException(); + try { + mService.vibrate(uid, opPkg, effect, usageForAttributes(attributes), mToken); + } catch (RemoteException e) { + Log.w(TAG, "Failed to vibrate.", e); } } diff --git a/core/java/android/os/VibrationEffect.aidl b/core/java/android/os/VibrationEffect.aidl new file mode 100644 index 000000000000..dcc79d798c3d --- /dev/null +++ b/core/java/android/os/VibrationEffect.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2017 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 VibrationEffect; +parcelable VibrationEffect.OneShotVibration; +parcelable VibrationEffect.WaveformVibration; +parcelable VibrationEffect.EffectVibration; diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java new file mode 100644 index 000000000000..eceaa31b9cf8 --- /dev/null +++ b/core/java/android/os/VibrationEffect.java @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2017 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.hardware.vibrator.V1_0.Constants.Effect; + +import java.util.Arrays; + +/** + * A VibrationEffect describes a haptic effect to be performed by a {@link Vibrator}. + * + * These effects may be any number of things, from single shot vibrations to complex waveforms. + */ +public abstract class VibrationEffect implements Parcelable { + private static final int PARCEL_TOKEN_ONE_SHOT = 1; + private static final int PARCEL_TOKEN_WAVEFORM = 2; + private static final int PARCEL_TOKEN_EFFECT = 3; + + /** + * The default vibration strength of the device. + */ + public static final int DEFAULT_AMPLITUDE = -1; + + /** + * A click effect. + * + * @see #get(int) + * @hide + */ + public static final int EFFECT_CLICK = Effect.CLICK; + + /** + * A double click effect. + * + * @see #get(int) + * @hide + */ + public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK; + + /** @hide to prevent subclassing from outside of the framework */ + public VibrationEffect() { } + + /** + * Create a one shot vibration. + * + * One shot vibrations will vibrate constantly for the specified period of time at the + * specified amplitude, and then stop. + * + * @param milliseconds The number of milliseconds to vibrate. This must be a positive number. + * @param amplitude The strength of the vibration. This must be a value between 1 and 255, or + * {@link #DEFAULT_AMPLITUDE}. + * + * @return The desired effect. + */ + public static VibrationEffect createOneShot(long milliseconds, int amplitude) { + VibrationEffect effect = new OneShot(milliseconds, amplitude); + effect.validate(); + return effect; + } + + /** + * Create a waveform vibration. + * + * Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For + * each pair, the value in the amplitude array determines the strength of the vibration and the + * value in the timing array determines how long it vibrates for. An amplitude of 0 implies no + * vibration (i.e. off), and any pairs with a timing value of 0 will be ignored. + * <p> + * The amplitude array of the generated waveform will be the same size as the given + * timing array with alternating values of 0 (i.e. off) and {@link #DEFAULT_AMPLITUDE}, + * starting with 0. Therefore the first timing value will be the period to wait before turning + * the vibrator on, the second value will be how long to vibrate at {@link #DEFAULT_AMPLITUDE} + * strength, etc. + * </p><p> + * To cause the pattern to repeat, pass the index into the timings array at which to start the + * repetition, or -1 to disable repeating. + * </p> + * + * @param timings The pattern of alternating on-off timings, starting with off. Timing values + * of 0 will cause the timing / amplitude pair to be ignored. + * @param repeat The index into the timings array at which to repeat, or -1 if you you don't + * want to repeat. + * + * @return The desired effect. + */ + public static VibrationEffect createWaveform(long[] timings, int repeat) { + int[] amplitudes = new int[timings.length]; + for (int i = 0; i < (timings.length / 2); i++) { + amplitudes[i*2 + 1] = VibrationEffect.DEFAULT_AMPLITUDE; + } + return createWaveform(timings, amplitudes, repeat); + } + + /** + * Create a waveform vibration. + * + * Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For + * each pair, the value in the amplitude array determines the strength of the vibration and the + * value in the timing array determines how long it vibrates for. An amplitude of 0 implies no + * vibration (i.e. off), and any pairs with a timing value of 0 will be ignored. + * </p><p> + * To cause the pattern to repeat, pass the index into the timings array at which to start the + * repetition, or -1 to disable repeating. + * </p> + * + * @param timings The timing values of the timing / amplitude pairs. Timing values of 0 + * will cause the pair to be ignored. + * @param amplitudes The amplitude values of the timing / amplitude pairs. Amplitude values + * must be between 0 and 255, or equal to {@link #DEFAULT_AMPLITUDE}. An + * amplitude value of 0 implies the motor is off. + * @param repeat The index into the timings array at which to repeat, or -1 if you you don't + * want to repeat. + * + * @return The desired effect. + */ + public static VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) { + VibrationEffect effect = new Waveform(timings, amplitudes, repeat); + effect.validate(); + return effect; + } + + /** + * Get a predefined vibration effect. + * + * Predefined effects are a set of common vibration effects that should be identical, regardless + * of the app they come from, in order to provide a cohesive experience for users across + * the entire device. They also may be custom tailored to the device hardware in order to + * provide a better experience than you could otherwise build using the generic building + * blocks. + * + * @param effectId The ID of the effect to perform: + * {@link #EFFECT_CLICK}, {@link #EFFECT_DOUBLE_CLICK}. + * + * @return The desired effect. + * @hide + */ + public static VibrationEffect get(int effectId) { + VibrationEffect effect = new Prebaked(effectId); + effect.validate(); + return effect; + } + + @Override + public int describeContents() { + return 0; + } + + /** @hide */ + public abstract void validate(); + + /** @hide */ + public static class OneShot extends VibrationEffect implements Parcelable { + private long mTiming; + private int mAmplitude; + + public OneShot(Parcel in) { + this(in.readLong(), in.readInt()); + } + + public OneShot(long milliseconds, int amplitude) { + mTiming = milliseconds; + mAmplitude = amplitude; + } + + public long getTiming() { + return mTiming; + } + + public int getAmplitude() { + return mAmplitude; + } + + @Override + public void validate() { + if (mAmplitude < -1 || mAmplitude == 0 || mAmplitude > 255) { + throw new IllegalArgumentException( + "amplitude must either be DEFAULT_AMPLITUDE, " + + "or between 1 and 255 inclusive"); + } + if (mTiming <= 0) { + throw new IllegalArgumentException("timing must be positive"); + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof VibrationEffect.OneShot)) { + return false; + } + VibrationEffect.OneShot other = (VibrationEffect.OneShot) o; + return other.mTiming == mTiming && other.mAmplitude == mAmplitude; + } + + @Override + public int hashCode() { + int result = 17; + result = 37 * (int) mTiming; + result = 37 * mAmplitude; + return result; + } + + @Override + public String toString() { + return "OneShot{mTiming=" + mTiming +", mAmplitude=" + mAmplitude + "}"; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(PARCEL_TOKEN_ONE_SHOT); + out.writeLong(mTiming); + out.writeInt(mAmplitude); + } + + public static final Parcelable.Creator<OneShot> CREATOR = + new Parcelable.Creator<OneShot>() { + @Override + public OneShot createFromParcel(Parcel in) { + // Skip the type token + in.readInt(); + return new OneShot(in); + } + @Override + public OneShot[] newArray(int size) { + return new OneShot[size]; + } + }; + } + + /** @hide */ + public static class Waveform extends VibrationEffect implements Parcelable { + private long[] mTimings; + private int[] mAmplitudes; + private int mRepeat; + + public Waveform(Parcel in) { + this(in.createLongArray(), in.createIntArray(), in.readInt()); + } + + public Waveform(long[] timings, int[] amplitudes, int repeat) { + mTimings = new long[timings.length]; + System.arraycopy(timings, 0, mTimings, 0, timings.length); + mAmplitudes = new int[amplitudes.length]; + System.arraycopy(amplitudes, 0, mAmplitudes, 0, amplitudes.length); + mRepeat = repeat; + } + + public long[] getTimings() { + return mTimings; + } + + public int[] getAmplitudes() { + return mAmplitudes; + } + + public int getRepeatIndex() { + return mRepeat; + } + + @Override + public void validate() { + if (mTimings.length != mAmplitudes.length) { + throw new IllegalArgumentException( + "timing and amplitude arrays must be of equal length"); + } + if (!hasNonZeroEntry(mTimings)) { + throw new IllegalArgumentException("at least one timing must be non-zero"); + } + for (long timing : mTimings) { + if (timing < 0) { + throw new IllegalArgumentException("timings must all be >= 0"); + } + } + for (int amplitude : mAmplitudes) { + if (amplitude < -1 || amplitude > 255) { + throw new IllegalArgumentException( + "amplitudes must all be DEFAULT_AMPLITUDE or between 0 and 255"); + } + } + if (mRepeat < -1 || mRepeat >= mTimings.length) { + throw new IllegalArgumentException("repeat index must be >= -1"); + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof VibrationEffect.Waveform)) { + return false; + } + VibrationEffect.Waveform other = (VibrationEffect.Waveform) o; + return Arrays.equals(mTimings, other.mTimings) && + Arrays.equals(mAmplitudes, other.mAmplitudes) && + mRepeat == other.mRepeat; + } + + @Override + public int hashCode() { + int result = 17; + result = 37 * Arrays.hashCode(mTimings); + result = 37 * Arrays.hashCode(mAmplitudes); + result = 37 * mRepeat; + return result; + } + + @Override + public String toString() { + return "Waveform{mTimings=" + Arrays.toString(mTimings) + + ", mAmplitudes=" + Arrays.toString(mAmplitudes) + + ", mRepeat=" + mRepeat + + "}"; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(PARCEL_TOKEN_WAVEFORM); + out.writeLongArray(mTimings); + out.writeIntArray(mAmplitudes); + out.writeInt(mRepeat); + } + + private static boolean hasNonZeroEntry(long[] vals) { + for (long val : vals) { + if (val != 0) { + return true; + } + } + return false; + } + + + public static final Parcelable.Creator<Waveform> CREATOR = + new Parcelable.Creator<Waveform>() { + @Override + public Waveform createFromParcel(Parcel in) { + // Skip the type token + in.readInt(); + return new Waveform(in); + } + @Override + public Waveform[] newArray(int size) { + return new Waveform[size]; + } + }; + } + + /** @hide */ + public static class Prebaked extends VibrationEffect implements Parcelable { + private int mEffectId; + + public Prebaked(Parcel in) { + this(in.readInt()); + } + + public Prebaked(int effectId) { + mEffectId = effectId; + } + + public int getId() { + return mEffectId; + } + + @Override + public void validate() { + if (mEffectId != EFFECT_CLICK) { + throw new IllegalArgumentException("Unknown prebaked effect type"); + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof VibrationEffect.Prebaked)) { + return false; + } + VibrationEffect.Prebaked other = (VibrationEffect.Prebaked) o; + return mEffectId == other.mEffectId; + } + + @Override + public int hashCode() { + return mEffectId; + } + + @Override + public String toString() { + return "Prebaked{mEffectId=" + mEffectId + "}"; + } + + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(PARCEL_TOKEN_EFFECT); + out.writeInt(mEffectId); + } + + public static final Parcelable.Creator<Prebaked> CREATOR = + new Parcelable.Creator<Prebaked>() { + @Override + public Prebaked createFromParcel(Parcel in) { + // Skip the type token + in.readInt(); + return new Prebaked(in); + } + @Override + public Prebaked[] newArray(int size) { + return new Prebaked[size]; + } + }; + } + + public static final Parcelable.Creator<VibrationEffect> CREATOR = + new Parcelable.Creator<VibrationEffect>() { + @Override + public VibrationEffect createFromParcel(Parcel in) { + int token = in.readInt(); + if (token == PARCEL_TOKEN_ONE_SHOT) { + return new OneShot(in); + } else if (token == PARCEL_TOKEN_WAVEFORM) { + return new Waveform(in); + } else if (token == PARCEL_TOKEN_EFFECT) { + return new Prebaked(in); + } else { + throw new IllegalStateException( + "Unexpected vibration event type token in parcel."); + } + } + @Override + public VibrationEffect[] newArray(int size) { + return new VibrationEffect[size]; + } + }; +} diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index f9b7666b79f7..b1f64218b7b4 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -55,12 +55,22 @@ public abstract class Vibrator { public abstract boolean hasVibrator(); /** + * Check whether the vibrator has amplitude control. + * + * @return True if the hardware can control the amplitude of the vibrations, otherwise false. + */ + public abstract boolean hasAmplitudeControl(); + + /** * Vibrate constantly for the specified period of time. * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#VIBRATE}. * * @param milliseconds The number of milliseconds to vibrate. + * + * @deprecated Use {@link #vibrate(VibrationEffect)} instead. */ + @Deprecated public void vibrate(long milliseconds) { vibrate(milliseconds, null); } @@ -75,9 +85,14 @@ public abstract class Vibrator { * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for * vibrations associated with incoming calls. + * + * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead. */ + @Deprecated public void vibrate(long milliseconds, AudioAttributes attributes) { - vibrate(Process.myUid(), mPackageName, milliseconds, attributes); + VibrationEffect effect = + VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE); + vibrate(effect, attributes); } /** @@ -99,7 +114,10 @@ public abstract class Vibrator { * @param pattern an array of longs of times for which to turn the vibrator on or off. * @param repeat the index into pattern at which to repeat, or -1 if * you don't want to repeat. + * + * @deprecated Use {@link #vibrate(VibrationEffect)} instead. */ + @Deprecated public void vibrate(long[] pattern, int repeat) { vibrate(pattern, repeat, null); } @@ -127,26 +145,34 @@ public abstract class Vibrator { * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for * vibrations associated with incoming calls. + * + * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead. */ + @Deprecated public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) { - vibrate(Process.myUid(), mPackageName, pattern, repeat, attributes); + // This call needs to continue throwing ArrayIndexOutOfBoundsException for compatibility + // purposes, whereas VibrationEffect throws an IllegalArgumentException. + if (repeat < -1 || repeat >= pattern.length) { + throw new ArrayIndexOutOfBoundsException(); + } + vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes); } - /** - * @hide - * Like {@link #vibrate(long, AudioAttributes)}, but allowing the caller to specify that - * the vibration is owned by someone else. - */ - public abstract void vibrate(int uid, String opPkg, long milliseconds, - AudioAttributes attributes); + public void vibrate(VibrationEffect vibe) { + vibrate(vibe, null); + } + + public void vibrate(VibrationEffect vibe, AudioAttributes attributes) { + vibrate(Process.myUid(), mPackageName, vibe, attributes); + } /** + * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allowing the caller to specify + * that the vibration is owned by someone else. * @hide - * Like {@link #vibrate(long[], int, AudioAttributes)}, but allowing the caller to specify that - * the vibration is owned by someone else. */ - public abstract void vibrate(int uid, String opPkg, long[] pattern, int repeat, - AudioAttributes attributes); + public abstract void vibrate(int uid, String opPkg, + VibrationEffect vibe, AudioAttributes attributes); /** * Turn the vibrator off. |
