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