/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.media.AudioAttributes; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Encapsulates a collection of attributes describing information about a vibration. */ public final class VibrationAttributes implements Parcelable { private static final String TAG = "VibrationAttributes"; /** @hide */ @IntDef(prefix = { "USAGE_CLASS_" }, value = { USAGE_CLASS_UNKNOWN, USAGE_CLASS_ALARM, USAGE_CLASS_FEEDBACK, USAGE_CLASS_MEDIA, }) @Retention(RetentionPolicy.SOURCE) public @interface UsageClass {} /** @hide */ @IntDef(prefix = { "USAGE_" }, value = { USAGE_UNKNOWN, USAGE_ACCESSIBILITY, USAGE_ALARM, USAGE_COMMUNICATION_REQUEST, USAGE_HARDWARE_FEEDBACK, USAGE_MEDIA, USAGE_NOTIFICATION, USAGE_PHYSICAL_EMULATION, USAGE_RINGTONE, USAGE_TOUCH, }) @Retention(RetentionPolicy.SOURCE) public @interface Usage {} /** * Vibration usage filter value to match all usages. * @hide */ public static final int USAGE_FILTER_MATCH_ALL = -1; /** * Vibration usage class value to use when the vibration usage class is unknown. */ public static final int USAGE_CLASS_UNKNOWN = 0x0; /** * Vibration usage class value to use when the vibration is initiated to catch user's * attention, such as alarm, ringtone, and notification vibrations. */ public static final int USAGE_CLASS_ALARM = 0x1; /** * Vibration usage class value to use when the vibration is initiated as a response to user's * actions, such as emulation of physical effects, and texting feedback vibration. */ public static final int USAGE_CLASS_FEEDBACK = 0x2; /** * Vibration usage class value to use when the vibration is part of media, such as music, movie, * soundtrack, game or animations. */ public static final int USAGE_CLASS_MEDIA = 0x3; /** * Mask for vibration usage class value. */ public static final int USAGE_CLASS_MASK = 0xF; /** * Usage value to use when usage is unknown. */ public static final int USAGE_UNKNOWN = 0x0 | USAGE_CLASS_UNKNOWN; /** * Usage value to use for alarm vibrations. */ public static final int USAGE_ALARM = 0x10 | USAGE_CLASS_ALARM; /** * Usage value to use for ringtone vibrations. */ public static final int USAGE_RINGTONE = 0x20 | USAGE_CLASS_ALARM; /** * Usage value to use for notification vibrations. */ public static final int USAGE_NOTIFICATION = 0x30 | USAGE_CLASS_ALARM; /** * Usage value to use for vibrations which mean a request to enter/end a * communication with the user, such as a voice prompt. */ public static final int USAGE_COMMUNICATION_REQUEST = 0x40 | USAGE_CLASS_ALARM; /** * Usage value to use for touch vibrations. * *
Most typical haptic feedback should be classed as touch feedback. Examples * include vibrations for tap, long press, drag and scroll. */ public static final int USAGE_TOUCH = 0x10 | USAGE_CLASS_FEEDBACK; /** * Usage value to use for vibrations which emulate physical hardware reactions, * such as edge squeeze. * *
Note that normal screen-touch feedback "click" effects would typically be * classed as {@link #USAGE_TOUCH}, and that on-screen "physical" animations * like bouncing would be {@link #USAGE_MEDIA}. */ public static final int USAGE_PHYSICAL_EMULATION = 0x20 | USAGE_CLASS_FEEDBACK; /** * Usage value to use for vibrations which provide a feedback for hardware * component interaction, such as a fingerprint sensor. */ public static final int USAGE_HARDWARE_FEEDBACK = 0x30 | USAGE_CLASS_FEEDBACK; /** * Usage value to use for accessibility vibrations, such as with a screen reader. */ public static final int USAGE_ACCESSIBILITY = 0x40 | USAGE_CLASS_FEEDBACK; /** * Usage value to use for media vibrations, such as music, movie, soundtrack, animations, games, * or any interactive media that isn't for touch feedback specifically. */ public static final int USAGE_MEDIA = 0x10 | USAGE_CLASS_MEDIA; /** * @hide */ @IntDef(prefix = { "FLAG_" }, flag = true, value = { FLAG_BYPASS_INTERRUPTION_POLICY, FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF, FLAG_INVALIDATE_SETTINGS_CACHE, FLAG_PIPELINED_EFFECT }) @Retention(RetentionPolicy.SOURCE) public @interface Flag{} /** * Flag requesting vibration effect to be played even under limited interruptions. * *
Only privileged apps can ignore user settings that limit interruptions, and this * flag will be ignored otherwise. */ public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 1; /** * Flag requesting vibration effect to be played even when user settings are disabling it. * *
Flag introduced to represent * {@link android.view.HapticFeedbackConstants#FLAG_IGNORE_GLOBAL_SETTING} and * {@link AudioAttributes#FLAG_BYPASS_MUTE}. * * @hide */ public static final int FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF = 1 << 1; /** * Flag requesting vibration effect to be played with fresh user settings values. * *
This flag is not protected by any permission, but vibrations that use it require an extra * query of user vibration intensity settings, ringer mode and other controls that affect the * vibration effect playback, which can increase the latency for the overall request. * *
This is intended to be used on scenarios where the user settings might have changed * recently, and needs to be applied to this vibration, like settings controllers that preview * newly set intensities to the user. * * @hide */ public static final int FLAG_INVALIDATE_SETTINGS_CACHE = 1 << 2; /** * Flag requesting that this vibration effect be pipelined with other vibration effects from the * same package that also carry this flag. * *
Pipelined effects won't cancel a running pipelined effect, but will instead play after
* it completes. However, only one pipelined effect can be waiting at a time - so if an effect
* is already waiting (but not running), it will be cancelled in favor of a newer one.
*
* @hide
*/
public static final int FLAG_PIPELINED_EFFECT = 1 << 3;
/**
* All flags supported by vibrator service, update it when adding new flag.
* @hide
*/
public static final int FLAG_ALL_SUPPORTED =
FLAG_BYPASS_INTERRUPTION_POLICY | FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF
| FLAG_INVALIDATE_SETTINGS_CACHE | FLAG_PIPELINED_EFFECT;
/** Creates a new {@link VibrationAttributes} instance with given usage. */
public static @NonNull VibrationAttributes createForUsage(@Usage int usage) {
return new VibrationAttributes.Builder().setUsage(usage).build();
}
private final int mUsage;
private final int mFlags;
private final int mOriginalAudioUsage;
private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage,
@Flag int flags) {
mUsage = usage;
mOriginalAudioUsage = audioUsage;
mFlags = flags & FLAG_ALL_SUPPORTED;
}
/**
* Return the vibration usage class.
*/
@UsageClass
public int getUsageClass() {
return mUsage & USAGE_CLASS_MASK;
}
/**
* Return the vibration usage.
*/
@Usage
public int getUsage() {
return mUsage;
}
/**
* Return the flags.
* @return a combined mask of all flags
*/
@Flag
public int getFlags() {
return mFlags;
}
/**
* Check whether a flag is set
* @return true if a flag is set and false otherwise
*/
public boolean isFlagSet(@Flag int flag) {
return (mFlags & flag) > 0;
}
/**
* Return {@link AudioAttributes} usage equivalent to {@link #getUsage()}.
* @return one of {@link AudioAttributes#SDK_USAGES} that represents {@link #getUsage()}
* @hide
*/
@TestApi
@AudioAttributes.AttributeUsage
public int getAudioUsage() {
if (mOriginalAudioUsage != AudioAttributes.USAGE_UNKNOWN) {
// Return same audio usage set in the Builder.
return mOriginalAudioUsage;
}
// Return correct audio usage based on the vibration usage set in the Builder.
switch (mUsage) {
case USAGE_NOTIFICATION:
return AudioAttributes.USAGE_NOTIFICATION;
case USAGE_COMMUNICATION_REQUEST:
return AudioAttributes.USAGE_VOICE_COMMUNICATION;
case USAGE_RINGTONE:
return AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
case USAGE_TOUCH:
return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION;
case USAGE_ALARM:
return AudioAttributes.USAGE_ALARM;
case USAGE_ACCESSIBILITY:
return AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY;
case USAGE_MEDIA:
return AudioAttributes.USAGE_MEDIA;
default:
return AudioAttributes.USAGE_UNKNOWN;
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mUsage);
dest.writeInt(mOriginalAudioUsage);
dest.writeInt(mFlags);
}
private VibrationAttributes(Parcel src) {
mUsage = src.readInt();
mOriginalAudioUsage = src.readInt();
mFlags = src.readInt();
}
public static final @NonNull Parcelable.Creator