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

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

Merge "Introduce media and alarm vibration intensity settings"

parents c8aec5f1 095b3d31
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1829,6 +1829,14 @@ package android.os {
    method @NonNull public android.os.VibrationEffect build(int);
  }

  public abstract class Vibrator {
    method public int getDefaultVibrationIntensity(int);
    field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3
    field public static final int VIBRATION_INTENSITY_LOW = 1; // 0x1
    field public static final int VIBRATION_INTENSITY_MEDIUM = 2; // 0x2
    field public static final int VIBRATION_INTENSITY_OFF = 0; // 0x0
  }

  public class VintfObject {
    method public static String[] getHalNamesAndVersions();
    method @NonNull public static String getPlatformSepolicyVersion();
+10 −12
Original line number Diff line number Diff line
@@ -32,9 +32,7 @@ import java.util.Objects;
public final class VibrationAttributes implements Parcelable {
    private static final String TAG = "VibrationAttributes";

    /**
     * @hide
     */
    /** @hide */
    @IntDef(prefix = { "USAGE_CLASS_" }, value = {
            USAGE_CLASS_UNKNOWN,
            USAGE_CLASS_ALARM,
@@ -43,18 +41,18 @@ public final class VibrationAttributes implements Parcelable {
    @Retention(RetentionPolicy.SOURCE)
    public @interface UsageClass {}

    /**
     * @hide
     */
    /** @hide */
    @IntDef(prefix = { "USAGE_" }, value = {
            USAGE_UNKNOWN,
            USAGE_ACCESSIBILITY,
            USAGE_ALARM,
            USAGE_RINGTONE,
            USAGE_NOTIFICATION,
            USAGE_COMMUNICATION_REQUEST,
            USAGE_TOUCH,
            USAGE_PHYSICAL_EMULATION,
            USAGE_HARDWARE_FEEDBACK,
            USAGE_MEDIA,
            USAGE_NOTIFICATION,
            USAGE_PHYSICAL_EMULATION,
            USAGE_RINGTONE,
            USAGE_TOUCH,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Usage {}
+34 −55
Original line number Diff line number Diff line
@@ -23,11 +23,14 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.vibrator.IVibrator;
import android.media.AudioAttributes;
import android.os.vibrator.VibrationConfig;
import android.util.Log;

import java.lang.annotation.Retention;
@@ -49,6 +52,7 @@ public abstract class Vibrator {
     *
     * @hide
     */
    @TestApi
    public static final int VIBRATION_INTENSITY_OFF = 0;

    /**
@@ -56,6 +60,7 @@ public abstract class Vibrator {
     *
     * @hide
     */
    @TestApi
    public static final int VIBRATION_INTENSITY_LOW = 1;

    /**
@@ -63,6 +68,7 @@ public abstract class Vibrator {
     *
     * @hide
     */
    @TestApi
    public static final int VIBRATION_INTENSITY_MEDIUM = 2;

    /**
@@ -70,6 +76,7 @@ public abstract class Vibrator {
     *
     * @hide
     */
    @TestApi
    public static final int VIBRATION_INTENSITY_HIGH = 3;

    /**
@@ -115,16 +122,12 @@ public abstract class Vibrator {
    }

    private final String mPackageName;
    // The default vibration intensity level for haptic feedback.
    @VibrationIntensity
    private int mDefaultHapticFeedbackIntensity;
    // The default vibration intensity level for notifications.
    @VibrationIntensity
    private int mDefaultNotificationVibrationIntensity;
    // The default vibration intensity level for ringtones.
    @VibrationIntensity
    private int mDefaultRingVibrationIntensity;
    private float mHapticChannelMaxVibrationAmplitude;
    @Nullable
    private final Resources mResources;

    // This is lazily loaded only for the few clients that need this (e. Settings app).
    @Nullable
    private volatile VibrationConfig mVibrationConfig;

    /**
     * @hide to prevent subclassing from outside of the framework
@@ -132,8 +135,7 @@ public abstract class Vibrator {
    @UnsupportedAppUsage
    public Vibrator() {
        mPackageName = ActivityThread.currentPackageName();
        final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
        loadVibrationConfig(ctx);
        mResources = null;
    }

    /**
@@ -141,26 +143,7 @@ public abstract class Vibrator {
     */
    protected Vibrator(Context context) {
        mPackageName = context.getOpPackageName();
        loadVibrationConfig(context);
    }

    private void loadVibrationConfig(Context context) {
        mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
                com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
        mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
                com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
        mDefaultRingVibrationIntensity = loadDefaultIntensity(context,
                com.android.internal.R.integer.config_defaultRingVibrationIntensity);
        mHapticChannelMaxVibrationAmplitude = loadFloat(context,
                com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
    }

    private int loadDefaultIntensity(Context ctx, int resId) {
        return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
    }

    private float loadFloat(Context ctx, int resId, float defaultValue) {
        return ctx != null ? ctx.getResources().getFloat(resId) : defaultValue;
        mResources = context.getResources();
    }

    /**
@@ -172,31 +155,30 @@ public abstract class Vibrator {
        return VibratorInfo.EMPTY_VIBRATOR_INFO;
    }

    /**
     * Get the default vibration intensity for haptic feedback.
     *
     * @hide
     */
    public int getDefaultHapticFeedbackIntensity() {
        return mDefaultHapticFeedbackIntensity;
    /** Get the static vibrator configuration from config.xml. */
    private VibrationConfig getConfig() {
        if (mVibrationConfig == null) {
            Resources resources = mResources;
            if (resources == null) {
                final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
                resources = ctx != null ? ctx.getResources() : null;
            }

    /**
     * Get the default vibration intensity for notifications.
     *
     * @hide
     */
    public int getDefaultNotificationVibrationIntensity() {
        return mDefaultNotificationVibrationIntensity;
            // This might be constructed more than once, but it only loads static config data from a
            // xml file, so it would be ok.
            mVibrationConfig = new VibrationConfig(resources);
        }
        return mVibrationConfig;
    }

    /**
     * Get the default vibration intensity for ringtones.
     * Get the default vibration intensity for given usage.
     *
     * @hide
     */
    public int getDefaultRingVibrationIntensity() {
        return mDefaultRingVibrationIntensity;
    @TestApi
    @VibrationIntensity
    public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
        return getConfig().getDefaultVibrationIntensity(usage);
    }

    /**
@@ -280,10 +262,7 @@ public abstract class Vibrator {
     * @hide
     */
    public float getHapticChannelMaximumAmplitude() {
        if (mHapticChannelMaxVibrationAmplitude <= 0) {
            return Float.NaN;
        }
        return mHapticChannelMaxVibrationAmplitude;
        return getConfig().getHapticChannelMaximumAmplitude();
    }

    /**
+175 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.vibrator;

import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY;
import static android.os.VibrationAttributes.USAGE_ALARM;
import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
import static android.os.VibrationAttributes.USAGE_MEDIA;
import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
import static android.os.VibrationAttributes.USAGE_RINGTONE;
import static android.os.VibrationAttributes.USAGE_TOUCH;
import static android.os.VibrationAttributes.USAGE_UNKNOWN;

import android.annotation.Nullable;
import android.content.res.Resources;
import android.os.VibrationAttributes;
import android.os.Vibrator;
import android.os.Vibrator.VibrationIntensity;

/**
 * List of device-specific internal vibration configuration loaded from platform config.xml.
 *
 * <p>This should not be public, but some individual values are exposed by {@link Vibrator} by
 * hidden methods, made available to Settings, SysUI and other platform client code. They can also
 * be individually exposed with the necessary permissions by the {@link Vibrator} service.
 *
 * @hide
 */
public class VibrationConfig {

    // TODO(b/191150049): move these to vibrator static config file
    private final float mHapticChannelMaxVibrationAmplitude;
    private final int mRampStepDurationMs;
    private final int mRampDownDurationMs;

    @VibrationIntensity
    private final int mDefaultAlarmVibrationIntensity;
    @VibrationIntensity
    private final int mDefaultHapticFeedbackIntensity;
    @VibrationIntensity
    private final int mDefaultMediaVibrationIntensity;
    @VibrationIntensity
    private final int mDefaultNotificationVibrationIntensity;
    @VibrationIntensity
    private final int mDefaultRingVibrationIntensity;

    /** @hide */
    public VibrationConfig(@Nullable Resources resources) {
        mHapticChannelMaxVibrationAmplitude = loadFloat(resources,
                com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
        mRampDownDurationMs = loadInteger(resources,
                com.android.internal.R.integer.config_vibrationWaveformRampDownDuration, 0);
        mRampStepDurationMs = loadInteger(resources,
                com.android.internal.R.integer.config_vibrationWaveformRampStepDuration, 0);

        mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultAlarmVibrationIntensity);
        mDefaultHapticFeedbackIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
        mDefaultMediaVibrationIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultMediaVibrationIntensity);
        mDefaultNotificationVibrationIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
        mDefaultRingVibrationIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultRingVibrationIntensity);
    }

    @VibrationIntensity
    private static int loadDefaultIntensity(@Nullable Resources res, int resId) {
        int defaultIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
        int value = loadInteger(res, resId, defaultIntensity);
        if (value < Vibrator.VIBRATION_INTENSITY_OFF || value > Vibrator.VIBRATION_INTENSITY_HIGH) {
            return defaultIntensity;
        }
        return value;
    }

    private static float loadFloat(@Nullable Resources res, int resId, float defaultValue) {
        return res != null ? res.getFloat(resId) : defaultValue;
    }

    private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) {
        return res != null ? res.getInteger(resId) : defaultValue;
    }

    /**
     * Return the maximum amplitude the vibrator can play using the audio haptic channels.
     *
     * @return a positive value representing the maximum absolute value the device can play signals
     * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown.
     */
    public float getHapticChannelMaximumAmplitude() {
        if (mHapticChannelMaxVibrationAmplitude <= 0) {
            return Float.NaN;
        }
        return mHapticChannelMaxVibrationAmplitude;
    }

    /**
     * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator
     * when a vibration is cancelled or finished at non-zero amplitude.
     */
    public int getRampDownDurationMs() {
        if (mRampDownDurationMs < 0) {
            return 0;
        }
        return mRampDownDurationMs;
    }

    /**
     * The duration, in milliseconds, that should be applied to convert vibration effect's
     * {@link android.os.vibrator.RampSegment} to a {@link android.os.vibrator.StepSegment} on
     * devices without PWLE support.
     */
    public int getRampStepDurationMs() {
        if (mRampStepDurationMs < 0) {
            return 0;
        }
        return mRampStepDurationMs;
    }

    /** Get the default vibration intensity for given usage. */
    @VibrationIntensity
    public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
        switch (usage) {
            case USAGE_ALARM:
                return mDefaultAlarmVibrationIntensity;
            case USAGE_NOTIFICATION:
            case USAGE_COMMUNICATION_REQUEST:
                return mDefaultNotificationVibrationIntensity;
            case USAGE_RINGTONE:
                return mDefaultRingVibrationIntensity;
            case USAGE_TOUCH:
            case USAGE_HARDWARE_FEEDBACK:
            case USAGE_PHYSICAL_EMULATION:
            case USAGE_ACCESSIBILITY:
                return mDefaultHapticFeedbackIntensity;
            case USAGE_MEDIA:
            case USAGE_UNKNOWN:
                // fall through
            default:
                return mDefaultMediaVibrationIntensity;
        }
    }

    @Override
    public String toString() {
        return "VibrationConfig{"
                + "mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude
                + ", mRampStepDurationMs=" + mRampStepDurationMs
                + ", mRampDownDurationMs=" + mRampDownDurationMs
                + ", mDefaultAlarmIntensity=" + mDefaultAlarmVibrationIntensity
                + ", mDefaultHapticFeedbackIntensity=" + mDefaultHapticFeedbackIntensity
                + ", mDefaultMediaIntensity=" + mDefaultMediaVibrationIntensity
                + ", mDefaultNotificationIntensity=" + mDefaultNotificationVibrationIntensity
                + ", mDefaultRingIntensity=" + mDefaultRingVibrationIntensity
                + "}";
    }
}
+38 −1
Original line number Diff line number Diff line
@@ -4602,6 +4602,43 @@ public final class Settings {
        @Readable
        public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices";
        /**
         * The intensity of alarm vibrations, if configurable.
         *
         * Not all devices are capable of changing their vibration intensity; on these devices
         * there will likely be no difference between the various vibration intensities except for
         * intensity 0 (off) and the rest.
         *
         * <b>Values:</b><br/>
         * 0 - Vibration is disabled<br/>
         * 1 - Weak vibrations<br/>
         * 2 - Medium vibrations<br/>
         * 3 - Strong vibrations
         * @hide
         */
        public static final String ALARM_VIBRATION_INTENSITY =
                "alarm_vibration_intensity";
        /**
         * The intensity of media vibrations, if configurable.
         *
         * This includes any vibration that is part of media, such as music, movie, soundtrack,
         * game or animations.
         *
         * Not all devices are capable of changing their vibration intensity; on these devices
         * there will likely be no difference between the various vibration intensities except for
         * intensity 0 (off) and the rest.
         *
         * <b>Values:</b><br/>
         * 0 - Vibration is disabled<br/>
         * 1 - Weak vibrations<br/>
         * 2 - Medium vibrations<br/>
         * 3 - Strong vibrations
         * @hide
         */
        public static final String MEDIA_VIBRATION_INTENSITY =
                "media_vibration_intensity";
        /**
         * The intensity of notification vibrations, if configurable.
         *
@@ -4619,6 +4656,7 @@ public final class Settings {
        @Readable
        public static final String NOTIFICATION_VIBRATION_INTENSITY =
                "notification_vibration_intensity";
        /**
         * The intensity of ringtone vibrations, if configurable.
         *
@@ -4670,7 +4708,6 @@ public final class Settings {
         * 3 - Strong vibrations
         * @hide
         */
        @Readable
        public static final String HARDWARE_HAPTIC_FEEDBACK_INTENSITY =
                "hardware_haptic_feedback_intensity";
Loading