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.FloatRange; 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.RequiresPermission; 25 import android.annotation.SystemApi; 26 import android.annotation.SystemService; 27 import android.app.ActivityThread; 28 import android.compat.annotation.UnsupportedAppUsage; 29 import android.content.Context; 30 import android.hardware.vibrator.IVibrator; 31 import android.media.AudioAttributes; 32 import android.util.Log; 33 import android.util.Range; 34 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.util.concurrent.Executor; 38 39 /** 40 * Class that operates the vibrator on the device. 41 * <p> 42 * If your process exits, any vibration you started will stop. 43 * </p> 44 */ 45 @SystemService(Context.VIBRATOR_SERVICE) 46 public abstract class Vibrator { 47 private static final String TAG = "Vibrator"; 48 49 /** 50 * Vibration intensity: no vibrations. 51 * 52 * @hide 53 */ 54 public static final int VIBRATION_INTENSITY_OFF = 0; 55 56 /** 57 * Vibration intensity: low. 58 * 59 * @hide 60 */ 61 public static final int VIBRATION_INTENSITY_LOW = 1; 62 63 /** 64 * Vibration intensity: medium. 65 * 66 * @hide 67 */ 68 public static final int VIBRATION_INTENSITY_MEDIUM = 2; 69 70 /** 71 * Vibration intensity: high. 72 * 73 * @hide 74 */ 75 public static final int VIBRATION_INTENSITY_HIGH = 3; 76 77 /** 78 * Vibration effect support: unknown 79 * 80 * The hardware doesn't report it's supported effects, so we can't determine whether the 81 * effect is supported or not. 82 */ 83 public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0; 84 85 /** 86 * Vibration effect support: supported 87 * 88 * This effect is supported by the underlying hardware. 89 */ 90 public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; 91 92 /** 93 * Vibration effect support: unsupported 94 * 95 * This effect is <b>not</b> supported by the underlying hardware. 96 */ 97 public static final int VIBRATION_EFFECT_SUPPORT_NO = 2; 98 99 /** @hide */ 100 @Retention(RetentionPolicy.SOURCE) 101 @IntDef(prefix = {"VIBRATION_EFFECT_SUPPORT_"}, value = { 102 VIBRATION_EFFECT_SUPPORT_UNKNOWN, 103 VIBRATION_EFFECT_SUPPORT_YES, 104 VIBRATION_EFFECT_SUPPORT_NO, 105 }) 106 public @interface VibrationEffectSupport {} 107 108 /** @hide */ 109 @Retention(RetentionPolicy.SOURCE) 110 @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = { 111 VIBRATION_INTENSITY_OFF, 112 VIBRATION_INTENSITY_LOW, 113 VIBRATION_INTENSITY_MEDIUM, 114 VIBRATION_INTENSITY_HIGH 115 }) 116 public @interface VibrationIntensity { 117 } 118 119 private final String mPackageName; 120 // The default vibration intensity level for haptic feedback. 121 @VibrationIntensity 122 private int mDefaultHapticFeedbackIntensity; 123 // The default vibration intensity level for notifications. 124 @VibrationIntensity 125 private int mDefaultNotificationVibrationIntensity; 126 // The default vibration intensity level for ringtones. 127 @VibrationIntensity 128 private int mDefaultRingVibrationIntensity; 129 private float mHapticChannelMaxVibrationAmplitude; 130 131 /** 132 * @hide to prevent subclassing from outside of the framework 133 */ 134 @UnsupportedAppUsage Vibrator()135 public Vibrator() { 136 mPackageName = ActivityThread.currentPackageName(); 137 final Context ctx = ActivityThread.currentActivityThread().getSystemContext(); 138 loadVibrationConfig(ctx); 139 } 140 141 /** 142 * @hide to prevent subclassing from outside of the framework 143 */ Vibrator(Context context)144 protected Vibrator(Context context) { 145 mPackageName = context.getOpPackageName(); 146 loadVibrationConfig(context); 147 } 148 loadVibrationConfig(Context context)149 private void loadVibrationConfig(Context context) { 150 mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context, 151 com.android.internal.R.integer.config_defaultHapticFeedbackIntensity); 152 mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context, 153 com.android.internal.R.integer.config_defaultNotificationVibrationIntensity); 154 mDefaultRingVibrationIntensity = loadDefaultIntensity(context, 155 com.android.internal.R.integer.config_defaultRingVibrationIntensity); 156 mHapticChannelMaxVibrationAmplitude = loadFloat(context, 157 com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0); 158 } 159 loadDefaultIntensity(Context ctx, int resId)160 private int loadDefaultIntensity(Context ctx, int resId) { 161 return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM; 162 } 163 loadFloat(Context ctx, int resId, float defaultValue)164 private float loadFloat(Context ctx, int resId, float defaultValue) { 165 return ctx != null ? ctx.getResources().getFloat(resId) : defaultValue; 166 } 167 168 /** @hide */ getInfo()169 protected VibratorInfo getInfo() { 170 return VibratorInfo.EMPTY_VIBRATOR_INFO; 171 } 172 173 /** 174 * Get the default vibration intensity for haptic feedback. 175 * 176 * @hide 177 */ getDefaultHapticFeedbackIntensity()178 public int getDefaultHapticFeedbackIntensity() { 179 return mDefaultHapticFeedbackIntensity; 180 } 181 182 /** 183 * Get the default vibration intensity for notifications. 184 * 185 * @hide 186 */ getDefaultNotificationVibrationIntensity()187 public int getDefaultNotificationVibrationIntensity() { 188 return mDefaultNotificationVibrationIntensity; 189 } 190 191 /** 192 * Get the default vibration intensity for ringtones. 193 * 194 * @hide 195 */ getDefaultRingVibrationIntensity()196 public int getDefaultRingVibrationIntensity() { 197 return mDefaultRingVibrationIntensity; 198 } 199 200 /** 201 * Return the ID of this vibrator. 202 * 203 * @return A non-negative integer representing the id of the vibrator controlled by this 204 * service, or -1 this service is not attached to any physical vibrator. 205 */ getId()206 public int getId() { 207 return getInfo().getId(); 208 } 209 210 /** 211 * Check whether the hardware has a vibrator. 212 * 213 * @return True if the hardware has a vibrator, else false. 214 */ hasVibrator()215 public abstract boolean hasVibrator(); 216 217 /** 218 * Check whether the vibrator has amplitude control. 219 * 220 * @return True if the hardware can control the amplitude of the vibrations, otherwise false. 221 */ hasAmplitudeControl()222 public abstract boolean hasAmplitudeControl(); 223 224 /** 225 * Check whether the vibrator has independent frequency control. 226 * 227 * @return True if the hardware can control the frequency of the vibrations, otherwise false. 228 * @hide 229 */ hasFrequencyControl()230 public boolean hasFrequencyControl() { 231 // We currently can only control frequency of the vibration using the compose PWLE method. 232 return getInfo().hasCapability( 233 IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS); 234 } 235 236 /** 237 * Check whether the vibrator can be controlled by an external service with the 238 * {@link IExternalVibratorService}. 239 * 240 * @return True if the hardware can be controlled by an external service, otherwise false. 241 * @hide 242 */ hasExternalControl()243 public boolean hasExternalControl() { 244 return getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL); 245 } 246 247 /** 248 * Gets the resonant frequency of the vibrator. 249 * 250 * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown or 251 * this vibrator is a composite of multiple physical devices. 252 * @hide 253 */ getResonantFrequency()254 public float getResonantFrequency() { 255 return getInfo().getResonantFrequency(); 256 } 257 258 /** 259 * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator. 260 * 261 * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown or 262 * this vibrator is a composite of multiple physical devices. 263 * @hide 264 */ getQFactor()265 public float getQFactor() { 266 return getInfo().getQFactor(); 267 } 268 269 /** 270 * Return a range of relative frequency values supported by the vibrator. 271 * 272 * <p>These values can be used to create waveforms that controls the vibration frequency via 273 * {@link VibrationEffect.WaveformBuilder}. 274 * 275 * @return A range of relative frequency values supported. The range will always contain the 276 * value 0, representing the device resonant frequency. Devices without frequency control will 277 * return the range [0,0]. Devices with frequency control will always return a range containing 278 * the safe range [-1, 1]. 279 * @hide 280 */ getRelativeFrequencyRange()281 public Range<Float> getRelativeFrequencyRange() { 282 return getInfo().getFrequencyRange(); 283 } 284 285 /** 286 * Return the maximum amplitude the vibrator can play at given relative frequency. 287 * 288 * <p>Devices without frequency control will return 1 for the input zero (resonant frequency), 289 * and 0 to any other input. 290 * 291 * <p>Devices with frequency control will return the supported value, for input in 292 * {@link #getRelativeFrequencyRange()}, and 0 for any other input. 293 * 294 * <p>These values can be used to create waveforms that plays vibrations outside the resonant 295 * frequency via {@link VibrationEffect.WaveformBuilder}. 296 * 297 * @return a value in [0,1] representing the maximum amplitude the device can play at given 298 * relative frequency. 299 * @hide 300 */ 301 @FloatRange(from = 0, to = 1) getMaximumAmplitude(float relativeFrequency)302 public float getMaximumAmplitude(float relativeFrequency) { 303 return getInfo().getMaxAmplitude(relativeFrequency); 304 } 305 306 /** 307 * Return the maximum amplitude the vibrator can play using the audio haptic channels. 308 * 309 * <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a 310 * positive value <code>maxAmplitude</code>, then the signals from the haptic channels of audio 311 * tracks should be in the range <code>[-maxAmplitude, maxAmplitude]</code>. 312 * 313 * @return a positive value representing the maximum absolute value the device can play signals 314 * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown. 315 * @hide 316 */ getHapticChannelMaximumAmplitude()317 public float getHapticChannelMaximumAmplitude() { 318 if (mHapticChannelMaxVibrationAmplitude <= 0) { 319 return Float.NaN; 320 } 321 return mHapticChannelMaxVibrationAmplitude; 322 } 323 324 /** 325 * Configure an always-on haptics effect. 326 * 327 * @param alwaysOnId The board-specific always-on ID to configure. 328 * @param effect Vibration effect to assign to always-on id. Passing null will disable it. 329 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 330 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 331 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 332 * vibrations associated with incoming calls. May only be null when effect is 333 * null. 334 * @hide 335 */ 336 @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON) setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes)337 public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, 338 @Nullable AudioAttributes attributes) { 339 return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes); 340 } 341 342 /** 343 * @hide 344 */ 345 @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON) setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes)346 public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, 347 @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) { 348 Log.w(TAG, "Always-on effects aren't supported"); 349 return false; 350 } 351 352 /** 353 * Vibrate constantly for the specified period of time. 354 * 355 * @param milliseconds The number of milliseconds to vibrate. 356 * @deprecated Use {@link #vibrate(VibrationEffect)} instead. 357 */ 358 @Deprecated 359 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long milliseconds)360 public void vibrate(long milliseconds) { 361 vibrate(milliseconds, null); 362 } 363 364 /** 365 * Vibrate constantly for the specified period of time. 366 * 367 * @param milliseconds The number of milliseconds to vibrate. 368 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 369 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 370 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 371 * vibrations associated with incoming calls. 372 * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead. 373 */ 374 @Deprecated 375 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long milliseconds, AudioAttributes attributes)376 public void vibrate(long milliseconds, AudioAttributes attributes) { 377 try { 378 // This ignores all exceptions to stay compatible with pre-O implementations. 379 VibrationEffect effect = 380 VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE); 381 vibrate(effect, attributes); 382 } catch (IllegalArgumentException iae) { 383 Log.e(TAG, "Failed to create VibrationEffect", iae); 384 } 385 } 386 387 /** 388 * Vibrate with a given pattern. 389 * 390 * <p> 391 * Pass in an array of ints that are the durations for which to turn on or off 392 * the vibrator in milliseconds. The first value indicates the number of milliseconds 393 * to wait before turning the vibrator on. The next value indicates the number of milliseconds 394 * for which to keep the vibrator on before turning it off. Subsequent values alternate 395 * between durations in milliseconds to turn the vibrator off or to turn the vibrator on. 396 * </p><p> 397 * To cause the pattern to repeat, pass the index into the pattern array at which 398 * to start the repeat, or -1 to disable repeating. 399 * </p> 400 * 401 * @param pattern an array of longs of times for which to turn the vibrator on or off. 402 * @param repeat the index into pattern at which to repeat, or -1 if 403 * you don't want to repeat. 404 * @deprecated Use {@link #vibrate(VibrationEffect)} instead. 405 */ 406 @Deprecated 407 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long[] pattern, int repeat)408 public void vibrate(long[] pattern, int repeat) { 409 vibrate(pattern, repeat, null); 410 } 411 412 /** 413 * Vibrate with a given pattern. 414 * 415 * <p> 416 * Pass in an array of ints that are the durations for which to turn on or off 417 * the vibrator in milliseconds. The first value indicates the number of milliseconds 418 * to wait before turning the vibrator on. The next value indicates the number of milliseconds 419 * for which to keep the vibrator on before turning it off. Subsequent values alternate 420 * between durations in milliseconds to turn the vibrator off or to turn the vibrator on. 421 * </p><p> 422 * To cause the pattern to repeat, pass the index into the pattern array at which 423 * to start the repeat, or -1 to disable repeating. 424 * </p> 425 * 426 * @param pattern an array of longs of times for which to turn the vibrator on or off. 427 * @param repeat the index into pattern at which to repeat, or -1 if 428 * you don't want to repeat. 429 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 430 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 431 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 432 * vibrations associated with incoming calls. 433 * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead. 434 */ 435 @Deprecated 436 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long[] pattern, int repeat, AudioAttributes attributes)437 public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) { 438 // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other 439 // exceptions for compatibility purposes 440 if (repeat < -1 || repeat >= pattern.length) { 441 Log.e(TAG, "vibrate called with repeat index out of bounds" + 442 " (pattern.length=" + pattern.length + ", index=" + repeat + ")"); 443 throw new ArrayIndexOutOfBoundsException(); 444 } 445 446 try { 447 vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes); 448 } catch (IllegalArgumentException iae) { 449 Log.e(TAG, "Failed to create VibrationEffect", iae); 450 } 451 } 452 453 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(VibrationEffect vibe)454 public void vibrate(VibrationEffect vibe) { 455 vibrate(vibe, null); 456 } 457 458 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(VibrationEffect vibe, AudioAttributes attributes)459 public void vibrate(VibrationEffect vibe, AudioAttributes attributes) { 460 vibrate(Process.myUid(), mPackageName, vibe, null, attributes); 461 } 462 463 /** 464 * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allows the 465 * caller to specify the vibration is owned by someone else and set reason for vibration. 466 * 467 * @hide 468 */ 469 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(int uid, String opPkg, VibrationEffect vibe, String reason, AudioAttributes attributes)470 public final void vibrate(int uid, String opPkg, VibrationEffect vibe, 471 String reason, AudioAttributes attributes) { 472 if (attributes == null) { 473 attributes = new AudioAttributes.Builder().build(); 474 } 475 VibrationAttributes attr = new VibrationAttributes.Builder(attributes, vibe).build(); 476 vibrate(uid, opPkg, vibe, reason, attr); 477 } 478 479 /** 480 * Like {@link #vibrate(int, String, VibrationEffect, String, AudioAttributes)}, but allows the 481 * caller to specify {@link VibrationAttributes} instead of {@link AudioAttributes}. 482 * 483 * @hide 484 */ 485 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, String reason, @NonNull VibrationAttributes attributes)486 public abstract void vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, 487 String reason, @NonNull VibrationAttributes attributes); 488 489 /** 490 * Query whether the vibrator supports the given effects. 491 * 492 * Not all hardware reports its effect capabilities, so the system may not necessarily know 493 * whether an effect is supported or not. 494 * 495 * The returned array will be the same length as the query array and the value at a given index 496 * will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index in the 497 * querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or 498 * {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's 499 * supported or not. 500 * 501 * @param effectIds Which effects to query for. 502 * @return An array containing the systems current knowledge about whether the given effects 503 * are supported or not. 504 */ 505 @NonNull 506 @VibrationEffectSupport areEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)507 public int[] areEffectsSupported( 508 @NonNull @VibrationEffect.EffectType int... effectIds) { 509 VibratorInfo info = getInfo(); 510 int[] supported = new int[effectIds.length]; 511 for (int i = 0; i < effectIds.length; i++) { 512 supported[i] = info.isEffectSupported(effectIds[i]); 513 } 514 return supported; 515 } 516 517 /** 518 * Query whether the vibrator supports all of the given effects. 519 * 520 * Not all hardware reports its effect capabilities, so the system may not necessarily know 521 * whether an effect is supported or not. 522 * 523 * If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are 524 * supported by the hardware. 525 * 526 * If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the 527 * query is not supported. 528 * 529 * If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know whether 530 * all of the effects are supported. It may support any or all of the queried effects, 531 * but there's no way to programmatically know whether a {@link #vibrate} call will successfully 532 * cause a vibration. It's guaranteed, however, that none of the queried effects are 533 * definitively unsupported by the hardware. 534 * 535 * @param effectIds Which effects to query for. 536 * @return Whether all of the effects are supported. 537 */ 538 @VibrationEffectSupport areAllEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)539 public final int areAllEffectsSupported( 540 @NonNull @VibrationEffect.EffectType int... effectIds) { 541 int support = VIBRATION_EFFECT_SUPPORT_YES; 542 for (int supported : areEffectsSupported(effectIds)) { 543 if (supported == VIBRATION_EFFECT_SUPPORT_NO) { 544 return VIBRATION_EFFECT_SUPPORT_NO; 545 } else if (supported == VIBRATION_EFFECT_SUPPORT_UNKNOWN) { 546 support = VIBRATION_EFFECT_SUPPORT_UNKNOWN; 547 } 548 } 549 return support; 550 } 551 552 553 /** 554 * Query whether the vibrator supports the given primitives. 555 * 556 * The returned array will be the same length as the query array and the value at a given index 557 * will contain whether the effect at that same index in the querying array is supported or 558 * not. 559 * 560 * @param primitiveIds Which primitives to query for. 561 * @return Whether the primitives are supported. 562 */ 563 @NonNull arePrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)564 public boolean[] arePrimitivesSupported( 565 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 566 VibratorInfo info = getInfo(); 567 boolean[] supported = new boolean[primitiveIds.length]; 568 for (int i = 0; i < primitiveIds.length; i++) { 569 supported[i] = info.isPrimitiveSupported(primitiveIds[i]); 570 } 571 return supported; 572 } 573 574 /** 575 * Query whether the vibrator supports all of the given primitives. 576 * 577 * @param primitiveIds Which primitives to query for. 578 * @return Whether primitives effects are supported. 579 */ areAllPrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)580 public final boolean areAllPrimitivesSupported( 581 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 582 for (boolean supported : arePrimitivesSupported(primitiveIds)) { 583 if (!supported) { 584 return false; 585 } 586 } 587 return true; 588 } 589 590 /** 591 * Query the estimated durations of the given primitives. 592 * 593 * <p>The returned array will be the same length as the query array and the value at a given 594 * index will contain the duration in milliseconds of the effect at the same index in the 595 * querying array. 596 * 597 * <p>The duration will be positive for primitives that are supported and zero for the 598 * unsupported ones, in correspondence with {@link #arePrimitivesSupported(int...)}. 599 * 600 * @param primitiveIds Which primitives to query for. 601 * @return The duration of each primitive, with zeroes for primitives that are not supported. 602 */ 603 @NonNull getPrimitiveDurations( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)604 public int[] getPrimitiveDurations( 605 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 606 VibratorInfo info = getInfo(); 607 int[] durations = new int[primitiveIds.length]; 608 for (int i = 0; i < primitiveIds.length; i++) { 609 durations[i] = info.getPrimitiveDuration(primitiveIds[i]); 610 } 611 return durations; 612 } 613 614 /** 615 * Turn the vibrator off. 616 */ 617 @RequiresPermission(android.Manifest.permission.VIBRATE) cancel()618 public abstract void cancel(); 619 620 /** 621 * Cancel specific types of ongoing vibrations. 622 * 623 * @param usageFilter The type of vibration to be cancelled, represented as a bitwise 624 * combination of {@link VibrationAttributes.Usage} values. 625 * @hide 626 */ 627 @RequiresPermission(android.Manifest.permission.VIBRATE) cancel(int usageFilter)628 public abstract void cancel(int usageFilter); 629 630 /** 631 * Check whether the vibrator is vibrating. 632 * 633 * @return True if the hardware is vibrating, otherwise false. 634 * @hide 635 */ 636 @SystemApi 637 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) isVibrating()638 public boolean isVibrating() { 639 return false; 640 } 641 642 /** 643 * Listener for when the vibrator state has changed. 644 * 645 * @see #addVibratorStateListener 646 * @see #removeVibratorStateListener 647 * @hide 648 */ 649 @SystemApi 650 public interface OnVibratorStateChangedListener { 651 /** 652 * Called when the vibrator state has changed. 653 * 654 * @param isVibrating If true, the vibrator has started vibrating. If false, 655 * it's stopped vibrating. 656 */ onVibratorStateChanged(boolean isVibrating)657 void onVibratorStateChanged(boolean isVibrating); 658 } 659 660 /** 661 * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread. 662 * If the listener was previously added and not removed, this call will be ignored. 663 * 664 * @param listener listener to be added 665 * @hide 666 */ 667 @SystemApi 668 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) addVibratorStateListener(@onNull OnVibratorStateChangedListener listener)669 public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { 670 } 671 672 /** 673 * Adds a listener for vibrator state change. If the listener was previously added and not 674 * removed, this call will be ignored. 675 * 676 * @param listener listener to be added 677 * @param executor executor of listener 678 * @hide 679 */ 680 @SystemApi 681 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) addVibratorStateListener( @onNull @allbackExecutor Executor executor, @NonNull OnVibratorStateChangedListener listener)682 public void addVibratorStateListener( 683 @NonNull @CallbackExecutor Executor executor, 684 @NonNull OnVibratorStateChangedListener listener) { 685 } 686 687 /** 688 * Removes the listener for vibrator state changes. If the listener was not previously 689 * registered, this call will do nothing. 690 * 691 * @param listener listener to be removed 692 * @hide 693 */ 694 @SystemApi 695 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) removeVibratorStateListener(@onNull OnVibratorStateChangedListener listener)696 public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { 697 } 698 } 699