Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 557d3096 authored by Wilson Wu's avatar Wilson Wu
Browse files

Independent keyboard vibration settings

To make keyboard vibration independent:
-. Add new settings key for keyboard vibration
-. Introduce category keyboard in VibrationAttributes
-. Ignore the vibration effect based on keyboard vibration settings
-. Use a build-in vibration scale for keyboard

Bug: 289107579
Test: atest VibrationSettingsTest
Test: atest HapticFeedbackVibrationProviderTest
Change-Id: I67c95718d11fb429083e1bc9dcab6e1bc85249fc
parent 352e82e4
Loading
Loading
Loading
Loading
+105 −6
Original line number Diff line number Diff line
@@ -140,6 +140,31 @@ public final class VibrationAttributes implements Parcelable {
     */
    public static final int USAGE_MEDIA = 0x10 | USAGE_CLASS_MEDIA;

    /** @hide */
    @IntDef(prefix = { "CATEGORY_" }, value = {
            CATEGORY_UNKNOWN,
            CATEGORY_KEYBOARD,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Category {}

    /**
     * Category value when the vibration category is unknown.
     *
     * @hide
     */
    public static final int CATEGORY_UNKNOWN = 0x0;

    /**
     * Category value for keyboard vibrations.
     *
     * <p>Most typical keyboard vibrations are haptic feedback for virtual keyboard key
     * press/release, for example.
     *
     * @hide
     */
    public static final int CATEGORY_KEYBOARD = 1;

    /**
     * @hide
     */
@@ -147,7 +172,8 @@ public final class VibrationAttributes implements Parcelable {
            FLAG_BYPASS_INTERRUPTION_POLICY,
            FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF,
            FLAG_INVALIDATE_SETTINGS_CACHE,
            FLAG_PIPELINED_EFFECT
            FLAG_PIPELINED_EFFECT,
            FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Flag{}
@@ -167,6 +193,8 @@ public final class VibrationAttributes implements Parcelable {
     * {@link android.view.HapticFeedbackConstants#FLAG_IGNORE_GLOBAL_SETTING} and
     * {@link AudioAttributes#FLAG_BYPASS_MUTE}.
     *
     * <p>Only privileged apps can ignore user settings, and this flag will be ignored otherwise.
     *
     * @hide
     */
    public static final int FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF = 1 << 1;
@@ -198,13 +226,32 @@ public final class VibrationAttributes implements Parcelable {
     */
    public static final int FLAG_PIPELINED_EFFECT = 1 << 3;

    /**
     * Flag requesting that this vibration effect to be played without applying the user
     * intensity setting to scale the vibration.
     *
     * <p>The user setting is still applied to enable/disable the vibration, but the vibration
     * effect strength will not be scaled based on the enabled setting value.
     *
     * <p>This is intended to be used on scenarios where the system needs to enforce a specific
     * strength for the vibration effect, regardless of the user preference. Only privileged apps
     * can ignore user settings, and this flag will be ignored otherwise.
     *
     * <p>If you need to bypass the user setting when it's disabling vibrations then this also
     * needs the flag {@link #FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF} to be set.
     *
     * @hide
     */
    public static final int FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE = 1 << 4;

    /**
     * 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;
                    | FLAG_INVALIDATE_SETTINGS_CACHE | FLAG_PIPELINED_EFFECT
                    | FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE;

    /** Creates a new {@link VibrationAttributes} instance with given usage. */
    public static @NonNull VibrationAttributes createForUsage(@Usage int usage) {
@@ -214,12 +261,14 @@ public final class VibrationAttributes implements Parcelable {
    private final int mUsage;
    private final int mFlags;
    private final int mOriginalAudioUsage;
    private final int mCategory;

    private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage,
            @Flag int flags) {
            @Flag int flags, @Category int category) {
        mUsage = usage;
        mOriginalAudioUsage = audioUsage;
        mFlags = flags & FLAG_ALL_SUPPORTED;
        mCategory = category;
    }

    /**
@@ -247,6 +296,20 @@ public final class VibrationAttributes implements Parcelable {
        return mFlags;
    }

    /**
     * Return the vibration category.
     *
     * <p>Vibration categories describe the source of the vibration, and it can be combined with
     * the vibration usage to best match to a user setting, e.g. a vibration with usage touch and
     * category keyboard can be used to control keyboard haptic feedback independently.
     *
     * @hide
     */
    @Category
    public int getCategory() {
        return mCategory;
    }

    /**
     * Check whether a flag is set
     * @return true if a flag is set and false otherwise
@@ -298,12 +361,14 @@ public final class VibrationAttributes implements Parcelable {
        dest.writeInt(mUsage);
        dest.writeInt(mOriginalAudioUsage);
        dest.writeInt(mFlags);
        dest.writeInt(mCategory);
    }

    private VibrationAttributes(Parcel src) {
        mUsage = src.readInt();
        mOriginalAudioUsage = src.readInt();
        mFlags = src.readInt();
        mCategory = src.readInt();
    }

    public static final @NonNull Parcelable.Creator<VibrationAttributes>
@@ -326,12 +391,12 @@ public final class VibrationAttributes implements Parcelable {
        }
        VibrationAttributes rhs = (VibrationAttributes) o;
        return mUsage == rhs.mUsage && mOriginalAudioUsage == rhs.mOriginalAudioUsage
                && mFlags == rhs.mFlags;
                && mFlags == rhs.mFlags && mCategory == rhs.mCategory;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mUsage, mOriginalAudioUsage, mFlags);
        return Objects.hash(mUsage, mOriginalAudioUsage, mFlags, mCategory);
    }

    @Override
@@ -340,6 +405,7 @@ public final class VibrationAttributes implements Parcelable {
                + "mUsage=" + usageToString()
                + ", mAudioUsage= " + AudioAttributes.usageToString(mOriginalAudioUsage)
                + ", mFlags=" + mFlags
                + ", mCategory=" + categoryToString()
                + '}';
    }

@@ -376,6 +442,23 @@ public final class VibrationAttributes implements Parcelable {
        }
    }

    /** @hide */
    public String categoryToString() {
        return categoryToString(mCategory);
    }

    /** @hide */
    public static String categoryToString(@Category int category) {
        switch (category) {
            case CATEGORY_UNKNOWN:
                return "UNKNOWN";
            case CATEGORY_KEYBOARD:
                return "KEYBOARD";
            default:
                return "unknown category " + category;
        }
    }

    /**
     * Builder class for {@link VibrationAttributes} objects.
     * By default, all information is set to UNKNOWN.
@@ -384,6 +467,7 @@ public final class VibrationAttributes implements Parcelable {
        private int mUsage = USAGE_UNKNOWN;
        private int mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN;
        private int mFlags = 0x0;
        private int mCategory = CATEGORY_UNKNOWN;

        /**
         * Constructs a new Builder with the defaults.
@@ -399,6 +483,7 @@ public final class VibrationAttributes implements Parcelable {
                mUsage = vib.mUsage;
                mOriginalAudioUsage = vib.mOriginalAudioUsage;
                mFlags = vib.mFlags;
                mCategory = vib.mCategory;
            }
        }

@@ -464,7 +549,8 @@ public final class VibrationAttributes implements Parcelable {
         * @return a new {@link VibrationAttributes} object
         */
        public @NonNull VibrationAttributes build() {
            VibrationAttributes ans = new VibrationAttributes(mUsage, mOriginalAudioUsage, mFlags);
            VibrationAttributes ans = new VibrationAttributes(
                    mUsage, mOriginalAudioUsage, mFlags, mCategory);
            return ans;
        }

@@ -479,6 +565,19 @@ public final class VibrationAttributes implements Parcelable {
            return this;
        }

        /**
         * Sets the attribute describing the category of the corresponding vibration.
         *
         * @param category The category for the vibration
         * @return the same Builder instance.
         *
         * @hide
         */
        public @NonNull Builder setCategory(@Category int category) {
            mCategory = category;
            return this;
        }

        /**
         * Sets only the flags specified in the bitmask, leaving the other supported flag values
         * unchanged in the builder.
+10 −0
Original line number Diff line number Diff line
@@ -183,6 +183,16 @@ public abstract class Vibrator {
        return getConfig().getDefaultVibrationIntensity(usage);
    }

    /**
     * Whether the keyboard vibration is enabled by default.
     *
     * @return {@code true} if the keyboard vibration is default enabled, {@code false} otherwise.
     * @hide
     */
    public boolean isDefaultKeyboardVibrationEnabled() {
        return getConfig().isDefaultKeyboardVibrationEnabled();
    }

    /**
     * Return the ID of this vibrator.
     *
+12 −0
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ public class VibrationConfig {
    @VibrationIntensity
    private final int mDefaultRingVibrationIntensity;

    private final boolean mDefaultKeyboardVibrationEnabled;

    /** @hide */
    public VibrationConfig(@Nullable Resources resources) {
        mHapticChannelMaxVibrationAmplitude = loadFloat(resources,
@@ -76,6 +78,8 @@ public class VibrationConfig {

        mIgnoreVibrationsOnWirelessCharger = loadBoolean(resources,
                com.android.internal.R.bool.config_ignoreVibrationsOnWirelessCharger, false);
        mDefaultKeyboardVibrationEnabled = loadBoolean(resources,
                com.android.internal.R.bool.config_defaultKeyboardVibrationEnabled, true);

        mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultAlarmVibrationIntensity);
@@ -157,6 +161,14 @@ public class VibrationConfig {
        return mIgnoreVibrationsOnWirelessCharger;
    }

    /**
     * Whether keyboard vibration settings is enabled by default.
     * @hide
     */
    public boolean isDefaultKeyboardVibrationEnabled() {
        return mDefaultKeyboardVibrationEnabled;
    }

    /** Get the default vibration intensity for given usage. */
    @VibrationIntensity
    public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
+7 −0
Original line number Diff line number Diff line
@@ -37,3 +37,10 @@ flag {
    is_fixed_read_only: true
    bug: "291128479"
}

flag {
    namespace: "haptics"
    name: "keyboard_category_enabled"
    description: "Enables the independent keyboard vibration settings feature"
    bug: "289107579"
}
+8 −0
Original line number Diff line number Diff line
@@ -5129,6 +5129,14 @@ public final class Settings {
        public static final String HARDWARE_HAPTIC_FEEDBACK_INTENSITY =
                "hardware_haptic_feedback_intensity";
        /**
         * Whether keyboard vibration feedback is enabled. The value is boolean (1 or 0).
         *
         * @hide
         */
        @Readable
        public static final String KEYBOARD_VIBRATION_ENABLED = "keyboard_vibration_enabled";
        /**
         * Ringer volume. This is used internally, changing this value will not
         * change the volume. See AudioManager.
Loading