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