• 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.media.AudioAttributes;
31 import android.util.Log;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.util.Arrays;
36 import java.util.concurrent.Executor;
37 
38 /**
39  * Class that operates the vibrator on the device.
40  * <p>
41  * If your process exits, any vibration you started will stop.
42  * </p>
43  */
44 @SystemService(Context.VIBRATOR_SERVICE)
45 public abstract class Vibrator {
46     private static final String TAG = "Vibrator";
47 
48     /**
49      * Vibration intensity: no vibrations.
50      *
51      * @hide
52      */
53     public static final int VIBRATION_INTENSITY_OFF = 0;
54 
55     /**
56      * Vibration intensity: low.
57      *
58      * @hide
59      */
60     public static final int VIBRATION_INTENSITY_LOW = 1;
61 
62     /**
63      * Vibration intensity: medium.
64      *
65      * @hide
66      */
67     public static final int VIBRATION_INTENSITY_MEDIUM = 2;
68 
69     /**
70      * Vibration intensity: high.
71      *
72      * @hide
73      */
74     public static final int VIBRATION_INTENSITY_HIGH = 3;
75 
76     /**
77      * Vibration effect support: unknown
78      *
79      * The hardware doesn't report it's supported effects, so we can't determine whether the
80      * effect is supported or not.
81      */
82     public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0;
83 
84     /**
85      * Vibration effect support: supported
86      *
87      * This effect is supported by the underlying hardware.
88      */
89     public static final int VIBRATION_EFFECT_SUPPORT_YES = 1;
90 
91     /**
92      * Vibration effect support: unsupported
93      *
94      * This effect is <b>not</b> supported by the underlying hardware.
95      */
96     public static final int VIBRATION_EFFECT_SUPPORT_NO = 2;
97 
98     /** @hide */
99     @Retention(RetentionPolicy.SOURCE)
100     @IntDef(prefix = {"VIBRATION_EFFECT_SUPPORT_"}, value = {
101             VIBRATION_EFFECT_SUPPORT_UNKNOWN,
102             VIBRATION_EFFECT_SUPPORT_YES,
103             VIBRATION_EFFECT_SUPPORT_NO,
104     })
105     public @interface VibrationEffectSupport {}
106 
107     /** @hide */
108     @Retention(RetentionPolicy.SOURCE)
109     @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = {
110             VIBRATION_INTENSITY_OFF,
111             VIBRATION_INTENSITY_LOW,
112             VIBRATION_INTENSITY_MEDIUM,
113             VIBRATION_INTENSITY_HIGH
114     })
115     public @interface VibrationIntensity {
116     }
117 
118     private final String mPackageName;
119     // The default vibration intensity level for haptic feedback.
120     @VibrationIntensity
121     private int mDefaultHapticFeedbackIntensity;
122     // The default vibration intensity level for notifications.
123     @VibrationIntensity
124     private int mDefaultNotificationVibrationIntensity;
125     // The default vibration intensity level for ringtones.
126     @VibrationIntensity
127     private int mDefaultRingVibrationIntensity;
128 
129     /**
130      * @hide to prevent subclassing from outside of the framework
131      */
132     @UnsupportedAppUsage
Vibrator()133     public Vibrator() {
134         mPackageName = ActivityThread.currentPackageName();
135         final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
136         loadVibrationIntensities(ctx);
137     }
138 
139     /**
140      * @hide to prevent subclassing from outside of the framework
141      */
Vibrator(Context context)142     protected Vibrator(Context context) {
143         mPackageName = context.getOpPackageName();
144         loadVibrationIntensities(context);
145     }
146 
loadVibrationIntensities(Context context)147     private void loadVibrationIntensities(Context context) {
148         mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
149                 com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
150         mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
151                 com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
152         mDefaultRingVibrationIntensity = loadDefaultIntensity(context,
153                 com.android.internal.R.integer.config_defaultRingVibrationIntensity);
154     }
155 
loadDefaultIntensity(Context ctx, int resId)156     private int loadDefaultIntensity(Context ctx, int resId) {
157         return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
158     }
159 
160     /**
161      * Get the default vibration intensity for haptic feedback.
162      *
163      * @hide
164      */
getDefaultHapticFeedbackIntensity()165     public int getDefaultHapticFeedbackIntensity() {
166         return mDefaultHapticFeedbackIntensity;
167     }
168 
169     /**
170      * Get the default vibration intensity for notifications.
171      *
172      * @hide
173      */
getDefaultNotificationVibrationIntensity()174     public int getDefaultNotificationVibrationIntensity() {
175         return mDefaultNotificationVibrationIntensity;
176     }
177 
178     /**
179      * Get the default vibration intensity for ringtones.
180      *
181      * @hide
182      */
getDefaultRingVibrationIntensity()183     public int getDefaultRingVibrationIntensity() {
184         return mDefaultRingVibrationIntensity;
185     }
186 
187     /**
188      * Check whether the hardware has a vibrator.
189      *
190      * @return True if the hardware has a vibrator, else false.
191      */
hasVibrator()192     public abstract boolean hasVibrator();
193 
194     /**
195      * Check whether the vibrator has amplitude control.
196      *
197      * @return True if the hardware can control the amplitude of the vibrations, otherwise false.
198      */
hasAmplitudeControl()199     public abstract boolean hasAmplitudeControl();
200 
201     /**
202      * Configure an always-on haptics effect.
203      *
204      * @param alwaysOnId The board-specific always-on ID to configure.
205      * @param effect     Vibration effect to assign to always-on id. Passing null will disable it.
206      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
207      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
208      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
209      *                   vibrations associated with incoming calls. May only be null when effect is
210      *                   null.
211      * @hide
212      */
213     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes)214     public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect,
215             @Nullable AudioAttributes attributes) {
216         return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes);
217     }
218 
219     /**
220      * @hide
221      */
222     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes)223     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
224             @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) {
225         Log.w(TAG, "Always-on effects aren't supported");
226         return false;
227     }
228 
229     /**
230      * Vibrate constantly for the specified period of time.
231      *
232      * @param milliseconds The number of milliseconds to vibrate.
233      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
234      */
235     @Deprecated
236     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long milliseconds)237     public void vibrate(long milliseconds) {
238         vibrate(milliseconds, null);
239     }
240 
241     /**
242      * Vibrate constantly for the specified period of time.
243      *
244      * @param milliseconds The number of milliseconds to vibrate.
245      * @param attributes   {@link AudioAttributes} corresponding to the vibration. For example,
246      *                     specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
247      *                     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
248      *                     vibrations associated with incoming calls.
249      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
250      */
251     @Deprecated
252     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long milliseconds, AudioAttributes attributes)253     public void vibrate(long milliseconds, AudioAttributes attributes) {
254         try {
255             // This ignores all exceptions to stay compatible with pre-O implementations.
256             VibrationEffect effect =
257                     VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
258             vibrate(effect, attributes);
259         } catch (IllegalArgumentException iae) {
260             Log.e(TAG, "Failed to create VibrationEffect", iae);
261         }
262     }
263 
264     /**
265      * Vibrate with a given pattern.
266      *
267      * <p>
268      * Pass in an array of ints that are the durations for which to turn on or off
269      * the vibrator in milliseconds.  The first value indicates the number of milliseconds
270      * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
271      * for which to keep the vibrator on before turning it off.  Subsequent values alternate
272      * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
273      * </p><p>
274      * To cause the pattern to repeat, pass the index into the pattern array at which
275      * to start the repeat, or -1 to disable repeating.
276      * </p>
277      *
278      * @param pattern an array of longs of times for which to turn the vibrator on or off.
279      * @param repeat  the index into pattern at which to repeat, or -1 if
280      *                you don't want to repeat.
281      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
282      */
283     @Deprecated
284     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long[] pattern, int repeat)285     public void vibrate(long[] pattern, int repeat) {
286         vibrate(pattern, repeat, null);
287     }
288 
289     /**
290      * Vibrate with a given pattern.
291      *
292      * <p>
293      * Pass in an array of ints that are the durations for which to turn on or off
294      * the vibrator in milliseconds.  The first value indicates the number of milliseconds
295      * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
296      * for which to keep the vibrator on before turning it off.  Subsequent values alternate
297      * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
298      * </p><p>
299      * To cause the pattern to repeat, pass the index into the pattern array at which
300      * to start the repeat, or -1 to disable repeating.
301      * </p>
302      *
303      * @param pattern    an array of longs of times for which to turn the vibrator on or off.
304      * @param repeat     the index into pattern at which to repeat, or -1 if
305      *                   you don't want to repeat.
306      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
307      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
308      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
309      *                   vibrations associated with incoming calls.
310      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
311      */
312     @Deprecated
313     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(long[] pattern, int repeat, AudioAttributes attributes)314     public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
315         // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other
316         // exceptions for compatibility purposes
317         if (repeat < -1 || repeat >= pattern.length) {
318             Log.e(TAG, "vibrate called with repeat index out of bounds" +
319                     " (pattern.length=" + pattern.length + ", index=" + repeat + ")");
320             throw new ArrayIndexOutOfBoundsException();
321         }
322 
323         try {
324             vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes);
325         } catch (IllegalArgumentException iae) {
326             Log.e(TAG, "Failed to create VibrationEffect", iae);
327         }
328     }
329 
330     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(VibrationEffect vibe)331     public void vibrate(VibrationEffect vibe) {
332         vibrate(vibe, null);
333     }
334 
335     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(VibrationEffect vibe, AudioAttributes attributes)336     public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
337         vibrate(Process.myUid(), mPackageName, vibe, null, attributes);
338     }
339 
340     /**
341      * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allows the
342      * caller to specify the vibration is owned by someone else and set reason for vibration.
343      *
344      * @hide
345      */
346     @RequiresPermission(android.Manifest.permission.VIBRATE)
vibrate(int uid, String opPkg, VibrationEffect vibe, String reason, AudioAttributes attributes)347     public abstract void vibrate(int uid, String opPkg, VibrationEffect vibe,
348             String reason, AudioAttributes attributes);
349 
350     /**
351      * Query whether the vibrator supports the given effects.
352      *
353      * Not all hardware reports its effect capabilities, so the system may not necessarily know
354      * whether an effect is supported or not.
355      *
356      * The returned array will be the same length as the query array and the value at a given index
357      * will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index in the
358      * querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or
359      * {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's
360      * supported or not.
361      *
362      * @param effectIds Which effects to query for.
363      * @return An array containing the systems current knowledge about whether the given effects
364      * are supported or not.
365      */
366     @NonNull
367     @VibrationEffectSupport
areEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)368     public int[] areEffectsSupported(
369             @NonNull @VibrationEffect.EffectType int... effectIds) {
370         final int[] support = new int[effectIds.length];
371         Arrays.fill(support, VIBRATION_EFFECT_SUPPORT_NO);
372         return support;
373     }
374 
375     /**
376      * Query whether the vibrator supports all of the given effects.
377      *
378      * Not all hardware reports its effect capabilities, so the system may not necessarily know
379      * whether an effect is supported or not.
380      *
381      * If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are
382      * supported by the hardware.
383      *
384      * If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the
385      * query is not supported.
386      *
387      * If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know whether
388      * all of the effects are supported. It may support any or all of the queried effects,
389      * but there's no way to programmatically know whether a {@link #vibrate} call will successfully
390      * cause a vibration. It's guaranteed, however, that none of the queried effects are
391      * definitively unsupported by the hardware.
392      *
393      * @param effectIds Which effects to query for.
394      * @return Whether all of the effects are supported.
395      */
396     @VibrationEffectSupport
areAllEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)397     public final int areAllEffectsSupported(
398             @NonNull @VibrationEffect.EffectType int... effectIds) {
399         int support = VIBRATION_EFFECT_SUPPORT_YES;
400         for (int supported : areEffectsSupported(effectIds)) {
401             if (supported == VIBRATION_EFFECT_SUPPORT_NO) {
402                 return VIBRATION_EFFECT_SUPPORT_NO;
403             } else if (supported == VIBRATION_EFFECT_SUPPORT_UNKNOWN) {
404                 support = VIBRATION_EFFECT_SUPPORT_UNKNOWN;
405             }
406         }
407         return support;
408     }
409 
410 
411     /**
412      * Query whether the vibrator supports the given primitives.
413      *
414      * The returned array will be the same length as the query array and the value at a given index
415      * will contain whether the effect at that same index in the querying array is supported or
416      * not.
417      *
418      * @param primitiveIds Which primitives to query for.
419      * @return Whether the primitives are supported.
420      */
421     @NonNull
arePrimitivesSupported( @onNull @ibrationEffect.Composition.Primitive int... primitiveIds)422     public boolean[] arePrimitivesSupported(
423             @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
424         return new boolean[primitiveIds.length];
425     }
426 
427     /**
428      * Query whether the vibrator supports all of the given primitives.
429      *
430      * @param primitiveIds Which primitives to query for.
431      * @return Whether primitives effects are supported.
432      */
areAllPrimitivesSupported( @onNull @ibrationEffect.Composition.Primitive int... primitiveIds)433     public final boolean areAllPrimitivesSupported(
434             @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
435         for (boolean supported : arePrimitivesSupported(primitiveIds)) {
436             if (!supported) {
437                 return false;
438             }
439         }
440         return true;
441     }
442 
443     /**
444      * Turn the vibrator off.
445      */
446     @RequiresPermission(android.Manifest.permission.VIBRATE)
cancel()447     public abstract void cancel();
448 
449     /**
450      * Check whether the vibrator is vibrating.
451      *
452      * @return True if the hardware is vibrating, otherwise false.
453      * @hide
454      */
455     @SystemApi
456     @TestApi
457     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
isVibrating()458     public boolean isVibrating() {
459         return false;
460     }
461 
462     /**
463     * Listener for when the vibrator state has changed.
464     *
465     * @see #addVibratorStateListener
466     * @see #removeVibratorStateListener
467     * @hide
468     */
469     @SystemApi
470     @TestApi
471     public interface OnVibratorStateChangedListener  {
472         /**
473          * Called when the vibrator state has changed.
474          *
475          * @param isVibrating If true, the vibrator has started vibrating. If false,
476          *                    it's stopped vibrating.
477          */
onVibratorStateChanged(boolean isVibrating)478         void onVibratorStateChanged(boolean isVibrating);
479     }
480 
481     /**
482      * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread.
483      * If the listener was previously added and not removed, this call will be ignored.
484      *
485      * @param listener listener to be added
486      * @hide
487      */
488     @SystemApi
489     @TestApi
490     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
addVibratorStateListener(@onNull OnVibratorStateChangedListener listener)491     public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
492     }
493 
494     /**
495      * Adds a listener for vibrator state change. If the listener was previously added and not
496      * removed, this call will be ignored.
497      *
498      * @param listener listener to be added
499      * @param executor executor of listener
500      * @hide
501      */
502     @SystemApi
503     @TestApi
504     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
addVibratorStateListener( @onNull @allbackExecutor Executor executor, @NonNull OnVibratorStateChangedListener listener)505     public void addVibratorStateListener(
506             @NonNull @CallbackExecutor Executor executor,
507             @NonNull OnVibratorStateChangedListener listener) {
508     }
509 
510     /**
511      * Removes the listener for vibrator state changes. If the listener was not previously
512      * registered, this call will do nothing.
513      *
514      * @param listener listener to be removed
515      * @hide
516      */
517     @SystemApi
518     @TestApi
519     @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
removeVibratorStateListener(@onNull OnVibratorStateChangedListener listener)520     public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
521     }
522 }
523