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.content.res.Resources; 31 import android.hardware.vibrator.IVibrator; 32 import android.media.AudioAttributes; 33 import android.os.vibrator.VibrationConfig; 34 import android.os.vibrator.VibratorFrequencyProfile; 35 import android.util.Log; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.util.concurrent.Executor; 40 41 /** 42 * Class that operates the vibrator on the device. 43 * <p> 44 * If your process exits, any vibration you started will stop. 45 * </p> 46 */ 47 @SystemService(Context.VIBRATOR_SERVICE) 48 public abstract class Vibrator { 49 private static final String TAG = "Vibrator"; 50 51 /** 52 * Vibration intensity: no vibrations. 53 * 54 * @hide 55 */ 56 @TestApi 57 public static final int VIBRATION_INTENSITY_OFF = 0; 58 59 /** 60 * Vibration intensity: low. 61 * 62 * @hide 63 */ 64 @TestApi 65 public static final int VIBRATION_INTENSITY_LOW = 1; 66 67 /** 68 * Vibration intensity: medium. 69 * 70 * @hide 71 */ 72 @TestApi 73 public static final int VIBRATION_INTENSITY_MEDIUM = 2; 74 75 /** 76 * Vibration intensity: high. 77 * 78 * @hide 79 */ 80 @TestApi 81 public static final int VIBRATION_INTENSITY_HIGH = 3; 82 83 /** 84 * Vibration effect support: unknown 85 * 86 * <p>The hardware doesn't report its supported effects, so we can't determine whether the 87 * effect is supported or not. 88 */ 89 public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0; 90 91 /** 92 * Vibration effect support: supported 93 * 94 * <p>This effect is supported by the underlying hardware. 95 */ 96 public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; 97 98 /** 99 * Vibration effect support: unsupported 100 * 101 * <p>This effect is <b>not</b> natively supported by the underlying hardware, although 102 * the system may still play a fallback vibration. 103 */ 104 public static final int VIBRATION_EFFECT_SUPPORT_NO = 2; 105 106 /** @hide */ 107 @Retention(RetentionPolicy.SOURCE) 108 @IntDef(prefix = {"VIBRATION_EFFECT_SUPPORT_"}, value = { 109 VIBRATION_EFFECT_SUPPORT_UNKNOWN, 110 VIBRATION_EFFECT_SUPPORT_YES, 111 VIBRATION_EFFECT_SUPPORT_NO, 112 }) 113 public @interface VibrationEffectSupport {} 114 115 /** @hide */ 116 @Retention(RetentionPolicy.SOURCE) 117 @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = { 118 VIBRATION_INTENSITY_OFF, 119 VIBRATION_INTENSITY_LOW, 120 VIBRATION_INTENSITY_MEDIUM, 121 VIBRATION_INTENSITY_HIGH 122 }) 123 public @interface VibrationIntensity { 124 } 125 126 private final String mPackageName; 127 @Nullable 128 private final Resources mResources; 129 130 // This is lazily loaded only for the few clients that need this (e. Settings app). 131 @Nullable 132 private volatile VibrationConfig mVibrationConfig; 133 134 /** 135 * @hide to prevent subclassing from outside of the framework 136 */ 137 @UnsupportedAppUsage Vibrator()138 public Vibrator() { 139 mPackageName = ActivityThread.currentPackageName(); 140 mResources = null; 141 } 142 143 /** 144 * @hide to prevent subclassing from outside of the framework 145 */ Vibrator(Context context)146 protected Vibrator(Context context) { 147 mPackageName = context.getOpPackageName(); 148 mResources = context.getResources(); 149 } 150 151 /** 152 * Get the info describing this vibrator. 153 * 154 * @hide 155 */ getInfo()156 public VibratorInfo getInfo() { 157 return VibratorInfo.EMPTY_VIBRATOR_INFO; 158 } 159 160 /** Get the static vibrator configuration from config.xml. */ getConfig()161 private VibrationConfig getConfig() { 162 if (mVibrationConfig == null) { 163 Resources resources = mResources; 164 if (resources == null) { 165 final Context ctx = ActivityThread.currentActivityThread().getSystemContext(); 166 resources = ctx != null ? ctx.getResources() : null; 167 } 168 // This might be constructed more than once, but it only loads static config data from a 169 // xml file, so it would be ok. 170 mVibrationConfig = new VibrationConfig(resources); 171 } 172 return mVibrationConfig; 173 } 174 175 /** 176 * Get the default vibration intensity for given usage. 177 * 178 * @hide 179 */ 180 @TestApi 181 @VibrationIntensity getDefaultVibrationIntensity(@ibrationAttributes.Usage int usage)182 public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) { 183 return getConfig().getDefaultVibrationIntensity(usage); 184 } 185 186 /** 187 * Whether the keyboard vibration is enabled by default. 188 * 189 * @return {@code true} if the keyboard vibration is default enabled, {@code false} otherwise. 190 * @hide 191 */ isDefaultKeyboardVibrationEnabled()192 public boolean isDefaultKeyboardVibrationEnabled() { 193 return getConfig().isDefaultKeyboardVibrationEnabled(); 194 } 195 196 /** 197 * Return the ID of this vibrator. 198 * 199 * @return A non-negative integer representing the id of the vibrator controlled by this 200 * service, or -1 this service is not attached to any physical vibrator. 201 */ getId()202 public int getId() { 203 return getInfo().getId(); 204 } 205 206 /** 207 * Check whether the hardware has a vibrator. 208 * 209 * @return True if the hardware has a vibrator, else false. 210 */ hasVibrator()211 public abstract boolean hasVibrator(); 212 213 /** 214 * Check whether the vibrator has amplitude control. 215 * 216 * @return True if the hardware can control the amplitude of the vibrations, otherwise false. 217 */ hasAmplitudeControl()218 public abstract boolean hasAmplitudeControl(); 219 220 /** 221 * Check whether the vibrator has independent frequency control. 222 * 223 * @return True if the hardware can control the frequency of the vibrations independently of 224 * the vibration amplitude, false otherwise. 225 * @hide 226 */ 227 @TestApi hasFrequencyControl()228 public boolean hasFrequencyControl() { 229 return getInfo().hasFrequencyControl(); 230 } 231 232 /** 233 * Checks whether or not the vibrator supports all components of a given {@link VibrationEffect} 234 * (i.e. the vibrator can play the given effect as intended). 235 * 236 * <p>If this method returns {@code true}, then the VibrationEffect should play as expected. 237 * If {@code false}, playing the VibrationEffect might still make a vibration, but the vibration 238 * may be significantly degraded from the intention. 239 * 240 * <p>This method aggregates the results of feature check methods such as 241 * {@link #hasAmplitudeControl}, {@link #areAllPrimitivesSupported(int...)}, etc, depending 242 * on the features that are actually used by the VibrationEffect. 243 * 244 * @param effect the {@link VibrationEffect} to check if it is supported 245 * @return {@code true} if the vibrator can play the given {@code effect} as intended, 246 * {@code false} otherwise. 247 * 248 * @hide 249 */ areVibrationFeaturesSupported(@onNull VibrationEffect effect)250 public boolean areVibrationFeaturesSupported(@NonNull VibrationEffect effect) { 251 return getInfo().areVibrationFeaturesSupported(effect); 252 } 253 254 /** 255 * Check whether the vibrator can be controlled by an external service with the 256 * {@link IExternalVibratorService}. 257 * 258 * @return True if the hardware can be controlled by an external service, otherwise false. 259 * @hide 260 */ hasExternalControl()261 public boolean hasExternalControl() { 262 return getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL); 263 } 264 265 /** 266 * Gets the resonant frequency of the vibrator, if applicable. 267 * 268 * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown, not 269 * applicable, or if this vibrator is a composite of multiple physical devices with different 270 * frequencies. 271 */ getResonantFrequency()272 public float getResonantFrequency() { 273 return getInfo().getResonantFrequencyHz(); 274 } 275 276 /** 277 * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator. 278 * 279 * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown, not 280 * applicable, or if this vibrator is a composite of multiple physical devices with different 281 * Q factors. 282 */ getQFactor()283 public float getQFactor() { 284 return getInfo().getQFactor(); 285 } 286 287 /** 288 * Gets the profile that describes the vibrator output across the supported frequency range. 289 * 290 * <p>The profile describes the relative output acceleration that the device can reach when it 291 * vibrates at different frequencies. 292 * 293 * @return The frequency profile for this vibrator, or null if the vibrator does not have 294 * frequency control. If this vibrator is a composite of multiple physical devices then this 295 * will return a profile supported in all devices, or null if the intersection is empty or not 296 * available. 297 * @hide 298 */ 299 @TestApi 300 @Nullable getFrequencyProfile()301 public VibratorFrequencyProfile getFrequencyProfile() { 302 VibratorInfo.FrequencyProfile frequencyProfile = getInfo().getFrequencyProfile(); 303 if (frequencyProfile.isEmpty()) { 304 return null; 305 } 306 return new VibratorFrequencyProfile(frequencyProfile); 307 } 308 309 /** 310 * Return the maximum amplitude the vibrator can play using the audio haptic channels. 311 * 312 * <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a 313 * positive value <code>maxAmplitude</code>, then the signals from the haptic channels of audio 314 * tracks should be in the range <code>[-maxAmplitude, maxAmplitude]</code>. 315 * 316 * @return a positive value representing the maximum absolute value the device can play signals 317 * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown. 318 * @hide 319 */ getHapticChannelMaximumAmplitude()320 public float getHapticChannelMaximumAmplitude() { 321 return getConfig().getHapticChannelMaximumAmplitude(); 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 VibrationAttributes} corresponding to the vibration. For example, 330 * specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or 331 * {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with 332 * incoming calls. May only be null when effect is null. 333 * @hide 334 */ 335 @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON) setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes)336 public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, 337 @Nullable VibrationAttributes attributes) { 338 return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes); 339 } 340 341 /** 342 * @hide 343 */ 344 @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON) setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes)345 public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, 346 @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes) { 347 Log.w(TAG, "Always-on effects aren't supported"); 348 return false; 349 } 350 351 /** 352 * Vibrate constantly for the specified period of time. 353 * 354 * <p>The app should be in the foreground for the vibration to happen.</p> 355 * 356 * @param milliseconds The number of milliseconds to vibrate. 357 * @deprecated Use {@link #vibrate(VibrationEffect)} instead. 358 */ 359 @Deprecated 360 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long milliseconds)361 public void vibrate(long milliseconds) { 362 vibrate(milliseconds, null); 363 } 364 365 /** 366 * Vibrate constantly for the specified period of time. 367 * 368 * <p>The app should be in the foreground for the vibration to happen. Background apps should 369 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 370 * 371 * @param milliseconds The number of milliseconds to vibrate. 372 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 373 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 374 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 375 * vibrations associated with incoming calls. 376 * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead. 377 */ 378 @Deprecated 379 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long milliseconds, AudioAttributes attributes)380 public void vibrate(long milliseconds, AudioAttributes attributes) { 381 try { 382 // This ignores all exceptions to stay compatible with pre-O implementations. 383 VibrationEffect effect = 384 VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE); 385 vibrate(effect, attributes); 386 } catch (IllegalArgumentException iae) { 387 Log.e(TAG, "Failed to create VibrationEffect", iae); 388 } 389 } 390 391 /** 392 * Vibrate with a given pattern. 393 * 394 * <p> 395 * Pass in an array of ints that are the durations for which to turn on or off 396 * the vibrator in milliseconds. The first value indicates the number of milliseconds 397 * to wait before turning the vibrator on. The next value indicates the number of milliseconds 398 * for which to keep the vibrator on before turning it off. Subsequent values alternate 399 * between durations in milliseconds to turn the vibrator off or to turn the vibrator on. 400 * </p><p> 401 * To cause the pattern to repeat, pass the index into the pattern array at which 402 * to start the repeat, or -1 to disable repeating. 403 * </p> 404 * 405 * <p>The app should be in the foreground for the vibration to happen.</p> 406 * 407 * @param pattern an array of longs of times for which to turn the vibrator on or off. 408 * @param repeat the index into pattern at which to repeat, or -1 if 409 * you don't want to repeat. 410 * @deprecated Use {@link #vibrate(VibrationEffect)} instead. 411 */ 412 @Deprecated 413 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long[] pattern, int repeat)414 public void vibrate(long[] pattern, int repeat) { 415 vibrate(pattern, repeat, null); 416 } 417 418 /** 419 * Vibrate with a given pattern. 420 * 421 * <p> 422 * Pass in an array of ints that are the durations for which to turn on or off 423 * the vibrator in milliseconds. The first value indicates the number of milliseconds 424 * to wait before turning the vibrator on. The next value indicates the number of milliseconds 425 * for which to keep the vibrator on before turning it off. Subsequent values alternate 426 * between durations in milliseconds to turn the vibrator off or to turn the vibrator on. 427 * </p><p> 428 * To cause the pattern to repeat, pass the index into the pattern array at which 429 * to start the repeat, or -1 to disable repeating. 430 * </p> 431 * 432 * <p>The app should be in the foreground for the vibration to happen. Background apps should 433 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 434 * 435 * @param pattern an array of longs of times for which to turn the vibrator on or off. 436 * @param repeat the index into pattern at which to repeat, or -1 if 437 * you don't want to repeat. 438 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 439 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 440 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 441 * vibrations associated with incoming calls. 442 * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead. 443 */ 444 @Deprecated 445 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long[] pattern, int repeat, AudioAttributes attributes)446 public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) { 447 // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other 448 // exceptions for compatibility purposes 449 if (repeat < -1 || repeat >= pattern.length) { 450 Log.e(TAG, "vibrate called with repeat index out of bounds" + 451 " (pattern.length=" + pattern.length + ", index=" + repeat + ")"); 452 throw new ArrayIndexOutOfBoundsException(); 453 } 454 455 try { 456 vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes); 457 } catch (IllegalArgumentException iae) { 458 Log.e(TAG, "Failed to create VibrationEffect", iae); 459 } 460 } 461 462 /** 463 * Vibrate with a given effect. 464 * 465 * <p>The app should be in the foreground for the vibration to happen.</p> 466 * 467 * @param vibe {@link VibrationEffect} describing the vibration to be performed. 468 */ 469 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(VibrationEffect vibe)470 public void vibrate(VibrationEffect vibe) { 471 vibrate(vibe, new VibrationAttributes.Builder().build()); 472 } 473 474 /** 475 * Vibrate with a given effect. 476 * 477 * <p>The app should be in the foreground for the vibration to happen. Background apps should 478 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 479 * 480 * @param vibe {@link VibrationEffect} describing the vibration to be performed. 481 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 482 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 483 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 484 * vibrations associated with incoming calls. 485 * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead. 486 */ 487 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(VibrationEffect vibe, AudioAttributes attributes)488 public void vibrate(VibrationEffect vibe, AudioAttributes attributes) { 489 vibrate(vibe, 490 attributes == null 491 ? new VibrationAttributes.Builder().build() 492 : new VibrationAttributes.Builder(attributes).build()); 493 } 494 495 /** 496 * Vibrate with a given effect. 497 * 498 * <p>The app should be in the foreground for the vibration to happen. Background apps should 499 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 500 * 501 * @param vibe {@link VibrationEffect} describing the vibration to be performed. 502 * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example, 503 * specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or 504 * {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with 505 * incoming calls. 506 */ 507 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(@onNull VibrationEffect vibe, @NonNull VibrationAttributes attributes)508 public void vibrate(@NonNull VibrationEffect vibe, @NonNull VibrationAttributes attributes) { 509 vibrate(Process.myUid(), mPackageName, vibe, null, attributes); 510 } 511 512 /** 513 * Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the 514 * caller to specify the vibration is owned by someone else and set a reason for vibration. 515 * 516 * @hide 517 */ 518 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, String reason, @NonNull VibrationAttributes attributes)519 public abstract void vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, 520 String reason, @NonNull VibrationAttributes attributes); 521 522 /** 523 * Performs a haptic feedback. 524 * 525 * <p>A haptic feedback is a short vibration feedback. The type of feedback is identified via 526 * the {@code constant}, which should be one of the effect constants provided in 527 * {@link HapticFeedbackConstants}. The haptic feedback provided for a given effect ID is 528 * consistent across all usages on the same device. 529 * 530 * @param constant the ID for the haptic feedback. This should be one of the constants defined 531 * in {@link HapticFeedbackConstants}. 532 * @param always {@code true} if the haptic feedback should be played regardless of the user 533 * vibration intensity settings applicable to the corresponding vibration. 534 * {@code false} if the vibration for the haptic feedback should respect the applicable 535 * vibration intensity settings. 536 * @param reason the reason for this haptic feedback. 537 * @param fromIme the haptic feedback is performed from an IME. 538 * 539 * @hide 540 */ performHapticFeedback(int constant, boolean always, String reason, boolean fromIme)541 public void performHapticFeedback(int constant, boolean always, String reason, 542 boolean fromIme) { 543 Log.w(TAG, "performHapticFeedback is not supported"); 544 } 545 546 /** 547 * Query whether the vibrator natively supports the given effects. 548 * 549 * <p>If an effect is not supported, the system may still automatically fall back to playing 550 * a simpler vibration instead, which is not optimised for the specific device. This includes 551 * the unknown case, which can't be determined in advance, that will dynamically attempt to 552 * fall back if the optimised effect fails to play. 553 * 554 * <p>The returned array will be the same length as the query array and the value at a given 555 * index will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index 556 * in the querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't 557 * supported, or {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether 558 * it's supported or not, as some hardware doesn't report its effect capabilities. 559 * 560 * <p>Use {@link #areAllEffectsSupported(int...)} to get a single combined result, 561 * or for convenience when querying exactly one effect. 562 * 563 * @param effectIds Which effects to query for. 564 * @return An array containing the systems current knowledge about whether the given effects 565 * are natively supported by the device, or not. 566 */ 567 @NonNull 568 @VibrationEffectSupport areEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)569 public int[] areEffectsSupported( 570 @NonNull @VibrationEffect.EffectType int... effectIds) { 571 VibratorInfo info = getInfo(); 572 int[] supported = new int[effectIds.length]; 573 for (int i = 0; i < effectIds.length; i++) { 574 supported[i] = info.isEffectSupported(effectIds[i]); 575 } 576 return supported; 577 } 578 579 /** 580 * Query whether the vibrator supports all the given effects. If no argument is provided this 581 * method will always return {@link #VIBRATION_EFFECT_SUPPORT_YES}. 582 * 583 * <p>If an effect is not supported, the system may still automatically fall back to a simpler 584 * vibration instead, which is not optimised for the specific device, however vibration isn't 585 * guaranteed in this case. 586 * 587 * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are 588 * supported by the hardware. 589 * 590 * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the 591 * query is not supported, and using them may fall back to an un-optimized vibration or no 592 * vibration. 593 * 594 * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know 595 * whether all the effects are supported. It may support any or all of the queried effects, 596 * but there's no way to programmatically know whether a {@link #vibrate} call will successfully 597 * cause a vibration. It's guaranteed, however, that none of the queried effects are 598 * definitively unsupported by the hardware. 599 * 600 * <p>Use {@link #areEffectsSupported(int...)} to get individual results for each effect. 601 * 602 * @param effectIds Which effects to query for. 603 * @return Whether all specified effects are natively supported by the device. Empty query 604 * defaults to {@link #VIBRATION_EFFECT_SUPPORT_YES}. 605 */ 606 @VibrationEffectSupport areAllEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)607 public final int areAllEffectsSupported( 608 @NonNull @VibrationEffect.EffectType int... effectIds) { 609 VibratorInfo info = getInfo(); 610 int allSupported = VIBRATION_EFFECT_SUPPORT_YES; 611 for (int effectId : effectIds) { 612 switch (info.isEffectSupported(effectId)) { 613 case VIBRATION_EFFECT_SUPPORT_NO: 614 return VIBRATION_EFFECT_SUPPORT_NO; 615 case VIBRATION_EFFECT_SUPPORT_YES: 616 continue; 617 default: // VIBRATION_EFFECT_SUPPORT_UNKNOWN 618 allSupported = VIBRATION_EFFECT_SUPPORT_UNKNOWN; 619 break; 620 } 621 } 622 return allSupported; 623 } 624 625 /** 626 * Query whether the vibrator supports the given primitives. 627 * 628 * The returned array will be the same length as the query array and the value at a given index 629 * will contain whether the effect at that same index in the querying array is supported or 630 * not. 631 * 632 * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if 633 * it is played. 634 * 635 * <p>Use {@link #areAllPrimitivesSupported(int...)} to get a single combined result, 636 * or for convenience when querying exactly one primitive. 637 * 638 * @param primitiveIds Which primitives to query for. 639 * @return Whether the primitives are supported. 640 */ 641 @NonNull arePrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)642 public boolean[] arePrimitivesSupported( 643 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 644 VibratorInfo info = getInfo(); 645 boolean[] supported = new boolean[primitiveIds.length]; 646 for (int i = 0; i < primitiveIds.length; i++) { 647 supported[i] = info.isPrimitiveSupported(primitiveIds[i]); 648 } 649 return supported; 650 } 651 652 /** 653 * Query whether the vibrator supports all of the given primitives. If no argument is provided 654 * this method will always return {@code true}. 655 * 656 * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if 657 * it is played. 658 * 659 * <p>Use {@link #arePrimitivesSupported(int...)} to get individual results for each primitive. 660 * 661 * @param primitiveIds Which primitives to query for. 662 * @return Whether all specified primitives are supported. Empty query defaults to {@code true}. 663 */ areAllPrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)664 public final boolean areAllPrimitivesSupported( 665 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 666 VibratorInfo info = getInfo(); 667 for (int primitiveId : primitiveIds) { 668 if (!info.isPrimitiveSupported(primitiveId)) { 669 return false; 670 } 671 } 672 return true; 673 } 674 675 /** 676 * Query the estimated durations of the given primitives. 677 * 678 * <p>The returned array will be the same length as the query array and the value at a given 679 * index will contain the duration in milliseconds of the effect at the same index in the 680 * querying array. 681 * 682 * <p>The duration will be positive for primitives that are supported and zero for the 683 * unsupported ones, in correspondence with {@link #arePrimitivesSupported(int...)}. 684 * 685 * @param primitiveIds Which primitives to query for. 686 * @return The duration of each primitive, with zeroes for primitives that are not supported. 687 */ 688 @NonNull getPrimitiveDurations( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)689 public int[] getPrimitiveDurations( 690 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 691 VibratorInfo info = getInfo(); 692 int[] durations = new int[primitiveIds.length]; 693 for (int i = 0; i < primitiveIds.length; i++) { 694 durations[i] = info.getPrimitiveDuration(primitiveIds[i]); 695 } 696 return durations; 697 } 698 699 /** 700 * Turn the vibrator off. 701 */ 702 @RequiresPermission(android.Manifest.permission.VIBRATE) cancel()703 public abstract void cancel(); 704 705 /** 706 * Cancel specific types of ongoing vibrations. 707 * 708 * @param usageFilter The type of vibration to be cancelled, represented as a bitwise 709 * combination of {@link VibrationAttributes.Usage} values. 710 * @hide 711 */ 712 @RequiresPermission(android.Manifest.permission.VIBRATE) cancel(int usageFilter)713 public abstract void cancel(int usageFilter); 714 715 /** 716 * Check whether the vibrator is vibrating. 717 * 718 * @return True if the hardware is vibrating, otherwise false. 719 * @hide 720 */ 721 @SystemApi 722 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) isVibrating()723 public boolean isVibrating() { 724 return false; 725 } 726 727 /** 728 * Listener for when the vibrator state has changed. 729 * 730 * @see #addVibratorStateListener 731 * @see #removeVibratorStateListener 732 * @hide 733 */ 734 @SystemApi 735 public interface OnVibratorStateChangedListener { 736 /** 737 * Called when the vibrator state has changed. 738 * 739 * @param isVibrating If true, the vibrator has started vibrating. If false, 740 * it's stopped vibrating. 741 */ onVibratorStateChanged(boolean isVibrating)742 void onVibratorStateChanged(boolean isVibrating); 743 } 744 745 /** 746 * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread. 747 * If the listener was previously added and not removed, this call will be ignored. 748 * 749 * @param listener listener to be added 750 * @hide 751 */ 752 @SystemApi 753 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) addVibratorStateListener(@onNull OnVibratorStateChangedListener listener)754 public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { 755 } 756 757 /** 758 * Adds a listener for vibrator state change. If the listener was previously added and not 759 * removed, this call will be ignored. 760 * 761 * @param listener listener to be added 762 * @param executor executor of listener 763 * @hide 764 */ 765 @SystemApi 766 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) addVibratorStateListener( @onNull @allbackExecutor Executor executor, @NonNull OnVibratorStateChangedListener listener)767 public void addVibratorStateListener( 768 @NonNull @CallbackExecutor Executor executor, 769 @NonNull OnVibratorStateChangedListener listener) { 770 } 771 772 /** 773 * Removes the listener for vibrator state changes. If the listener was not previously 774 * registered, this call will do nothing. 775 * 776 * @param listener listener to be removed 777 * @hide 778 */ 779 @SystemApi 780 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) removeVibratorStateListener(@onNull OnVibratorStateChangedListener listener)781 public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { 782 } 783 } 784