• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os;
18 
19 import android.annotation.CallbackExecutor;
20 import android.annotation.FloatRange;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SystemApi;
26 import android.annotation.SystemService;
27 import android.app.ActivityThread;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.content.Context;
30 import android.hardware.vibrator.IVibrator;
31 import android.media.AudioAttributes;
32 import android.util.Log;
33 import android.util.Range;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.concurrent.Executor;
38 
39 /**
40  * Class that operates the vibrator on the device.
41  * <p>
42  * If your process exits, any vibration you started will stop.
43  * </p>
44  */
45 @SystemService(Context.VIBRATOR_SERVICE)
46 public abstract class Vibrator {
47     private static final String TAG = "Vibrator";
48 
49     /**
50      * Vibration intensity: no vibrations.
51      *
52      * @hide
53      */
54     public static final int VIBRATION_INTENSITY_OFF = 0;
55 
56     /**
57      * Vibration intensity: low.
58      *
59      * @hide
60      */
61     public static final int VIBRATION_INTENSITY_LOW = 1;
62 
63     /**
64      * Vibration intensity: medium.
65      *
66      * @hide
67      */
68     public static final int VIBRATION_INTENSITY_MEDIUM = 2;
69 
70     /**
71      * Vibration intensity: high.
72      *
73      * @hide
74      */
75     public static final int VIBRATION_INTENSITY_HIGH = 3;
76 
77     /**
78      * Vibration effect support: unknown
79      *
80      * The hardware doesn't report it's supported effects, so we can't determine whether the
81      * effect is supported or not.
82      */
83     public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0;
84 
85     /**
86      * Vibration effect support: supported
87      *
88      * This effect is supported by the underlying hardware.
89      */
90     public static final int VIBRATION_EFFECT_SUPPORT_YES = 1;
91 
92     /**
93      * Vibration effect support: unsupported
94      *
95      * This effect is <b>not</b> supported by the underlying hardware.
96      */
97     public static final int VIBRATION_EFFECT_SUPPORT_NO = 2;
98 
99     /** @hide */
100     @Retention(RetentionPolicy.SOURCE)
101     @IntDef(prefix = {"VIBRATION_EFFECT_SUPPORT_"}, value = {
102             VIBRATION_EFFECT_SUPPORT_UNKNOWN,
103             VIBRATION_EFFECT_SUPPORT_YES,
104             VIBRATION_EFFECT_SUPPORT_NO,
105     })
106     public @interface VibrationEffectSupport {}
107 
108     /** @hide */
109     @Retention(RetentionPolicy.SOURCE)
110     @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = {
111             VIBRATION_INTENSITY_OFF,
112             VIBRATION_INTENSITY_LOW,
113             VIBRATION_INTENSITY_MEDIUM,
114             VIBRATION_INTENSITY_HIGH
115     })
116     public @interface VibrationIntensity {
117     }
118 
119     private final String mPackageName;
120     // The default vibration intensity level for haptic feedback.
121     @VibrationIntensity
122     private int mDefaultHapticFeedbackIntensity;
123     // The default vibration intensity level for notifications.
124     @VibrationIntensity
125     private int mDefaultNotificationVibrationIntensity;
126     // The default vibration intensity level for ringtones.
127     @VibrationIntensity
128     private int mDefaultRingVibrationIntensity;
129     private float mHapticChannelMaxVibrationAmplitude;
130 
131     /**
132      * @hide to prevent subclassing from outside of the framework
133      */
134     @UnsupportedAppUsage
Vibrator()135     public Vibrator() {
136         mPackageName = ActivityThread.currentPackageName();
137         final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
138         loadVibrationConfig(ctx);
139     }
140 
141     /**
142      * @hide to prevent subclassing from outside of the framework
143      */
Vibrator(Context context)144     protected Vibrator(Context context) {
145         mPackageName = context.getOpPackageName();
146         loadVibrationConfig(context);
147     }
148 
loadVibrationConfig(Context context)149     private void loadVibrationConfig(Context context) {
150         mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
151                 com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
152         mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
153                 com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
154         mDefaultRingVibrationIntensity = loadDefaultIntensity(context,
155                 com.android.internal.R.integer.config_defaultRingVibrationIntensity);
156         mHapticChannelMaxVibrationAmplitude = loadFloat(context,
157                 com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
158     }
159 
loadDefaultIntensity(Context ctx, int resId)160     private int loadDefaultIntensity(Context ctx, int resId) {
161         return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
162     }
163 
loadFloat(Context ctx, int resId, float defaultValue)164     private float loadFloat(Context ctx, int resId, float defaultValue) {
165         return ctx != null ? ctx.getResources().getFloat(resId) : defaultValue;
166     }
167 
168     /** @hide */
getInfo()169     protected VibratorInfo getInfo() {
170         return VibratorInfo.EMPTY_VIBRATOR_INFO;
171     }
172 
173     /**
174      * Get the default vibration intensity for haptic feedback.
175      *
176      * @hide
177      */
getDefaultHapticFeedbackIntensity()178     public int getDefaultHapticFeedbackIntensity() {
179         return mDefaultHapticFeedbackIntensity;
180     }
181 
182     /**
183      * Get the default vibration intensity for notifications.
184      *
185      * @hide
186      */
getDefaultNotificationVibrationIntensity()187     public int getDefaultNotificationVibrationIntensity() {
188         return mDefaultNotificationVibrationIntensity;
189     }
190 
191     /**
192      * Get the default vibration intensity for ringtones.
193      *
194      * @hide
195      */
getDefaultRingVibrationIntensity()196     public int getDefaultRingVibrationIntensity() {
197         return mDefaultRingVibrationIntensity;
198     }
199 
200     /**
201      * Return the ID of this vibrator.
202      *
203      * @return A non-negative integer representing the id of the vibrator controlled by this
204      * service, or -1 this service is not attached to any physical vibrator.
205      */
getId()206     public int getId() {
207         return getInfo().getId();
208     }
209 
210     /**
211      * Check whether the hardware has a vibrator.
212      *
213      * @return True if the hardware has a vibrator, else false.
214      */
hasVibrator()215     public abstract boolean hasVibrator();
216 
217     /**
218      * Check whether the vibrator has amplitude control.
219      *
220      * @return True if the hardware can control the amplitude of the vibrations, otherwise false.
221      */
hasAmplitudeControl()222     public abstract boolean hasAmplitudeControl();
223 
224     /**
225      * Check whether the vibrator has independent frequency control.
226      *
227      * @return True if the hardware can control the frequency of the vibrations, otherwise false.
228      * @hide
229      */
hasFrequencyControl()230     public boolean hasFrequencyControl() {
231         // We currently can only control frequency of the vibration using the compose PWLE method.
232         return getInfo().hasCapability(
233                 IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
234     }
235 
236     /**
237      * Check whether the vibrator can be controlled by an external service with the
238      * {@link IExternalVibratorService}.
239      *
240      * @return True if the hardware can be controlled by an external service, otherwise false.
241      * @hide
242      */
hasExternalControl()243     public boolean hasExternalControl() {
244         return getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL);
245     }
246 
247     /**
248      * Gets the resonant frequency of the vibrator.
249      *
250      * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown or
251      * this vibrator is a composite of multiple physical devices.
252      * @hide
253      */
getResonantFrequency()254     public float getResonantFrequency() {
255         return getInfo().getResonantFrequency();
256     }
257 
258     /**
259      * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator.
260      *
261      * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown or
262      *         this vibrator is a composite of multiple physical devices.
263      * @hide
264      */
getQFactor()265     public float getQFactor() {
266         return getInfo().getQFactor();
267     }
268 
269     /**
270      * Return a range of relative frequency values supported by the vibrator.
271      *
272      * <p>These values can be used to create waveforms that controls the vibration frequency via
273      * {@link VibrationEffect.WaveformBuilder}.
274      *
275      * @return A range of relative frequency values supported. The range will always contain the
276      * value 0, representing the device resonant frequency. Devices without frequency control will
277      * return the range [0,0]. Devices with frequency control will always return a range containing
278      * the safe range [-1, 1].
279      * @hide
280      */
getRelativeFrequencyRange()281     public Range<Float> getRelativeFrequencyRange() {
282         return getInfo().getFrequencyRange();
283     }
284 
285     /**
286      * Return the maximum amplitude the vibrator can play at given relative frequency.
287      *
288      * <p>Devices without frequency control will return 1 for the input zero (resonant frequency),
289      * and 0 to any other input.
290      *
291      * <p>Devices with frequency control will return the supported value, for input in
292      * {@link #getRelativeFrequencyRange()}, and 0 for any other input.
293      *
294      * <p>These values can be used to create waveforms that plays vibrations outside the resonant
295      * frequency via {@link VibrationEffect.WaveformBuilder}.
296      *
297      * @return a value in [0,1] representing the maximum amplitude the device can play at given
298      * relative frequency.
299      * @hide
300      */
301     @FloatRange(from = 0, to = 1)
getMaximumAmplitude(float relativeFrequency)302     public float getMaximumAmplitude(float relativeFrequency) {
303         return getInfo().getMaxAmplitude(relativeFrequency);
304     }
305 
306     /**
307      * Return the maximum amplitude the vibrator can play using the audio haptic channels.
308      *
309      * <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a
310      * positive value <code>maxAmplitude</code>, then the signals from the haptic channels of audio
311      * tracks should be in the range <code>[-maxAmplitude, maxAmplitude]</code>.
312      *
313      * @return a positive value representing the maximum absolute value the device can play signals
314      * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown.
315      * @hide
316      */
getHapticChannelMaximumAmplitude()317     public float getHapticChannelMaximumAmplitude() {
318         if (mHapticChannelMaxVibrationAmplitude <= 0) {
319             return Float.NaN;
320         }
321         return mHapticChannelMaxVibrationAmplitude;
322     }
323 
324     /**
325      * Configure an always-on haptics effect.
326      *
327      * @param alwaysOnId The board-specific always-on ID to configure.
328      * @param effect     Vibration effect to assign to always-on id. Passing null will disable it.
329      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
330      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
331      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
332      *                   vibrations associated with incoming calls. May only be null when effect is
333      *                   null.
334      * @hide
335      */
336     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes)337     public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect,
338             @Nullable AudioAttributes attributes) {
339         return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes);
340     }
341 
342     /**
343      * @hide
344      */
345     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes)346     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
347             @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) {
348         Log.w(TAG, "Always-on effects aren't supported");
349         return false;
350     }
351 
352     /**
353      * Vibrate constantly for the specified period of time.
354      *
355      * @param milliseconds The number of milliseconds to vibrate.
356      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
357      */
358     @Deprecated
359     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long milliseconds)360     public void vibrate(long milliseconds) {
361         vibrate(milliseconds, null);
362     }
363 
364     /**
365      * Vibrate constantly for the specified period of time.
366      *
367      * @param milliseconds The number of milliseconds to vibrate.
368      * @param attributes   {@link AudioAttributes} corresponding to the vibration. For example,
369      *                     specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
370      *                     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
371      *                     vibrations associated with incoming calls.
372      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
373      */
374     @Deprecated
375     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long milliseconds, AudioAttributes attributes)376     public void vibrate(long milliseconds, AudioAttributes attributes) {
377         try {
378             // This ignores all exceptions to stay compatible with pre-O implementations.
379             VibrationEffect effect =
380                     VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
381             vibrate(effect, attributes);
382         } catch (IllegalArgumentException iae) {
383             Log.e(TAG, "Failed to create VibrationEffect", iae);
384         }
385     }
386 
387     /**
388      * Vibrate with a given pattern.
389      *
390      * <p>
391      * Pass in an array of ints that are the durations for which to turn on or off
392      * the vibrator in milliseconds.  The first value indicates the number of milliseconds
393      * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
394      * for which to keep the vibrator on before turning it off.  Subsequent values alternate
395      * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
396      * </p><p>
397      * To cause the pattern to repeat, pass the index into the pattern array at which
398      * to start the repeat, or -1 to disable repeating.
399      * </p>
400      *
401      * @param pattern an array of longs of times for which to turn the vibrator on or off.
402      * @param repeat  the index into pattern at which to repeat, or -1 if
403      *                you don't want to repeat.
404      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
405      */
406     @Deprecated
407     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long[] pattern, int repeat)408     public void vibrate(long[] pattern, int repeat) {
409         vibrate(pattern, repeat, null);
410     }
411 
412     /**
413      * Vibrate with a given pattern.
414      *
415      * <p>
416      * Pass in an array of ints that are the durations for which to turn on or off
417      * the vibrator in milliseconds.  The first value indicates the number of milliseconds
418      * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
419      * for which to keep the vibrator on before turning it off.  Subsequent values alternate
420      * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
421      * </p><p>
422      * To cause the pattern to repeat, pass the index into the pattern array at which
423      * to start the repeat, or -1 to disable repeating.
424      * </p>
425      *
426      * @param pattern    an array of longs of times for which to turn the vibrator on or off.
427      * @param repeat     the index into pattern at which to repeat, or -1 if
428      *                   you don't want to repeat.
429      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
430      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
431      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
432      *                   vibrations associated with incoming calls.
433      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
434      */
435     @Deprecated
436     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long[] pattern, int repeat, AudioAttributes attributes)437     public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
438         // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other
439         // exceptions for compatibility purposes
440         if (repeat < -1 || repeat >= pattern.length) {
441             Log.e(TAG, "vibrate called with repeat index out of bounds" +
442                     " (pattern.length=" + pattern.length + ", index=" + repeat + ")");
443             throw new ArrayIndexOutOfBoundsException();
444         }
445 
446         try {
447             vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes);
448         } catch (IllegalArgumentException iae) {
449             Log.e(TAG, "Failed to create VibrationEffect", iae);
450         }
451     }
452 
453     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(VibrationEffect vibe)454     public void vibrate(VibrationEffect vibe) {
455         vibrate(vibe, null);
456     }
457 
458     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(VibrationEffect vibe, AudioAttributes attributes)459     public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
460         vibrate(Process.myUid(), mPackageName, vibe, null, attributes);
461     }
462 
463     /**
464      * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allows the
465      * caller to specify the vibration is owned by someone else and set reason for vibration.
466      *
467      * @hide
468      */
469     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(int uid, String opPkg, VibrationEffect vibe, String reason, AudioAttributes attributes)470     public final void vibrate(int uid, String opPkg, VibrationEffect vibe,
471             String reason, AudioAttributes attributes) {
472         if (attributes == null) {
473             attributes = new AudioAttributes.Builder().build();
474         }
475         VibrationAttributes attr = new VibrationAttributes.Builder(attributes, vibe).build();
476         vibrate(uid, opPkg, vibe, reason, attr);
477     }
478 
479     /**
480      * Like {@link #vibrate(int, String, VibrationEffect, String, AudioAttributes)}, but allows the
481      * caller to specify {@link VibrationAttributes} instead of {@link AudioAttributes}.
482      *
483      * @hide
484      */
485     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, String reason, @NonNull VibrationAttributes attributes)486     public abstract void vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe,
487             String reason, @NonNull VibrationAttributes attributes);
488 
489     /**
490      * Query whether the vibrator supports the given effects.
491      *
492      * Not all hardware reports its effect capabilities, so the system may not necessarily know
493      * whether an effect is supported or not.
494      *
495      * The returned array will be the same length as the query array and the value at a given index
496      * will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index in the
497      * querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or
498      * {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's
499      * supported or not.
500      *
501      * @param effectIds Which effects to query for.
502      * @return An array containing the systems current knowledge about whether the given effects
503      * are supported or not.
504      */
505     @NonNull
506     @VibrationEffectSupport
areEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)507     public int[] areEffectsSupported(
508             @NonNull @VibrationEffect.EffectType int... effectIds) {
509         VibratorInfo info = getInfo();
510         int[] supported = new int[effectIds.length];
511         for (int i = 0; i < effectIds.length; i++) {
512             supported[i] = info.isEffectSupported(effectIds[i]);
513         }
514         return supported;
515     }
516 
517     /**
518      * Query whether the vibrator supports all of the given effects.
519      *
520      * Not all hardware reports its effect capabilities, so the system may not necessarily know
521      * whether an effect is supported or not.
522      *
523      * If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are
524      * supported by the hardware.
525      *
526      * If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the
527      * query is not supported.
528      *
529      * If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know whether
530      * all of the effects are supported. It may support any or all of the queried effects,
531      * but there's no way to programmatically know whether a {@link #vibrate} call will successfully
532      * cause a vibration. It's guaranteed, however, that none of the queried effects are
533      * definitively unsupported by the hardware.
534      *
535      * @param effectIds Which effects to query for.
536      * @return Whether all of the effects are supported.
537      */
538     @VibrationEffectSupport
areAllEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)539     public final int areAllEffectsSupported(
540             @NonNull @VibrationEffect.EffectType int... effectIds) {
541         int support = VIBRATION_EFFECT_SUPPORT_YES;
542         for (int supported : areEffectsSupported(effectIds)) {
543             if (supported == VIBRATION_EFFECT_SUPPORT_NO) {
544                 return VIBRATION_EFFECT_SUPPORT_NO;
545             } else if (supported == VIBRATION_EFFECT_SUPPORT_UNKNOWN) {
546                 support = VIBRATION_EFFECT_SUPPORT_UNKNOWN;
547             }
548         }
549         return support;
550     }
551 
552 
553     /**
554      * Query whether the vibrator supports the given primitives.
555      *
556      * The returned array will be the same length as the query array and the value at a given index
557      * will contain whether the effect at that same index in the querying array is supported or
558      * not.
559      *
560      * @param primitiveIds Which primitives to query for.
561      * @return Whether the primitives are supported.
562      */
563     @NonNull
arePrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)564     public boolean[] arePrimitivesSupported(
565             @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
566         VibratorInfo info = getInfo();
567         boolean[] supported = new boolean[primitiveIds.length];
568         for (int i = 0; i < primitiveIds.length; i++) {
569             supported[i] = info.isPrimitiveSupported(primitiveIds[i]);
570         }
571         return supported;
572     }
573 
574     /**
575      * Query whether the vibrator supports all of the given primitives.
576      *
577      * @param primitiveIds Which primitives to query for.
578      * @return Whether primitives effects are supported.
579      */
areAllPrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)580     public final boolean areAllPrimitivesSupported(
581             @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
582         for (boolean supported : arePrimitivesSupported(primitiveIds)) {
583             if (!supported) {
584                 return false;
585             }
586         }
587         return true;
588     }
589 
590     /**
591      * Query the estimated durations of the given primitives.
592      *
593      * <p>The returned array will be the same length as the query array and the value at a given
594      * index will contain the duration in milliseconds of the effect at the same index in the
595      * querying array.
596      *
597      * <p>The duration will be positive for primitives that are supported and zero for the
598      * unsupported ones, in correspondence with {@link #arePrimitivesSupported(int...)}.
599      *
600      * @param primitiveIds Which primitives to query for.
601      * @return The duration of each primitive, with zeroes for primitives that are not supported.
602      */
603     @NonNull
getPrimitiveDurations( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)604     public int[] getPrimitiveDurations(
605             @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
606         VibratorInfo info = getInfo();
607         int[] durations = new int[primitiveIds.length];
608         for (int i = 0; i < primitiveIds.length; i++) {
609             durations[i] = info.getPrimitiveDuration(primitiveIds[i]);
610         }
611         return durations;
612     }
613 
614     /**
615      * Turn the vibrator off.
616      */
617     @RequiresPermission(android.Manifest.permission.VIBRATE)
cancel()618     public abstract void cancel();
619 
620     /**
621      * Cancel specific types of ongoing vibrations.
622      *
623      * @param usageFilter The type of vibration to be cancelled, represented as a bitwise
624      *                    combination of {@link VibrationAttributes.Usage} values.
625      * @hide
626      */
627     @RequiresPermission(android.Manifest.permission.VIBRATE)
cancel(int usageFilter)628     public abstract void cancel(int usageFilter);
629 
630     /**
631      * Check whether the vibrator is vibrating.
632      *
633      * @return True if the hardware is vibrating, otherwise false.
634      * @hide
635      */
636     @SystemApi
637     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
isVibrating()638     public boolean isVibrating() {
639         return false;
640     }
641 
642     /**
643     * Listener for when the vibrator state has changed.
644     *
645     * @see #addVibratorStateListener
646     * @see #removeVibratorStateListener
647     * @hide
648     */
649     @SystemApi
650     public interface OnVibratorStateChangedListener  {
651         /**
652          * Called when the vibrator state has changed.
653          *
654          * @param isVibrating If true, the vibrator has started vibrating. If false,
655          *                    it's stopped vibrating.
656          */
onVibratorStateChanged(boolean isVibrating)657         void onVibratorStateChanged(boolean isVibrating);
658     }
659 
660     /**
661      * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread.
662      * If the listener was previously added and not removed, this call will be ignored.
663      *
664      * @param listener listener to be added
665      * @hide
666      */
667     @SystemApi
668     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
addVibratorStateListener(@onNull OnVibratorStateChangedListener listener)669     public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
670     }
671 
672     /**
673      * Adds a listener for vibrator state change. If the listener was previously added and not
674      * removed, this call will be ignored.
675      *
676      * @param listener listener to be added
677      * @param executor executor of listener
678      * @hide
679      */
680     @SystemApi
681     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
addVibratorStateListener( @onNull @allbackExecutor Executor executor, @NonNull OnVibratorStateChangedListener listener)682     public void addVibratorStateListener(
683             @NonNull @CallbackExecutor Executor executor,
684             @NonNull OnVibratorStateChangedListener listener) {
685     }
686 
687     /**
688      * Removes the listener for vibrator state changes. If the listener was not previously
689      * registered, this call will do nothing.
690      *
691      * @param listener listener to be removed
692      * @hide
693      */
694     @SystemApi
695     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
removeVibratorStateListener(@onNull OnVibratorStateChangedListener listener)696     public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
697     }
698 }
699