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

Commit 2a0ef1ed authored by Lais Andrade's avatar Lais Andrade Committed by Android (Google) Code Review
Browse files

Merge "Enable hardware feedback in background and disable touch feedback in silent mode"

parents 7b693d35 27ca4427
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ public final class VibrationAttributes implements Parcelable {
    /**
     * @hide
     */
    @IntDef(prefix = { "FLAG_" }, value = {
    @IntDef(prefix = { "FLAG_" }, flag = true, value = {
            FLAG_BYPASS_INTERRUPTION_POLICY,
    })
    @Retention(RetentionPolicy.SOURCE)
@@ -162,7 +162,8 @@ public final class VibrationAttributes implements Parcelable {
    private final int mFlags;
    private final int mOriginalAudioUsage;

    private VibrationAttributes(int usage, int audioUsage, int flags) {
    private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage,
            @Flag int flags) {
        mUsage = usage;
        mOriginalAudioUsage = audioUsage;
        mFlags = flags & FLAG_ALL_SUPPORTED;
@@ -172,6 +173,7 @@ public final class VibrationAttributes implements Parcelable {
     * Return the vibration usage class.
     * @return USAGE_CLASS_ALARM, USAGE_CLASS_FEEDBACK or USAGE_CLASS_UNKNOWN
     */
    @UsageClass
    public int getUsageClass() {
        return mUsage & USAGE_CLASS_MASK;
    }
@@ -180,6 +182,7 @@ public final class VibrationAttributes implements Parcelable {
     * Return the vibration usage.
     * @return one of the values that can be set in {@link Builder#setUsage(int)}
     */
    @Usage
    public int getUsage() {
        return mUsage;
    }
@@ -188,6 +191,7 @@ public final class VibrationAttributes implements Parcelable {
     * Return the flags.
     * @return a combined mask of all flags
     */
    @Flag
    public int getFlags() {
        return mFlags;
    }
@@ -196,7 +200,7 @@ public final class VibrationAttributes implements Parcelable {
     * Check whether a flag is set
     * @return true if a flag is set and false otherwise
     */
    public boolean isFlagSet(int flag) {
    public boolean isFlagSet(@Flag int flag) {
        return (mFlags & flag) > 0;
    }

@@ -206,6 +210,7 @@ public final class VibrationAttributes implements Parcelable {
     * @hide
     */
    @TestApi
    @AudioAttributes.AttributeUsage
    public int getAudioUsage() {
        if (mOriginalAudioUsage != AudioAttributes.USAGE_UNKNOWN) {
            // Return same audio usage set in the Builder.
@@ -292,7 +297,7 @@ public final class VibrationAttributes implements Parcelable {
    }

    /** @hide */
    public static String usageToString(int usage) {
    public static String usageToString(@Usage int usage) {
        switch (usage) {
            case USAGE_UNKNOWN:
                return "UNKNOWN";
@@ -419,7 +424,7 @@ public final class VibrationAttributes implements Parcelable {
         * {@link VibrationAttributes#USAGE_MEDIA}.
         * @return the same Builder instance.
         */
        public @NonNull Builder setUsage(int usage) {
        public @NonNull Builder setUsage(@Usage int usage) {
            mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN;
            mUsage = usage;
            return this;
@@ -431,7 +436,7 @@ public final class VibrationAttributes implements Parcelable {
         * @param mask Bit range that should be changed.
         * @return the same Builder instance.
         */
        public @NonNull Builder setFlags(int flags, int mask) {
        public @NonNull Builder setFlags(@Flag int flags, int mask) {
            mask &= FLAG_ALL_SUPPORTED;
            mFlags = (mFlags & ~mask) | (flags & mask);
            return this;
+1 −1
Original line number Diff line number Diff line
@@ -53,13 +53,13 @@ final class Vibration {
        IGNORED,
        IGNORED_APP_OPS,
        IGNORED_BACKGROUND,
        IGNORED_RINGTONE,
        IGNORED_UNKNOWN_VIBRATION,
        IGNORED_UNSUPPORTED,
        IGNORED_FOR_ALARM,
        IGNORED_FOR_EXTERNAL,
        IGNORED_FOR_ONGOING,
        IGNORED_FOR_POWER,
        IGNORED_FOR_RINGER_MODE,
        IGNORED_FOR_SETTINGS,
        IGNORED_SUPERSEDED,
    }
+118 −85
Original line number Diff line number Diff line
@@ -53,12 +53,44 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/** Controls all the system settings related to vibration. */
final class VibrationSettings {
    private static final String TAG = "VibrationSettings";

    /**
     * Set of usages allowed for vibrations from background processes.
     *
     * <p>Some examples are notification, ringtone or alarm vibrations, that are allowed to vibrate
     * unexpectedly as they are meant to grab the user's attention. Hardware feedback and physical
     * emulation are also supported, as the trigger process might still be in the background when
     * the user interaction wakes the device.
     */
    private static final Set<Integer> BACKGROUND_PROCESS_USAGE_ALLOWLIST = new HashSet<>(
            Arrays.asList(
                    USAGE_RINGTONE,
                    USAGE_ALARM,
                    USAGE_NOTIFICATION,
                    USAGE_COMMUNICATION_REQUEST,
                    USAGE_HARDWARE_FEEDBACK,
                    USAGE_PHYSICAL_EMULATION));

    /**
     * Set of usages allowed for vibrations in battery saver mode (low power).
     *
     * <p>Some examples are ringtone or alarm vibrations, that have high priority and should vibrate
     * even when the device is saving battery.
     */
    private static final Set<Integer> BATTERY_SAVER_USAGE_ALLOWLIST = new HashSet<>(
            Arrays.asList(
                    USAGE_RINGTONE,
                    USAGE_ALARM,
                    USAGE_COMMUNICATION_REQUEST));

    /** Listener for changes on vibration settings. */
    interface OnVibratorSettingsChanged {
        /** Callback triggered when any of the vibrator settings change. */
@@ -94,8 +126,6 @@ final class VibrationSettings {
    @GuardedBy("mLock")
    private boolean mApplyRampingRinger;
    @GuardedBy("mLock")
    private int mZenMode;
    @GuardedBy("mLock")
    private int mHapticFeedbackIntensity;
    @GuardedBy("mLock")
    private int mHardwareFeedbackIntensity;
@@ -104,7 +134,7 @@ final class VibrationSettings {
    @GuardedBy("mLock")
    private int mRingIntensity;
    @GuardedBy("mLock")
    private boolean mLowPowerMode;
    private boolean mBatterySaverMode;

    VibrationSettings(Context context, Handler handler) {
        this(context, handler,
@@ -172,8 +202,8 @@ final class VibrationSettings {
                    public void onLowPowerModeChanged(PowerSaveState result) {
                        boolean shouldNotifyListeners;
                        synchronized (mLock) {
                            shouldNotifyListeners = result.batterySaverEnabled != mLowPowerMode;
                            mLowPowerMode = result.batterySaverEnabled;
                            shouldNotifyListeners = result.batterySaverEnabled != mBatterySaverMode;
                            mBatterySaverMode = result.batterySaverEnabled;
                        }
                        if (shouldNotifyListeners) {
                            notifyListeners();
@@ -187,7 +217,6 @@ final class VibrationSettings {
        registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
        registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
        registerSettingsObserver(Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER));
        registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.ZEN_MODE));
        registerSettingsObserver(
                Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY));
        registerSettingsObserver(
@@ -299,71 +328,78 @@ final class VibrationSettings {
        return mFallbackEffects.get(effectId);
    }

    /** Return {@code true} if input devices should vibrate instead of this device. */
    public boolean shouldVibrateInputDevices() {
        return mVibrateInputDevices;
    }

    /**
     * Return {@code true} if the device should vibrate for current ringer mode.
     * Check if given vibration should be ignored by the service.
     *
     * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings
     * for ringtone usage only. All other usages are allowed independently of ringer mode.
     * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored,
     * null otherwise.
     */
    public boolean shouldVibrateForRingerMode(int usageHint) {
        if (usageHint != USAGE_RINGTONE) {
            return true;
        }
    @Nullable
    public Vibration.Status shouldIgnoreVibration(int uid, VibrationAttributes attrs) {
        final int usage = attrs.getUsage();
        synchronized (mLock) {
            if (mAudioManager == null) {
                return false;
            }
            int ringerMode = mAudioManager.getRingerModeInternal();
            if (mVibrateWhenRinging) {
                return ringerMode != AudioManager.RINGER_MODE_SILENT;
            } else if (mApplyRampingRinger) {
                return ringerMode != AudioManager.RINGER_MODE_SILENT;
            } else {
                return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
            if (!mUidObserver.isUidForeground(uid)
                    && !BACKGROUND_PROCESS_USAGE_ALLOWLIST.contains(usage)) {
                return Vibration.Status.IGNORED_BACKGROUND;
            }

            if (mBatterySaverMode && !BATTERY_SAVER_USAGE_ALLOWLIST.contains(usage)) {
                return Vibration.Status.IGNORED_FOR_POWER;
            }

            int intensity = getCurrentIntensity(usage);
            if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
                return Vibration.Status.IGNORED_FOR_SETTINGS;
            }

    /**
     * Returns {@code true} if this vibration is allowed for given {@code uid}.
     *
     * <p>This checks if the user is aware of this foreground process, or if the vibration usage is
     * allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration).
     */
    public boolean shouldVibrateForUid(int uid, int usageHint) {
        return mUidObserver.isUidForeground(uid) || isClassAlarm(usageHint);
            if (!shouldVibrateForRingerModeLocked(usage)) {
                return Vibration.Status.IGNORED_FOR_RINGER_MODE;
            }
        }
        return null;
    }

    /**
     * Returns {@code true} if this vibration is allowed for current power mode state.
     * Return {@code true} if the device should vibrate for current ringer mode.
     *
     * <p>This checks if the device is in battery saver mode, in which case only alarm, ringtone and
     * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate.
     * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings
     * for touch and ringtone usages only. All other usages are allowed by this method.
     */
    public boolean shouldVibrateForPowerMode(int usageHint) {
        synchronized (mLock) {
            return !mLowPowerMode || usageHint == USAGE_RINGTONE || usageHint == USAGE_ALARM
                    || usageHint == USAGE_COMMUNICATION_REQUEST;
        }
    }
    @GuardedBy("mLock")
    private boolean shouldVibrateForRingerModeLocked(int usageHint) {
        // If audio manager was not loaded yet then assume most restrictive mode.
        int ringerMode = (mAudioManager == null)
                ? AudioManager.RINGER_MODE_SILENT
                : mAudioManager.getRingerModeInternal();

    /** Return {@code true} if input devices should vibrate instead of this device. */
    public boolean shouldVibrateInputDevices() {
        return mVibrateInputDevices;
        switch (usageHint) {
            case USAGE_TOUCH:
                // Touch feedback disabled when phone is on silent mode.
                return ringerMode != AudioManager.RINGER_MODE_SILENT;
            case USAGE_RINGTONE:
                switch (ringerMode) {
                    case AudioManager.RINGER_MODE_SILENT:
                        return false;
                    case AudioManager.RINGER_MODE_VIBRATE:
                        return true;
                    default:
                        // Ringtone vibrations also depend on 2 other settings:
                        return mVibrateWhenRinging || mApplyRampingRinger;
                }

    /** Return {@code true} if setting for {@link Settings.Global#ZEN_MODE} is not OFF. */
    public boolean isInZenMode() {
        return mZenMode != Settings.Global.ZEN_MODE_OFF;
            default:
                // All other usages ignore ringer mode settings.
                return true;
        }

    private static boolean isClassAlarm(int usageHint) {
        return (usageHint & VibrationAttributes.USAGE_CLASS_MASK)
                == VibrationAttributes.USAGE_CLASS_ALARM;
    }

    /** Updates all vibration settings and triggers registered listeners. */
    public void updateSettings() {
    @VisibleForTesting
    void updateSettings() {
        synchronized (mLock) {
            mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
            mApplyRampingRinger = getSystemSetting(Settings.System.APPLY_RAMPING_RINGER, 0) != 0;
@@ -378,7 +414,6 @@ final class VibrationSettings {
            mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
                    getDefaultIntensity(USAGE_RINGTONE));
            mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
            mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
        }
        notifyListeners();
    }
@@ -399,14 +434,15 @@ final class VibrationSettings {

    @Override
    public String toString() {
        synchronized (mLock) {
            return "VibrationSettings{"
                    + "mVibrateInputDevices=" + mVibrateInputDevices
                    + ", mVibrateWhenRinging=" + mVibrateWhenRinging
                    + ", mApplyRampingRinger=" + mApplyRampingRinger
                + ", mLowPowerMode=" + mLowPowerMode
                + ", mZenMode=" + Settings.Global.zenModeToString(mZenMode)
                    + ", mBatterySaverMode=" + mBatterySaverMode
                    + ", mProcStatesCache=" + mUidObserver.mProcStatesCache
                + ", mHapticChannelMaxVibrationAmplitude=" + getHapticChannelMaxVibrationAmplitude()
                    + ", mHapticChannelMaxVibrationAmplitude="
                    + getHapticChannelMaxVibrationAmplitude()
                    + ", mRampStepDuration=" + mRampStepDuration
                    + ", mRampDownDuration=" + mRampDownDuration
                    + ", mHardwareHapticFeedbackIntensity="
@@ -425,6 +461,7 @@ final class VibrationSettings {
                    + intensityToString(getDefaultIntensity(USAGE_RINGTONE))
                    + '}';
        }
    }

    /** Write current settings into given {@link ProtoOutputStream}. */
    public void dumpProto(ProtoOutputStream proto) {
@@ -480,10 +517,6 @@ final class VibrationSettings {
                settingName, defaultValue, UserHandle.USER_CURRENT);
    }

    private int getGlobalSetting(String settingName, int defaultValue) {
        return Settings.Global.getInt(mContext.getContentResolver(), settingName, defaultValue);
    }

    private void registerSettingsObserver(Uri settingUri) {
        mContext.getContentResolver().registerContentObserver(
                settingUri, /* notifyForDescendants= */ true, mSettingObserver,
+189 −177

File changed.

Preview size limit exceeded, changes collapsed.

+193 −99

File changed.

Preview size limit exceeded, changes collapsed.