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