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