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     public 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      * Whether the keyboard vibration is enabled by default.
188      *
189      * @return {@code true} if the keyboard vibration is default enabled, {@code false} otherwise.
190      * @hide
191      */
isDefaultKeyboardVibrationEnabled()192     public boolean isDefaultKeyboardVibrationEnabled() {
193         return getConfig().isDefaultKeyboardVibrationEnabled();
194     }
195 
196     /**
197      * Return the ID of this vibrator.
198      *
199      * @return A non-negative integer representing the id of the vibrator controlled by this
200      * service, or -1 this service is not attached to any physical vibrator.
201      */
getId()202     public int getId() {
203         return getInfo().getId();
204     }
205 
206     /**
207      * Check whether the hardware has a vibrator.
208      *
209      * @return True if the hardware has a vibrator, else false.
210      */
hasVibrator()211     public abstract boolean hasVibrator();
212 
213     /**
214      * Check whether the vibrator has amplitude control.
215      *
216      * @return True if the hardware can control the amplitude of the vibrations, otherwise false.
217      */
hasAmplitudeControl()218     public abstract boolean hasAmplitudeControl();
219 
220     /**
221      * Check whether the vibrator has independent frequency control.
222      *
223      * @return True if the hardware can control the frequency of the vibrations independently of
224      * the vibration amplitude, false otherwise.
225      * @hide
226      */
227     @TestApi
hasFrequencyControl()228     public boolean hasFrequencyControl() {
229         return getInfo().hasFrequencyControl();
230     }
231 
232     /**
233      * Checks whether or not the vibrator supports all components of a given {@link VibrationEffect}
234      * (i.e. the vibrator can play the given effect as intended).
235      *
236      * <p>If this method returns {@code true}, then the VibrationEffect should play as expected.
237      * If {@code false}, playing the VibrationEffect might still make a vibration, but the vibration
238      * may be significantly degraded from the intention.
239      *
240      * <p>This method aggregates the results of feature check methods such as
241      * {@link #hasAmplitudeControl}, {@link #areAllPrimitivesSupported(int...)}, etc, depending
242      * on the features that are actually used by the VibrationEffect.
243      *
244      * @param effect the {@link VibrationEffect} to check if it is supported
245      * @return {@code true} if the vibrator can play the given {@code effect} as intended,
246      *         {@code false} otherwise.
247      *
248      * @hide
249      */
areVibrationFeaturesSupported(@onNull VibrationEffect effect)250     public boolean areVibrationFeaturesSupported(@NonNull VibrationEffect effect) {
251         return getInfo().areVibrationFeaturesSupported(effect);
252     }
253 
254     /**
255      * Check whether the vibrator can be controlled by an external service with the
256      * {@link IExternalVibratorService}.
257      *
258      * @return True if the hardware can be controlled by an external service, otherwise false.
259      * @hide
260      */
hasExternalControl()261     public boolean hasExternalControl() {
262         return getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL);
263     }
264 
265     /**
266      * Gets the resonant frequency of the vibrator, if applicable.
267      *
268      * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown, not
269      * applicable, or if this vibrator is a composite of multiple physical devices with different
270      * frequencies.
271      */
getResonantFrequency()272     public float getResonantFrequency() {
273         return getInfo().getResonantFrequencyHz();
274     }
275 
276     /**
277      * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator.
278      *
279      * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown, not
280      * applicable, or if this vibrator is a composite of multiple physical devices with different
281      * Q factors.
282      */
getQFactor()283     public float getQFactor() {
284         return getInfo().getQFactor();
285     }
286 
287     /**
288      * Gets the profile that describes the vibrator output across the supported frequency range.
289      *
290      * <p>The profile describes the relative output acceleration that the device can reach when it
291      * vibrates at different frequencies.
292      *
293      * @return The frequency profile for this vibrator, or null if the vibrator does not have
294      * frequency control. If this vibrator is a composite of multiple physical devices then this
295      * will return a profile supported in all devices, or null if the intersection is empty or not
296      * available.
297      * @hide
298      */
299     @TestApi
300     @Nullable
getFrequencyProfile()301     public VibratorFrequencyProfile getFrequencyProfile() {
302         VibratorInfo.FrequencyProfile frequencyProfile = getInfo().getFrequencyProfile();
303         if (frequencyProfile.isEmpty()) {
304             return null;
305         }
306         return new VibratorFrequencyProfile(frequencyProfile);
307     }
308 
309     /**
310      * Return the maximum amplitude the vibrator can play using the audio haptic channels.
311      *
312      * <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a
313      * positive value <code>maxAmplitude</code>, then the signals from the haptic channels of audio
314      * tracks should be in the range <code>[-maxAmplitude, maxAmplitude]</code>.
315      *
316      * @return a positive value representing the maximum absolute value the device can play signals
317      * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown.
318      * @hide
319      */
getHapticChannelMaximumAmplitude()320     public float getHapticChannelMaximumAmplitude() {
321         return getConfig().getHapticChannelMaximumAmplitude();
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 VibrationAttributes} corresponding to the vibration. For example,
330      *                   specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or
331      *                   {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with
332      *                   incoming calls. May only be null when effect is null.
333      * @hide
334      */
335     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes)336     public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect,
337             @Nullable VibrationAttributes attributes) {
338         return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes);
339     }
340 
341     /**
342      * @hide
343      */
344     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes)345     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
346             @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes) {
347         Log.w(TAG, "Always-on effects aren't supported");
348         return false;
349     }
350 
351     /**
352      * Vibrate constantly for the specified period of time.
353      *
354      * <p>The app should be in the foreground for the vibration to happen.</p>
355      *
356      * @param milliseconds The number of milliseconds to vibrate.
357      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
358      */
359     @Deprecated
360     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long milliseconds)361     public void vibrate(long milliseconds) {
362         vibrate(milliseconds, null);
363     }
364 
365     /**
366      * Vibrate constantly for the specified period of time.
367      *
368      * <p>The app should be in the foreground for the vibration to happen. Background apps should
369      * specify a ringtone, notification or alarm usage in order to vibrate.</p>
370      *
371      * @param milliseconds The number of milliseconds to vibrate.
372      * @param attributes   {@link AudioAttributes} corresponding to the vibration. For example,
373      *                     specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
374      *                     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
375      *                     vibrations associated with incoming calls.
376      * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead.
377      */
378     @Deprecated
379     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long milliseconds, AudioAttributes attributes)380     public void vibrate(long milliseconds, AudioAttributes attributes) {
381         try {
382             // This ignores all exceptions to stay compatible with pre-O implementations.
383             VibrationEffect effect =
384                     VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
385             vibrate(effect, attributes);
386         } catch (IllegalArgumentException iae) {
387             Log.e(TAG, "Failed to create VibrationEffect", iae);
388         }
389     }
390 
391     /**
392      * Vibrate with a given pattern.
393      *
394      * <p>
395      * Pass in an array of ints that are the durations for which to turn on or off
396      * the vibrator in milliseconds.  The first value indicates the number of milliseconds
397      * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
398      * for which to keep the vibrator on before turning it off.  Subsequent values alternate
399      * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
400      * </p><p>
401      * To cause the pattern to repeat, pass the index into the pattern array at which
402      * to start the repeat, or -1 to disable repeating.
403      * </p>
404      *
405      * <p>The app should be in the foreground for the vibration to happen.</p>
406      *
407      * @param pattern an array of longs of times for which to turn the vibrator on or off.
408      * @param repeat  the index into pattern at which to repeat, or -1 if
409      *                you don't want to repeat.
410      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
411      */
412     @Deprecated
413     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long[] pattern, int repeat)414     public void vibrate(long[] pattern, int repeat) {
415         vibrate(pattern, repeat, null);
416     }
417 
418     /**
419      * Vibrate with a given pattern.
420      *
421      * <p>
422      * Pass in an array of ints that are the durations for which to turn on or off
423      * the vibrator in milliseconds.  The first value indicates the number of milliseconds
424      * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
425      * for which to keep the vibrator on before turning it off.  Subsequent values alternate
426      * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
427      * </p><p>
428      * To cause the pattern to repeat, pass the index into the pattern array at which
429      * to start the repeat, or -1 to disable repeating.
430      * </p>
431      *
432      * <p>The app should be in the foreground for the vibration to happen. Background apps should
433      * specify a ringtone, notification or alarm usage in order to vibrate.</p>
434      *
435      * @param pattern    an array of longs of times for which to turn the vibrator on or off.
436      * @param repeat     the index into pattern at which to repeat, or -1 if
437      *                   you don't want to repeat.
438      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
439      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
440      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
441      *                   vibrations associated with incoming calls.
442      * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead.
443      */
444     @Deprecated
445     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long[] pattern, int repeat, AudioAttributes attributes)446     public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
447         // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other
448         // exceptions for compatibility purposes
449         if (repeat < -1 || repeat >= pattern.length) {
450             Log.e(TAG, "vibrate called with repeat index out of bounds" +
451                     " (pattern.length=" + pattern.length + ", index=" + repeat + ")");
452             throw new ArrayIndexOutOfBoundsException();
453         }
454 
455         try {
456             vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes);
457         } catch (IllegalArgumentException iae) {
458             Log.e(TAG, "Failed to create VibrationEffect", iae);
459         }
460     }
461 
462     /**
463      * Vibrate with a given effect.
464      *
465      * <p>The app should be in the foreground for the vibration to happen.</p>
466      *
467      * @param vibe {@link VibrationEffect} describing the vibration to be performed.
468      */
469     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(VibrationEffect vibe)470     public void vibrate(VibrationEffect vibe) {
471         vibrate(vibe, new VibrationAttributes.Builder().build());
472     }
473 
474     /**
475      * Vibrate with a given effect.
476      *
477      * <p>The app should be in the foreground for the vibration to happen. Background apps should
478      * specify a ringtone, notification or alarm usage in order to vibrate.</p>
479      *
480      * @param vibe       {@link VibrationEffect} describing the vibration to be performed.
481      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
482      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
483      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
484      *                   vibrations associated with incoming calls.
485      * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead.
486      */
487     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(VibrationEffect vibe, AudioAttributes attributes)488     public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
489         vibrate(vibe,
490                 attributes == null
491                         ? new VibrationAttributes.Builder().build()
492                         : new VibrationAttributes.Builder(attributes).build());
493     }
494 
495     /**
496      * Vibrate with a given effect.
497      *
498      * <p>The app should be in the foreground for the vibration to happen. Background apps should
499      * specify a ringtone, notification or alarm usage in order to vibrate.</p>
500      *
501      * @param vibe       {@link VibrationEffect} describing the vibration to be performed.
502      * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example,
503      *                   specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or
504      *                   {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with
505      *                   incoming calls.
506      */
507     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(@onNull VibrationEffect vibe, @NonNull VibrationAttributes attributes)508     public void vibrate(@NonNull VibrationEffect vibe, @NonNull VibrationAttributes attributes) {
509         vibrate(Process.myUid(), mPackageName, vibe, null, attributes);
510     }
511 
512     /**
513      * Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
514      * caller to specify the vibration is owned by someone else and set a reason for vibration.
515      *
516      * @hide
517      */
518     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, String reason, @NonNull VibrationAttributes attributes)519     public abstract void vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe,
520             String reason, @NonNull VibrationAttributes attributes);
521 
522     /**
523      * Performs a haptic feedback.
524      *
525      * <p>A haptic feedback is a short vibration feedback. The type of feedback is identified via
526      * the {@code constant}, which should be one of the effect constants provided in
527      * {@link HapticFeedbackConstants}. The haptic feedback provided for a given effect ID is
528      * consistent across all usages on the same device.
529      *
530      * @param constant the ID for the haptic feedback. This should be one of the constants defined
531      *          in {@link HapticFeedbackConstants}.
532      * @param always {@code true} if the haptic feedback should be played regardless of the user
533      *          vibration intensity settings applicable to the corresponding vibration.
534      *          {@code false} if the vibration for the haptic feedback should respect the applicable
535      *          vibration intensity settings.
536      * @param reason the reason for this haptic feedback.
537      * @param fromIme the haptic feedback is performed from an IME.
538      *
539      * @hide
540      */
performHapticFeedback(int constant, boolean always, String reason, boolean fromIme)541     public void performHapticFeedback(int constant, boolean always, String reason,
542             boolean fromIme) {
543         Log.w(TAG, "performHapticFeedback is not supported");
544     }
545 
546     /**
547      * Query whether the vibrator natively supports the given effects.
548      *
549      * <p>If an effect is not supported, the system may still automatically fall back to playing
550      * a simpler vibration instead, which is not optimised for the specific device. This includes
551      * the unknown case, which can't be determined in advance, that will dynamically attempt to
552      * fall back if the optimised effect fails to play.
553      *
554      * <p>The returned array will be the same length as the query array and the value at a given
555      * index will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index
556      * in the querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't
557      * supported, or {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether
558      * it's supported or not, as some hardware doesn't report its effect capabilities.
559      *
560      * <p>Use {@link #areAllEffectsSupported(int...)} to get a single combined result,
561      * or for convenience when querying exactly one effect.
562      *
563      * @param effectIds Which effects to query for.
564      * @return An array containing the systems current knowledge about whether the given effects
565      * are natively supported by the device, or not.
566      */
567     @NonNull
568     @VibrationEffectSupport
areEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)569     public int[] areEffectsSupported(
570             @NonNull @VibrationEffect.EffectType int... effectIds) {
571         VibratorInfo info = getInfo();
572         int[] supported = new int[effectIds.length];
573         for (int i = 0; i < effectIds.length; i++) {
574             supported[i] = info.isEffectSupported(effectIds[i]);
575         }
576         return supported;
577     }
578 
579     /**
580      * Query whether the vibrator supports all the given effects. If no argument is provided this
581      * method will always return {@link #VIBRATION_EFFECT_SUPPORT_YES}.
582      *
583      * <p>If an effect is not supported, the system may still automatically fall back to a simpler
584      * vibration instead, which is not optimised for the specific device, however vibration isn't
585      * guaranteed in this case.
586      *
587      * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are
588      * supported by the hardware.
589      *
590      * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the
591      * query is not supported, and using them may fall back to an un-optimized vibration or no
592      * vibration.
593      *
594      * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know
595      * whether all the effects are supported. It may support any or all of the queried effects,
596      * but there's no way to programmatically know whether a {@link #vibrate} call will successfully
597      * cause a vibration. It's guaranteed, however, that none of the queried effects are
598      * definitively unsupported by the hardware.
599      *
600      * <p>Use {@link #areEffectsSupported(int...)} to get individual results for each effect.
601      *
602      * @param effectIds Which effects to query for.
603      * @return Whether all specified effects are natively supported by the device. Empty query
604      * defaults to {@link #VIBRATION_EFFECT_SUPPORT_YES}.
605      */
606     @VibrationEffectSupport
areAllEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)607     public final int areAllEffectsSupported(
608             @NonNull @VibrationEffect.EffectType int... effectIds) {
609         VibratorInfo info = getInfo();
610         int allSupported = VIBRATION_EFFECT_SUPPORT_YES;
611         for (int effectId : effectIds) {
612             switch (info.isEffectSupported(effectId)) {
613                 case VIBRATION_EFFECT_SUPPORT_NO:
614                     return VIBRATION_EFFECT_SUPPORT_NO;
615                 case VIBRATION_EFFECT_SUPPORT_YES:
616                     continue;
617                 default: // VIBRATION_EFFECT_SUPPORT_UNKNOWN
618                     allSupported = VIBRATION_EFFECT_SUPPORT_UNKNOWN;
619                     break;
620             }
621         }
622         return allSupported;
623     }
624 
625     /**
626      * Query whether the vibrator supports the given primitives.
627      *
628      * The returned array will be the same length as the query array and the value at a given index
629      * will contain whether the effect at that same index in the querying array is supported or
630      * not.
631      *
632      * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if
633      * it is played.
634      *
635      * <p>Use {@link #areAllPrimitivesSupported(int...)} to get a single combined result,
636      * or for convenience when querying exactly one primitive.
637      *
638      * @param primitiveIds Which primitives to query for.
639      * @return Whether the primitives are supported.
640      */
641     @NonNull
arePrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)642     public boolean[] arePrimitivesSupported(
643             @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
644         VibratorInfo info = getInfo();
645         boolean[] supported = new boolean[primitiveIds.length];
646         for (int i = 0; i < primitiveIds.length; i++) {
647             supported[i] = info.isPrimitiveSupported(primitiveIds[i]);
648         }
649         return supported;
650     }
651 
652     /**
653      * Query whether the vibrator supports all of the given primitives.  If no argument is provided
654      * this method will always return {@code true}.
655      *
656      * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if
657      * it is played.
658      *
659      * <p>Use {@link #arePrimitivesSupported(int...)} to get individual results for each primitive.
660      *
661      * @param primitiveIds Which primitives to query for.
662      * @return Whether all specified primitives are supported. Empty query defaults to {@code true}.
663      */
areAllPrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)664     public final boolean areAllPrimitivesSupported(
665             @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
666         VibratorInfo info = getInfo();
667         for (int primitiveId : primitiveIds) {
668             if (!info.isPrimitiveSupported(primitiveId)) {
669                 return false;
670             }
671         }
672         return true;
673     }
674 
675     /**
676      * Query the estimated durations of the given primitives.
677      *
678      * <p>The returned array will be the same length as the query array and the value at a given
679      * index will contain the duration in milliseconds of the effect at the same index in the
680      * querying array.
681      *
682      * <p>The duration will be positive for primitives that are supported and zero for the
683      * unsupported ones, in correspondence with {@link #arePrimitivesSupported(int...)}.
684      *
685      * @param primitiveIds Which primitives to query for.
686      * @return The duration of each primitive, with zeroes for primitives that are not supported.
687      */
688     @NonNull
getPrimitiveDurations( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)689     public int[] getPrimitiveDurations(
690             @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
691         VibratorInfo info = getInfo();
692         int[] durations = new int[primitiveIds.length];
693         for (int i = 0; i < primitiveIds.length; i++) {
694             durations[i] = info.getPrimitiveDuration(primitiveIds[i]);
695         }
696         return durations;
697     }
698 
699     /**
700      * Turn the vibrator off.
701      */
702     @RequiresPermission(android.Manifest.permission.VIBRATE)
cancel()703     public abstract void cancel();
704 
705     /**
706      * Cancel specific types of ongoing vibrations.
707      *
708      * @param usageFilter The type of vibration to be cancelled, represented as a bitwise
709      *                    combination of {@link VibrationAttributes.Usage} values.
710      * @hide
711      */
712     @RequiresPermission(android.Manifest.permission.VIBRATE)
cancel(int usageFilter)713     public abstract void cancel(int usageFilter);
714 
715     /**
716      * Check whether the vibrator is vibrating.
717      *
718      * @return True if the hardware is vibrating, otherwise false.
719      * @hide
720      */
721     @SystemApi
722     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
isVibrating()723     public boolean isVibrating() {
724         return false;
725     }
726 
727     /**
728     * Listener for when the vibrator state has changed.
729     *
730     * @see #addVibratorStateListener
731     * @see #removeVibratorStateListener
732     * @hide
733     */
734     @SystemApi
735     public interface OnVibratorStateChangedListener  {
736         /**
737          * Called when the vibrator state has changed.
738          *
739          * @param isVibrating If true, the vibrator has started vibrating. If false,
740          *                    it's stopped vibrating.
741          */
onVibratorStateChanged(boolean isVibrating)742         void onVibratorStateChanged(boolean isVibrating);
743     }
744 
745     /**
746      * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread.
747      * If the listener was previously added and not removed, this call will be ignored.
748      *
749      * @param listener listener to be added
750      * @hide
751      */
752     @SystemApi
753     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
addVibratorStateListener(@onNull OnVibratorStateChangedListener listener)754     public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
755     }
756 
757     /**
758      * Adds a listener for vibrator state change. If the listener was previously added and not
759      * removed, this call will be ignored.
760      *
761      * @param listener listener to be added
762      * @param executor executor of listener
763      * @hide
764      */
765     @SystemApi
766     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
addVibratorStateListener( @onNull @allbackExecutor Executor executor, @NonNull OnVibratorStateChangedListener listener)767     public void addVibratorStateListener(
768             @NonNull @CallbackExecutor Executor executor,
769             @NonNull OnVibratorStateChangedListener listener) {
770     }
771 
772     /**
773      * Removes the listener for vibrator state changes. If the listener was not previously
774      * registered, this call will do nothing.
775      *
776      * @param listener listener to be removed
777      * @hide
778      */
779     @SystemApi
780     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
removeVibratorStateListener(@onNull OnVibratorStateChangedListener listener)781     public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
782     }
783 }
784