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