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
17package android.os;
18
19import android.annotation.IntDef;
20import android.annotation.RequiresPermission;
21import android.annotation.SystemService;
22import android.app.ActivityThread;
23import android.content.Context;
24import android.media.AudioAttributes;
25import android.util.Log;
26
27import java.lang.annotation.Retention;
28import java.lang.annotation.RetentionPolicy;
29
30/**
31 * Class that operates the vibrator on the device.
32 * <p>
33 * If your process exits, any vibration you started will stop.
34 * </p>
35 */
36@SystemService(Context.VIBRATOR_SERVICE)
37public abstract class Vibrator {
38    private static final String TAG = "Vibrator";
39
40    /**
41     * Vibration intensity: no vibrations.
42     * @hide
43     */
44    public static final int VIBRATION_INTENSITY_OFF = 0;
45
46    /**
47     * Vibration intensity: low.
48     * @hide
49     */
50    public static final int VIBRATION_INTENSITY_LOW = 1;
51
52    /**
53     * Vibration intensity: medium.
54     * @hide
55     */
56    public static final int VIBRATION_INTENSITY_MEDIUM = 2;
57
58    /**
59     * Vibration intensity: high.
60     * @hide
61     */
62    public static final int VIBRATION_INTENSITY_HIGH = 3;
63
64    /** @hide */
65    @Retention(RetentionPolicy.SOURCE)
66    @IntDef(prefix = { "VIBRATION_INTENSITY_" }, value = {
67        VIBRATION_INTENSITY_OFF,
68        VIBRATION_INTENSITY_LOW,
69        VIBRATION_INTENSITY_MEDIUM,
70        VIBRATION_INTENSITY_HIGH
71    })
72    public @interface VibrationIntensity{}
73
74    private final String mPackageName;
75    // The default vibration intensity level for haptic feedback.
76    @VibrationIntensity
77    private final int mDefaultHapticFeedbackIntensity;
78    // The default vibration intensity level for notifications.
79    @VibrationIntensity
80    private final int mDefaultNotificationVibrationIntensity;
81
82    /**
83     * @hide to prevent subclassing from outside of the framework
84     */
85    public Vibrator() {
86        mPackageName = ActivityThread.currentPackageName();
87        final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
88        mDefaultHapticFeedbackIntensity = loadDefaultIntensity(ctx,
89                com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
90        mDefaultNotificationVibrationIntensity = loadDefaultIntensity(ctx,
91                com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
92    }
93
94    /**
95     * @hide to prevent subclassing from outside of the framework
96     */
97    protected Vibrator(Context context) {
98        mPackageName = context.getOpPackageName();
99        mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
100                com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
101        mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
102                com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
103    }
104
105    private int loadDefaultIntensity(Context ctx, int resId) {
106        return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
107    }
108
109    /**
110     * Get the default vibration intensity for haptic feedback.
111     * @hide
112     */
113    public int getDefaultHapticFeedbackIntensity() {
114        return mDefaultHapticFeedbackIntensity;
115    }
116
117    /**
118     * Get the default vibration intensity for notifications and ringtones.
119     * @hide
120     */
121    public int getDefaultNotificationVibrationIntensity() {
122        return mDefaultNotificationVibrationIntensity;
123    }
124
125    /**
126     * Check whether the hardware has a vibrator.
127     *
128     * @return True if the hardware has a vibrator, else false.
129     */
130    public abstract boolean hasVibrator();
131
132    /**
133     * Check whether the vibrator has amplitude control.
134     *
135     * @return True if the hardware can control the amplitude of the vibrations, otherwise false.
136     */
137    public abstract boolean hasAmplitudeControl();
138
139    /**
140     * Vibrate constantly for the specified period of time.
141     *
142     * @param milliseconds The number of milliseconds to vibrate.
143     *
144     * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
145     */
146    @Deprecated
147    @RequiresPermission(android.Manifest.permission.VIBRATE)
148    public void vibrate(long milliseconds) {
149        vibrate(milliseconds, null);
150    }
151
152    /**
153     * Vibrate constantly for the specified period of time.
154     *
155     * @param milliseconds The number of milliseconds to vibrate.
156     * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
157     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
158     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
159     *        vibrations associated with incoming calls.
160     *
161     * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
162     */
163    @Deprecated
164    @RequiresPermission(android.Manifest.permission.VIBRATE)
165    public void vibrate(long milliseconds, AudioAttributes attributes) {
166        try {
167            // This ignores all exceptions to stay compatible with pre-O implementations.
168            VibrationEffect effect =
169                    VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
170            vibrate(effect, attributes);
171        } catch (IllegalArgumentException iae) {
172            Log.e(TAG, "Failed to create VibrationEffect", iae);
173        }
174    }
175
176    /**
177     * Vibrate with a given pattern.
178     *
179     * <p>
180     * Pass in an array of ints that are the durations for which to turn on or off
181     * the vibrator in milliseconds.  The first value indicates the number of milliseconds
182     * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
183     * for which to keep the vibrator on before turning it off.  Subsequent values alternate
184     * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
185     * </p><p>
186     * To cause the pattern to repeat, pass the index into the pattern array at which
187     * to start the repeat, or -1 to disable repeating.
188     * </p>
189     *
190     * @param pattern an array of longs of times for which to turn the vibrator on or off.
191     * @param repeat the index into pattern at which to repeat, or -1 if
192     *        you don't want to repeat.
193     *
194     * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
195     */
196    @Deprecated
197    @RequiresPermission(android.Manifest.permission.VIBRATE)
198    public void vibrate(long[] pattern, int repeat) {
199        vibrate(pattern, repeat, null);
200    }
201
202    /**
203     * Vibrate with a given pattern.
204     *
205     * <p>
206     * Pass in an array of ints that are the durations for which to turn on or off
207     * the vibrator in milliseconds.  The first value indicates the number of milliseconds
208     * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
209     * for which to keep the vibrator on before turning it off.  Subsequent values alternate
210     * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
211     * </p><p>
212     * To cause the pattern to repeat, pass the index into the pattern array at which
213     * to start the repeat, or -1 to disable repeating.
214     * </p>
215     *
216     * @param pattern an array of longs of times for which to turn the vibrator on or off.
217     * @param repeat the index into pattern at which to repeat, or -1 if
218     *        you don't want to repeat.
219     * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
220     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
221     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
222     *        vibrations associated with incoming calls.
223     *
224     * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
225     */
226    @Deprecated
227    @RequiresPermission(android.Manifest.permission.VIBRATE)
228    public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
229        // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other
230        // exceptions for compatibility purposes
231        if (repeat < -1 || repeat >= pattern.length) {
232            Log.e(TAG, "vibrate called with repeat index out of bounds" +
233                    " (pattern.length=" + pattern.length + ", index=" + repeat + ")");
234            throw new ArrayIndexOutOfBoundsException();
235        }
236
237        try {
238            vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes);
239        } catch (IllegalArgumentException iae) {
240            Log.e(TAG, "Failed to create VibrationEffect", iae);
241        }
242    }
243
244    @RequiresPermission(android.Manifest.permission.VIBRATE)
245    public void vibrate(VibrationEffect vibe) {
246        vibrate(vibe, null);
247    }
248
249    @RequiresPermission(android.Manifest.permission.VIBRATE)
250    public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
251        vibrate(Process.myUid(), mPackageName, vibe, attributes);
252    }
253
254    /**
255     * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allowing the caller to specify
256     * that the vibration is owned by someone else.
257     * @hide
258     */
259    @RequiresPermission(android.Manifest.permission.VIBRATE)
260    public abstract void vibrate(int uid, String opPkg,
261            VibrationEffect vibe, AudioAttributes attributes);
262
263    /**
264     * Turn the vibrator off.
265     */
266    @RequiresPermission(android.Manifest.permission.VIBRATE)
267    public abstract void cancel();
268}
269