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 protected 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 * Return the ID of this vibrator. 188 * 189 * @return A non-negative integer representing the id of the vibrator controlled by this 190 * service, or -1 this service is not attached to any physical vibrator. 191 */ getId()192 public int getId() { 193 return getInfo().getId(); 194 } 195 196 /** 197 * Check whether the hardware has a vibrator. 198 * 199 * @return True if the hardware has a vibrator, else false. 200 */ hasVibrator()201 public abstract boolean hasVibrator(); 202 203 /** 204 * Check whether the vibrator has amplitude control. 205 * 206 * @return True if the hardware can control the amplitude of the vibrations, otherwise false. 207 */ hasAmplitudeControl()208 public abstract boolean hasAmplitudeControl(); 209 210 /** 211 * Check whether the vibrator has independent frequency control. 212 * 213 * @return True if the hardware can control the frequency of the vibrations independently of 214 * the vibration amplitude, false otherwise. 215 * @hide 216 */ 217 @TestApi hasFrequencyControl()218 public boolean hasFrequencyControl() { 219 // We currently can only control frequency of the vibration using the compose PWLE method. 220 return getInfo().hasCapability( 221 IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS); 222 } 223 224 /** 225 * Checks whether or not the vibrator supports all components of a given {@link VibrationEffect} 226 * (i.e. the vibrator can play the given effect as intended). 227 * 228 * <p>If this method returns {@code true}, then the VibrationEffect should play as expected. 229 * If {@code false}, playing the VibrationEffect might still make a vibration, but the vibration 230 * may be significantly degraded from the intention. 231 * 232 * <p>This method aggregates the results of feature check methods such as 233 * {@link #hasAmplitudeControl}, {@link #areAllPrimitivesSupported(int...)}, etc, depending 234 * on the features that are actually used by the VibrationEffect. 235 * 236 * @param effect the {@link VibrationEffect} to check if it is supported 237 * @return {@code true} if the vibrator can play the given {@code effect} as intended, 238 * {@code false} otherwise. 239 * 240 * @hide 241 */ areVibrationFeaturesSupported(@onNull VibrationEffect effect)242 public boolean areVibrationFeaturesSupported(@NonNull VibrationEffect effect) { 243 return effect.areVibrationFeaturesSupported(this); 244 } 245 246 /** 247 * Check whether the vibrator can be controlled by an external service with the 248 * {@link IExternalVibratorService}. 249 * 250 * @return True if the hardware can be controlled by an external service, otherwise false. 251 * @hide 252 */ hasExternalControl()253 public boolean hasExternalControl() { 254 return getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL); 255 } 256 257 /** 258 * Gets the resonant frequency of the vibrator, if applicable. 259 * 260 * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown, not 261 * applicable, or if this vibrator is a composite of multiple physical devices with different 262 * frequencies. 263 */ getResonantFrequency()264 public float getResonantFrequency() { 265 return getInfo().getResonantFrequencyHz(); 266 } 267 268 /** 269 * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator. 270 * 271 * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown, not 272 * applicable, or if this vibrator is a composite of multiple physical devices with different 273 * Q factors. 274 */ getQFactor()275 public float getQFactor() { 276 return getInfo().getQFactor(); 277 } 278 279 /** 280 * Gets the profile that describes the vibrator output across the supported frequency range. 281 * 282 * <p>The profile describes the relative output acceleration that the device can reach when it 283 * vibrates at different frequencies. 284 * 285 * @return The frequency profile for this vibrator, or null if the vibrator does not have 286 * frequency control. If this vibrator is a composite of multiple physical devices then this 287 * will return a profile supported in all devices, or null if the intersection is empty or not 288 * available. 289 * @hide 290 */ 291 @TestApi 292 @Nullable getFrequencyProfile()293 public VibratorFrequencyProfile getFrequencyProfile() { 294 VibratorInfo.FrequencyProfile frequencyProfile = getInfo().getFrequencyProfile(); 295 if (frequencyProfile.isEmpty()) { 296 return null; 297 } 298 return new VibratorFrequencyProfile(frequencyProfile); 299 } 300 301 /** 302 * Return the maximum amplitude the vibrator can play using the audio haptic channels. 303 * 304 * <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a 305 * positive value <code>maxAmplitude</code>, then the signals from the haptic channels of audio 306 * tracks should be in the range <code>[-maxAmplitude, maxAmplitude]</code>. 307 * 308 * @return a positive value representing the maximum absolute value the device can play signals 309 * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown. 310 * @hide 311 */ getHapticChannelMaximumAmplitude()312 public float getHapticChannelMaximumAmplitude() { 313 return getConfig().getHapticChannelMaximumAmplitude(); 314 } 315 316 /** 317 * Configure an always-on haptics effect. 318 * 319 * @param alwaysOnId The board-specific always-on ID to configure. 320 * @param effect Vibration effect to assign to always-on id. Passing null will disable it. 321 * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example, 322 * specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or 323 * {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with 324 * incoming calls. May only be null when effect is null. 325 * @hide 326 */ 327 @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON) setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes)328 public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect, 329 @Nullable VibrationAttributes attributes) { 330 return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes); 331 } 332 333 /** 334 * @hide 335 */ 336 @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON) setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes)337 public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, 338 @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes) { 339 Log.w(TAG, "Always-on effects aren't supported"); 340 return false; 341 } 342 343 /** 344 * Vibrate constantly for the specified period of time. 345 * 346 * <p>The app should be in the foreground for the vibration to happen.</p> 347 * 348 * @param milliseconds The number of milliseconds to vibrate. 349 * @deprecated Use {@link #vibrate(VibrationEffect)} instead. 350 */ 351 @Deprecated 352 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long milliseconds)353 public void vibrate(long milliseconds) { 354 vibrate(milliseconds, null); 355 } 356 357 /** 358 * Vibrate constantly for the specified period of time. 359 * 360 * <p>The app should be in the foreground for the vibration to happen. Background apps should 361 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 362 * 363 * @param milliseconds The number of milliseconds to vibrate. 364 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 365 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 366 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 367 * vibrations associated with incoming calls. 368 * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead. 369 */ 370 @Deprecated 371 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long milliseconds, AudioAttributes attributes)372 public void vibrate(long milliseconds, AudioAttributes attributes) { 373 try { 374 // This ignores all exceptions to stay compatible with pre-O implementations. 375 VibrationEffect effect = 376 VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE); 377 vibrate(effect, attributes); 378 } catch (IllegalArgumentException iae) { 379 Log.e(TAG, "Failed to create VibrationEffect", iae); 380 } 381 } 382 383 /** 384 * Vibrate with a given pattern. 385 * 386 * <p> 387 * Pass in an array of ints that are the durations for which to turn on or off 388 * the vibrator in milliseconds. The first value indicates the number of milliseconds 389 * to wait before turning the vibrator on. The next value indicates the number of milliseconds 390 * for which to keep the vibrator on before turning it off. Subsequent values alternate 391 * between durations in milliseconds to turn the vibrator off or to turn the vibrator on. 392 * </p><p> 393 * To cause the pattern to repeat, pass the index into the pattern array at which 394 * to start the repeat, or -1 to disable repeating. 395 * </p> 396 * 397 * <p>The app should be in the foreground for the vibration to happen.</p> 398 * 399 * @param pattern an array of longs of times for which to turn the vibrator on or off. 400 * @param repeat the index into pattern at which to repeat, or -1 if 401 * you don't want to repeat. 402 * @deprecated Use {@link #vibrate(VibrationEffect)} instead. 403 */ 404 @Deprecated 405 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long[] pattern, int repeat)406 public void vibrate(long[] pattern, int repeat) { 407 vibrate(pattern, repeat, null); 408 } 409 410 /** 411 * Vibrate with a given pattern. 412 * 413 * <p> 414 * Pass in an array of ints that are the durations for which to turn on or off 415 * the vibrator in milliseconds. The first value indicates the number of milliseconds 416 * to wait before turning the vibrator on. The next value indicates the number of milliseconds 417 * for which to keep the vibrator on before turning it off. Subsequent values alternate 418 * between durations in milliseconds to turn the vibrator off or to turn the vibrator on. 419 * </p><p> 420 * To cause the pattern to repeat, pass the index into the pattern array at which 421 * to start the repeat, or -1 to disable repeating. 422 * </p> 423 * 424 * <p>The app should be in the foreground for the vibration to happen. Background apps should 425 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 426 * 427 * @param pattern an array of longs of times for which to turn the vibrator on or off. 428 * @param repeat the index into pattern at which to repeat, or -1 if 429 * you don't want to repeat. 430 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 431 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 432 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 433 * vibrations associated with incoming calls. 434 * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead. 435 */ 436 @Deprecated 437 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(long[] pattern, int repeat, AudioAttributes attributes)438 public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) { 439 // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other 440 // exceptions for compatibility purposes 441 if (repeat < -1 || repeat >= pattern.length) { 442 Log.e(TAG, "vibrate called with repeat index out of bounds" + 443 " (pattern.length=" + pattern.length + ", index=" + repeat + ")"); 444 throw new ArrayIndexOutOfBoundsException(); 445 } 446 447 try { 448 vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes); 449 } catch (IllegalArgumentException iae) { 450 Log.e(TAG, "Failed to create VibrationEffect", iae); 451 } 452 } 453 454 /** 455 * Vibrate with a given effect. 456 * 457 * <p>The app should be in the foreground for the vibration to happen.</p> 458 * 459 * @param vibe {@link VibrationEffect} describing the vibration to be performed. 460 */ 461 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(VibrationEffect vibe)462 public void vibrate(VibrationEffect vibe) { 463 vibrate(vibe, new VibrationAttributes.Builder().build()); 464 } 465 466 /** 467 * Vibrate with a given effect. 468 * 469 * <p>The app should be in the foreground for the vibration to happen. Background apps should 470 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 471 * 472 * @param vibe {@link VibrationEffect} describing the vibration to be performed. 473 * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, 474 * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or 475 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for 476 * vibrations associated with incoming calls. 477 * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead. 478 */ 479 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(VibrationEffect vibe, AudioAttributes attributes)480 public void vibrate(VibrationEffect vibe, AudioAttributes attributes) { 481 vibrate(vibe, 482 attributes == null 483 ? new VibrationAttributes.Builder().build() 484 : new VibrationAttributes.Builder(attributes).build()); 485 } 486 487 /** 488 * Vibrate with a given effect. 489 * 490 * <p>The app should be in the foreground for the vibration to happen. Background apps should 491 * specify a ringtone, notification or alarm usage in order to vibrate.</p> 492 * 493 * @param vibe {@link VibrationEffect} describing the vibration to be performed. 494 * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example, 495 * specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or 496 * {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with 497 * incoming calls. 498 */ 499 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(@onNull VibrationEffect vibe, @NonNull VibrationAttributes attributes)500 public void vibrate(@NonNull VibrationEffect vibe, @NonNull VibrationAttributes attributes) { 501 vibrate(Process.myUid(), mPackageName, vibe, null, attributes); 502 } 503 504 /** 505 * Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the 506 * caller to specify the vibration is owned by someone else and set a reason for vibration. 507 * 508 * @hide 509 */ 510 @RequiresPermission(android.Manifest.permission.VIBRATE) vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, String reason, @NonNull VibrationAttributes attributes)511 public abstract void vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe, 512 String reason, @NonNull VibrationAttributes attributes); 513 514 /** 515 * Query whether the vibrator natively supports the given effects. 516 * 517 * <p>If an effect is not supported, the system may still automatically fall back to playing 518 * a simpler vibration instead, which is not optimised for the specific device. This includes 519 * the unknown case, which can't be determined in advance, that will dynamically attempt to 520 * fall back if the optimised effect fails to play. 521 * 522 * <p>The returned array will be the same length as the query array and the value at a given 523 * index will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index 524 * in the querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't 525 * supported, or {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether 526 * it's supported or not, as some hardware doesn't report its effect capabilities. 527 * 528 * <p>Use {@link #areAllEffectsSupported(int...)} to get a single combined result, 529 * or for convenience when querying exactly one effect. 530 * 531 * @param effectIds Which effects to query for. 532 * @return An array containing the systems current knowledge about whether the given effects 533 * are natively supported by the device, or not. 534 */ 535 @NonNull 536 @VibrationEffectSupport areEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)537 public int[] areEffectsSupported( 538 @NonNull @VibrationEffect.EffectType int... effectIds) { 539 VibratorInfo info = getInfo(); 540 int[] supported = new int[effectIds.length]; 541 for (int i = 0; i < effectIds.length; i++) { 542 supported[i] = info.isEffectSupported(effectIds[i]); 543 } 544 return supported; 545 } 546 547 /** 548 * Query whether the vibrator supports all the given effects. If no argument is provided this 549 * method will always return {@link #VIBRATION_EFFECT_SUPPORT_YES}. 550 * 551 * <p>If an effect is not supported, the system may still automatically fall back to a simpler 552 * vibration instead, which is not optimised for the specific device, however vibration isn't 553 * guaranteed in this case. 554 * 555 * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are 556 * supported by the hardware. 557 * 558 * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the 559 * query is not supported, and using them may fall back to an un-optimized vibration or no 560 * vibration. 561 * 562 * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know 563 * whether all the effects are supported. It may support any or all of the queried effects, 564 * but there's no way to programmatically know whether a {@link #vibrate} call will successfully 565 * cause a vibration. It's guaranteed, however, that none of the queried effects are 566 * definitively unsupported by the hardware. 567 * 568 * <p>Use {@link #areEffectsSupported(int...)} to get individual results for each effect. 569 * 570 * @param effectIds Which effects to query for. 571 * @return Whether all specified effects are natively supported by the device. Empty query 572 * defaults to {@link #VIBRATION_EFFECT_SUPPORT_YES}. 573 */ 574 @VibrationEffectSupport areAllEffectsSupported( @onNull @ibrationEffect.EffectType int... effectIds)575 public final int areAllEffectsSupported( 576 @NonNull @VibrationEffect.EffectType int... effectIds) { 577 VibratorInfo info = getInfo(); 578 int allSupported = VIBRATION_EFFECT_SUPPORT_YES; 579 for (int effectId : effectIds) { 580 switch (info.isEffectSupported(effectId)) { 581 case VIBRATION_EFFECT_SUPPORT_NO: 582 return VIBRATION_EFFECT_SUPPORT_NO; 583 case VIBRATION_EFFECT_SUPPORT_YES: 584 continue; 585 default: // VIBRATION_EFFECT_SUPPORT_UNKNOWN 586 allSupported = VIBRATION_EFFECT_SUPPORT_UNKNOWN; 587 break; 588 } 589 } 590 return allSupported; 591 } 592 593 /** 594 * Query whether the vibrator supports the given primitives. 595 * 596 * The returned array will be the same length as the query array and the value at a given index 597 * will contain whether the effect at that same index in the querying array is supported or 598 * not. 599 * 600 * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if 601 * it is played. 602 * 603 * <p>Use {@link #areAllPrimitivesSupported(int...)} to get a single combined result, 604 * or for convenience when querying exactly one primitive. 605 * 606 * @param primitiveIds Which primitives to query for. 607 * @return Whether the primitives are supported. 608 */ 609 @NonNull arePrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)610 public boolean[] arePrimitivesSupported( 611 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 612 VibratorInfo info = getInfo(); 613 boolean[] supported = new boolean[primitiveIds.length]; 614 for (int i = 0; i < primitiveIds.length; i++) { 615 supported[i] = info.isPrimitiveSupported(primitiveIds[i]); 616 } 617 return supported; 618 } 619 620 /** 621 * Query whether the vibrator supports all of the given primitives. If no argument is provided 622 * this method will always return {@code true}. 623 * 624 * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if 625 * it is played. 626 * 627 * <p>Use {@link #arePrimitivesSupported(int...)} to get individual results for each primitive. 628 * 629 * @param primitiveIds Which primitives to query for. 630 * @return Whether all specified primitives are supported. Empty query defaults to {@code true}. 631 */ areAllPrimitivesSupported( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)632 public final boolean areAllPrimitivesSupported( 633 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 634 VibratorInfo info = getInfo(); 635 for (int primitiveId : primitiveIds) { 636 if (!info.isPrimitiveSupported(primitiveId)) { 637 return false; 638 } 639 } 640 return true; 641 } 642 643 /** 644 * Query the estimated durations of the given primitives. 645 * 646 * <p>The returned array will be the same length as the query array and the value at a given 647 * index will contain the duration in milliseconds of the effect at the same index in the 648 * querying array. 649 * 650 * <p>The duration will be positive for primitives that are supported and zero for the 651 * unsupported ones, in correspondence with {@link #arePrimitivesSupported(int...)}. 652 * 653 * @param primitiveIds Which primitives to query for. 654 * @return The duration of each primitive, with zeroes for primitives that are not supported. 655 */ 656 @NonNull getPrimitiveDurations( @onNull @ibrationEffect.Composition.PrimitiveType int... primitiveIds)657 public int[] getPrimitiveDurations( 658 @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { 659 VibratorInfo info = getInfo(); 660 int[] durations = new int[primitiveIds.length]; 661 for (int i = 0; i < primitiveIds.length; i++) { 662 durations[i] = info.getPrimitiveDuration(primitiveIds[i]); 663 } 664 return durations; 665 } 666 667 /** 668 * Turn the vibrator off. 669 */ 670 @RequiresPermission(android.Manifest.permission.VIBRATE) cancel()671 public abstract void cancel(); 672 673 /** 674 * Cancel specific types of ongoing vibrations. 675 * 676 * @param usageFilter The type of vibration to be cancelled, represented as a bitwise 677 * combination of {@link VibrationAttributes.Usage} values. 678 * @hide 679 */ 680 @RequiresPermission(android.Manifest.permission.VIBRATE) cancel(int usageFilter)681 public abstract void cancel(int usageFilter); 682 683 /** 684 * Check whether the vibrator is vibrating. 685 * 686 * @return True if the hardware is vibrating, otherwise false. 687 * @hide 688 */ 689 @SystemApi 690 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) isVibrating()691 public boolean isVibrating() { 692 return false; 693 } 694 695 /** 696 * Listener for when the vibrator state has changed. 697 * 698 * @see #addVibratorStateListener 699 * @see #removeVibratorStateListener 700 * @hide 701 */ 702 @SystemApi 703 public interface OnVibratorStateChangedListener { 704 /** 705 * Called when the vibrator state has changed. 706 * 707 * @param isVibrating If true, the vibrator has started vibrating. If false, 708 * it's stopped vibrating. 709 */ onVibratorStateChanged(boolean isVibrating)710 void onVibratorStateChanged(boolean isVibrating); 711 } 712 713 /** 714 * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread. 715 * If the listener was previously added and not removed, this call will be ignored. 716 * 717 * @param listener listener to be added 718 * @hide 719 */ 720 @SystemApi 721 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) addVibratorStateListener(@onNull OnVibratorStateChangedListener listener)722 public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { 723 } 724 725 /** 726 * Adds a listener for vibrator state change. If the listener was previously added and not 727 * removed, this call will be ignored. 728 * 729 * @param listener listener to be added 730 * @param executor executor of listener 731 * @hide 732 */ 733 @SystemApi 734 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) addVibratorStateListener( @onNull @allbackExecutor Executor executor, @NonNull OnVibratorStateChangedListener listener)735 public void addVibratorStateListener( 736 @NonNull @CallbackExecutor Executor executor, 737 @NonNull OnVibratorStateChangedListener listener) { 738 } 739 740 /** 741 * Removes the listener for vibrator state changes. If the listener was not previously 742 * registered, this call will do nothing. 743 * 744 * @param listener listener to be removed 745 * @hide 746 */ 747 @SystemApi 748 @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) removeVibratorStateListener(@onNull OnVibratorStateChangedListener listener)749 public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { 750 } 751 } 752