Introduce media and alarm vibration intensity settings
Introduce new setting keys for media and alarm vibration intensity. Merge all default vibration intensity getters into a helper class that receives the VibrationAttributes usage int and applies the default logic to all usages. Also update the usage of boolean settings for haptic feedback and ringtone to disable vibrations in VibrationSettings. Bug: 198346559 Bug: 207477604 Test: VibratorTest & VibrationSettingsTest Change-Id: I69ba05a8bc35657637b1f351f4c19d2d96efc9e3
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -32,32 +32,30 @@ 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,
|
||||
USAGE_CLASS_FEEDBACK,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface UsageClass{}
|
||||
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{}
|
||||
public @interface Usage {}
|
||||
|
||||
/**
|
||||
* Vibration usage filter value to match all usages.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
// 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 notifications.
|
||||
* Get the default vibration intensity for given usage.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int getDefaultNotificationVibrationIntensity() {
|
||||
return mDefaultNotificationVibrationIntensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default vibration intensity for ringtones.
|
||||
*
|
||||
* @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
core/java/android/os/vibrator/VibrationConfig.java
Normal file
175
core/java/android/os/vibrator/VibrationConfig.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -212,6 +212,12 @@ message SystemSettingsProto {
|
||||
// DatabaseHelper.
|
||||
optional SettingProto in_silent = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
optional SettingProto when_ringing = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
|
||||
optional SettingProto alarm_intensity = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
optional SettingProto media_intensity = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
optional SettingProto ring_intensity = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
// notification_intensity is already logged at Notification.vibration_intensity
|
||||
// haptic_feedback_intensity is already logged at HapticFeedback.intensity
|
||||
}
|
||||
optional Vibrate vibrate = 32;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ message VibrationProto {
|
||||
optional int32 status = 6;
|
||||
}
|
||||
|
||||
// Next id: 18
|
||||
// Next id: 24
|
||||
message VibratorManagerServiceDumpProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
repeated int32 vibrator_ids = 1;
|
||||
@@ -106,8 +106,14 @@ message VibratorManagerServiceDumpProto {
|
||||
optional VibrationProto current_external_vibration = 4;
|
||||
optional bool vibrator_under_external_control = 5;
|
||||
optional bool low_power_mode = 6;
|
||||
optional int32 alarm_intensity = 18;
|
||||
optional int32 alarm_default_intensity = 19;
|
||||
optional int32 haptic_feedback_intensity = 7;
|
||||
optional int32 haptic_feedback_default_intensity = 8;
|
||||
optional int32 hardware_feedback_intensity = 22;
|
||||
optional int32 hardware_feedback_default_intensity = 23;
|
||||
optional int32 media_intensity = 20;
|
||||
optional int32 media_default_intensity = 21;
|
||||
optional int32 notification_intensity = 9;
|
||||
optional int32 notification_default_intensity = 10;
|
||||
optional int32 ring_intensity = 11;
|
||||
|
||||
@@ -1179,10 +1179,18 @@
|
||||
<string-array translatable="false" name="config_ringtoneEffectUris">
|
||||
</string-array>
|
||||
|
||||
<!-- The default intensity level for alarm vibrations. See
|
||||
Settings.System.ALARM_VIBRATION_INTENSITY more details on the constant values and
|
||||
meanings. -->
|
||||
<integer name="config_defaultAlarmVibrationIntensity">2</integer>
|
||||
<!-- The default intensity level for haptic feedback. See
|
||||
Settings.System.HAPTIC_FEEDBACK_INTENSITY more details on the constant values and
|
||||
meanings. -->
|
||||
<integer name="config_defaultHapticFeedbackIntensity">2</integer>
|
||||
<!-- The default intensity level for media vibrations. See
|
||||
Settings.System.MEDIA_VIBRATION_INTENSITY more details on the constant values and
|
||||
meanings. -->
|
||||
<integer name="config_defaultMediaVibrationIntensity">2</integer>
|
||||
<!-- The default intensity level for notification vibrations. See
|
||||
Settings.System.NOTIFICATION_VIBRATION_INTENSITY more details on the constant values and
|
||||
meanings. -->
|
||||
|
||||
@@ -3867,7 +3867,9 @@
|
||||
<java-symbol type="drawable" name="ic_arrow_forward" />
|
||||
<java-symbol type="drawable" name="ic_permission" />
|
||||
|
||||
<java-symbol type="integer" name="config_defaultAlarmVibrationIntensity" />
|
||||
<java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />
|
||||
<java-symbol type="integer" name="config_defaultMediaVibrationIntensity" />
|
||||
<java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" />
|
||||
<java-symbol type="integer" name="config_defaultRingVibrationIntensity" />
|
||||
|
||||
|
||||
@@ -27,14 +27,22 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.hardware.vibrator.IVibrator;
|
||||
import android.media.AudioAttributes;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.internal.util.test.FakeSettingsProviderRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -50,11 +58,19 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class VibratorTest {
|
||||
|
||||
@Rule
|
||||
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
|
||||
|
||||
private Context mContextSpy;
|
||||
private Vibrator mVibratorSpy;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mVibratorSpy = spy(InstrumentationRegistry.getContext().getSystemService(Vibrator.class));
|
||||
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
|
||||
|
||||
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
|
||||
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
|
||||
mVibratorSpy = spy(new SystemVibrator(mContextSpy));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -78,6 +78,8 @@ public class SystemSettings {
|
||||
Settings.System.NOTIFICATION_SOUND,
|
||||
Settings.System.ACCELEROMETER_ROTATION,
|
||||
Settings.System.SHOW_BATTERY_PERCENT,
|
||||
Settings.System.ALARM_VIBRATION_INTENSITY,
|
||||
Settings.System.MEDIA_VIBRATION_INTENSITY,
|
||||
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Settings.System.RING_VIBRATION_INTENSITY,
|
||||
Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
|
||||
@@ -118,6 +118,8 @@ public class SystemSettingsValidators {
|
||||
VALIDATORS.put(System.MUTE_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR);
|
||||
VALIDATORS.put(System.VIBRATE_ON, BOOLEAN_VALIDATOR);
|
||||
VALIDATORS.put(System.APPLY_RAMPING_RINGER, BOOLEAN_VALIDATOR);
|
||||
VALIDATORS.put(System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
|
||||
VALIDATORS.put(System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
|
||||
VALIDATORS.put(System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
|
||||
VALIDATORS.put(System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
|
||||
VALIDATORS.put(System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
|
||||
|
||||
@@ -2916,6 +2916,18 @@ class SettingsProtoDumpUtil {
|
||||
dumpSetting(s, p,
|
||||
Settings.System.VIBRATE_WHEN_RINGING,
|
||||
SystemSettingsProto.Vibrate.WHEN_RINGING);
|
||||
|
||||
// NOTIFICATION_VIBRATION_INTENSITY is already logged at Notification.vibration_intensity
|
||||
// HAPTIC_FEEDBACK_INTENSITY is already logged at HapticFeedback.intensity
|
||||
dumpSetting(s, p,
|
||||
Settings.System.ALARM_VIBRATION_INTENSITY,
|
||||
SystemSettingsProto.Vibrate.ALARM_INTENSITY);
|
||||
dumpSetting(s, p,
|
||||
Settings.System.MEDIA_VIBRATION_INTENSITY,
|
||||
SystemSettingsProto.Vibrate.MEDIA_INTENSITY);
|
||||
dumpSetting(s, p,
|
||||
Settings.System.RING_VIBRATION_INTENSITY,
|
||||
SystemSettingsProto.Vibrate.RING_INTENSITY);
|
||||
p.end(vibrateToken);
|
||||
|
||||
final long volumeToken = p.start(SystemSettingsProto.VOLUME);
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
|
||||
package com.android.server.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.app.ActivityManager;
|
||||
@@ -44,8 +47,11 @@ import android.os.UserHandle;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.Vibrator.VibrationIntensity;
|
||||
import android.os.vibrator.VibrationConfig;
|
||||
import android.provider.Settings;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -109,12 +115,8 @@ final class VibrationSettings {
|
||||
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
|
||||
private final SparseArray<VibrationEffect> mFallbackEffects;
|
||||
|
||||
private final int mRampStepDuration;
|
||||
private final int mRampDownDuration;
|
||||
private final VibrationConfig mVibrationConfig;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private Vibrator mVibrator;
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private AudioManager mAudioManager;
|
||||
@@ -122,40 +124,22 @@ final class VibrationSettings {
|
||||
@GuardedBy("mLock")
|
||||
private boolean mVibrateInputDevices;
|
||||
@GuardedBy("mLock")
|
||||
private boolean mVibrateWhenRinging;
|
||||
@GuardedBy("mLock")
|
||||
private boolean mApplyRampingRinger;
|
||||
@GuardedBy("mLock")
|
||||
private int mHapticFeedbackIntensity;
|
||||
@GuardedBy("mLock")
|
||||
private int mHardwareFeedbackIntensity;
|
||||
@GuardedBy("mLock")
|
||||
private int mNotificationIntensity;
|
||||
@GuardedBy("mLock")
|
||||
private int mRingIntensity;
|
||||
private SparseIntArray mCurrentVibrationIntensities = new SparseIntArray();
|
||||
@GuardedBy("mLock")
|
||||
private boolean mBatterySaverMode;
|
||||
|
||||
VibrationSettings(Context context, Handler handler) {
|
||||
this(context, handler,
|
||||
context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_vibrationWaveformRampDownDuration),
|
||||
context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_vibrationWaveformRampStepDuration));
|
||||
this(context, handler, new VibrationConfig(context.getResources()));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
VibrationSettings(Context context, Handler handler, int rampDownDuration,
|
||||
int rampStepDuration) {
|
||||
VibrationSettings(Context context, Handler handler, VibrationConfig config) {
|
||||
mContext = context;
|
||||
mVibrationConfig = config;
|
||||
mSettingObserver = new SettingsObserver(handler);
|
||||
mUidObserver = new UidObserver();
|
||||
mUserReceiver = new UserObserver();
|
||||
|
||||
// TODO(b/191150049): move these to vibrator static config file
|
||||
mRampDownDuration = rampDownDuration;
|
||||
mRampStepDuration = rampStepDuration;
|
||||
|
||||
VibrationEffect clickEffect = createEffectFromResource(
|
||||
com.android.internal.R.array.config_virtualKeyVibePattern);
|
||||
VibrationEffect doubleClickEffect = createEffectFromResource(
|
||||
@@ -179,7 +163,6 @@ final class VibrationSettings {
|
||||
|
||||
public void onSystemReady() {
|
||||
synchronized (mLock) {
|
||||
mVibrator = mContext.getSystemService(Vibrator.class);
|
||||
mAudioManager = mContext.getSystemService(AudioManager.class);
|
||||
}
|
||||
try {
|
||||
@@ -214,11 +197,20 @@ final class VibrationSettings {
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
|
||||
mContext.registerReceiver(mUserReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
|
||||
|
||||
// Listen to all settings that might affect the result of Vibrator.getVibrationIntensity.
|
||||
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.System.getUriFor(
|
||||
Settings.System.HAPTIC_FEEDBACK_ENABLED));
|
||||
registerSettingsObserver(
|
||||
Settings.System.getUriFor(Settings.System.ALARM_VIBRATION_INTENSITY));
|
||||
registerSettingsObserver(
|
||||
Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY));
|
||||
registerSettingsObserver(
|
||||
Settings.System.getUriFor(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY));
|
||||
registerSettingsObserver(
|
||||
Settings.System.getUriFor(Settings.System.MEDIA_VIBRATION_INTENSITY));
|
||||
registerSettingsObserver(
|
||||
Settings.System.getUriFor(Settings.System.NOTIFICATION_VIBRATION_INTENSITY));
|
||||
registerSettingsObserver(
|
||||
@@ -253,7 +245,7 @@ final class VibrationSettings {
|
||||
* devices without PWLE support.
|
||||
*/
|
||||
public int getRampStepDuration() {
|
||||
return mRampStepDuration;
|
||||
return mVibrationConfig.getRampStepDurationMs();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,7 +253,7 @@ final class VibrationSettings {
|
||||
* when a vibration is cancelled or finished at non-zero amplitude.
|
||||
*/
|
||||
public int getRampDownDuration() {
|
||||
return mRampDownDuration;
|
||||
return mVibrationConfig.getRampDownDurationMs();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,25 +262,8 @@ final class VibrationSettings {
|
||||
* @param usageHint one of VibrationAttributes.USAGE_*
|
||||
* @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
|
||||
*/
|
||||
public int getDefaultIntensity(int usageHint) {
|
||||
if (usageHint == USAGE_ALARM) {
|
||||
return Vibrator.VIBRATION_INTENSITY_HIGH;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
if (mVibrator != null) {
|
||||
switch (usageHint) {
|
||||
case USAGE_RINGTONE:
|
||||
return mVibrator.getDefaultRingVibrationIntensity();
|
||||
case USAGE_NOTIFICATION:
|
||||
return mVibrator.getDefaultNotificationVibrationIntensity();
|
||||
case USAGE_TOUCH:
|
||||
case USAGE_HARDWARE_FEEDBACK:
|
||||
case USAGE_PHYSICAL_EMULATION:
|
||||
return mVibrator.getDefaultHapticFeedbackIntensity();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
public int getDefaultIntensity(@VibrationAttributes.Usage int usageHint) {
|
||||
return mVibrationConfig.getDefaultVibrationIntensity(usageHint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,23 +272,10 @@ final class VibrationSettings {
|
||||
* @param usageHint one of VibrationAttributes.USAGE_*
|
||||
* @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
|
||||
*/
|
||||
public int getCurrentIntensity(int usageHint) {
|
||||
public int getCurrentIntensity(@VibrationAttributes.Usage int usageHint) {
|
||||
int defaultIntensity = getDefaultIntensity(usageHint);
|
||||
synchronized (mLock) {
|
||||
switch (usageHint) {
|
||||
case USAGE_RINGTONE:
|
||||
return mRingIntensity;
|
||||
case USAGE_NOTIFICATION:
|
||||
return mNotificationIntensity;
|
||||
case USAGE_TOUCH:
|
||||
return mHapticFeedbackIntensity;
|
||||
case USAGE_HARDWARE_FEEDBACK:
|
||||
case USAGE_PHYSICAL_EMULATION:
|
||||
return mHardwareFeedbackIntensity;
|
||||
case USAGE_ALARM:
|
||||
return Vibrator.VIBRATION_INTENSITY_HIGH;
|
||||
default:
|
||||
return Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
}
|
||||
return mCurrentVibrationIntensities.get(usageHint, defaultIntensity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +333,7 @@ final class VibrationSettings {
|
||||
* for touch and ringtone usages only. All other usages are allowed by this method.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private boolean shouldVibrateForRingerModeLocked(int usageHint) {
|
||||
private boolean shouldVibrateForRingerModeLocked(@VibrationAttributes.Usage int usageHint) {
|
||||
// If audio manager was not loaded yet then assume most restrictive mode.
|
||||
int ringerMode = (mAudioManager == null)
|
||||
? AudioManager.RINGER_MODE_SILENT
|
||||
@@ -379,18 +341,9 @@ final class VibrationSettings {
|
||||
|
||||
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;
|
||||
}
|
||||
// Touch feedback and ringtone disabled when phone is on silent mode.
|
||||
return ringerMode != AudioManager.RINGER_MODE_SILENT;
|
||||
default:
|
||||
// All other usages ignore ringer mode settings.
|
||||
return true;
|
||||
@@ -401,64 +354,89 @@ final class VibrationSettings {
|
||||
@VisibleForTesting
|
||||
void updateSettings() {
|
||||
synchronized (mLock) {
|
||||
mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
|
||||
mApplyRampingRinger = getSystemSetting(Settings.System.APPLY_RAMPING_RINGER, 0) != 0;
|
||||
mHapticFeedbackIntensity = getSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
getDefaultIntensity(USAGE_TOUCH));
|
||||
mHardwareFeedbackIntensity = getSystemSetting(
|
||||
Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
|
||||
getHardwareFeedbackIntensityWhenSettingIsMissing(mHapticFeedbackIntensity));
|
||||
mNotificationIntensity = getSystemSetting(
|
||||
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
getDefaultIntensity(USAGE_NOTIFICATION));
|
||||
mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
|
||||
mVibrateInputDevices = loadSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
|
||||
|
||||
int alarmIntensity = toIntensity(
|
||||
loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1),
|
||||
getDefaultIntensity(USAGE_ALARM));
|
||||
int defaultHapticFeedbackIntensity = getDefaultIntensity(USAGE_TOUCH);
|
||||
int hapticFeedbackIntensity = toIntensity(
|
||||
loadSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, -1),
|
||||
defaultHapticFeedbackIntensity);
|
||||
int positiveHapticFeedbackIntensity = toPositiveIntensity(
|
||||
hapticFeedbackIntensity, defaultHapticFeedbackIntensity);
|
||||
int hardwareFeedbackIntensity = toIntensity(
|
||||
loadSystemSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, -1),
|
||||
positiveHapticFeedbackIntensity);
|
||||
int mediaIntensity = toIntensity(
|
||||
loadSystemSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, -1),
|
||||
getDefaultIntensity(USAGE_MEDIA));
|
||||
int defaultNotificationIntensity = getDefaultIntensity(USAGE_NOTIFICATION);
|
||||
int notificationIntensity = toIntensity(
|
||||
loadSystemSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, -1),
|
||||
defaultNotificationIntensity);
|
||||
int positiveNotificationIntensity = toPositiveIntensity(
|
||||
notificationIntensity, defaultNotificationIntensity);
|
||||
int ringIntensity = toIntensity(
|
||||
loadSystemSetting(Settings.System.RING_VIBRATION_INTENSITY, -1),
|
||||
getDefaultIntensity(USAGE_RINGTONE));
|
||||
mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
|
||||
|
||||
|
||||
mCurrentVibrationIntensities.clear();
|
||||
mCurrentVibrationIntensities.put(USAGE_ALARM, alarmIntensity);
|
||||
mCurrentVibrationIntensities.put(USAGE_NOTIFICATION, notificationIntensity);
|
||||
mCurrentVibrationIntensities.put(USAGE_MEDIA, mediaIntensity);
|
||||
mCurrentVibrationIntensities.put(USAGE_UNKNOWN, mediaIntensity);
|
||||
|
||||
// Communication request is not disabled by the notification setting.
|
||||
mCurrentVibrationIntensities.put(USAGE_COMMUNICATION_REQUEST,
|
||||
positiveNotificationIntensity);
|
||||
|
||||
if (!loadBooleanSetting(Settings.System.VIBRATE_WHEN_RINGING)
|
||||
&& !loadBooleanSetting(Settings.System.APPLY_RAMPING_RINGER)) {
|
||||
// Make sure deprecated boolean setting still disables ringtone vibrations.
|
||||
mCurrentVibrationIntensities.put(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
} else {
|
||||
mCurrentVibrationIntensities.put(USAGE_RINGTONE, ringIntensity);
|
||||
}
|
||||
|
||||
// This should adapt the behavior preceding the introduction of this new setting
|
||||
// key, which is to apply HAPTIC_FEEDBACK_INTENSITY, unless it's disabled.
|
||||
mCurrentVibrationIntensities.put(USAGE_HARDWARE_FEEDBACK, hardwareFeedbackIntensity);
|
||||
mCurrentVibrationIntensities.put(USAGE_PHYSICAL_EMULATION, hardwareFeedbackIntensity);
|
||||
|
||||
if (!loadBooleanSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)) {
|
||||
// Make sure deprecated boolean setting still disables touch vibrations.
|
||||
mCurrentVibrationIntensities.put(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
} else {
|
||||
mCurrentVibrationIntensities.put(USAGE_TOUCH, hapticFeedbackIntensity);
|
||||
}
|
||||
|
||||
// A11y is not disabled by any haptic feedback setting.
|
||||
mCurrentVibrationIntensities.put(USAGE_ACCESSIBILITY, positiveHapticFeedbackIntensity);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value to be used for {@link Settings.System#HARDWARE_HAPTIC_FEEDBACK_INTENSITY}
|
||||
* when the value was not set by the user.
|
||||
*
|
||||
* <p>This should adapt the behavior preceding the introduction of this new setting key, which
|
||||
* is to apply {@link Settings.System#HAPTIC_FEEDBACK_INTENSITY} unless it's disabled.
|
||||
*/
|
||||
private int getHardwareFeedbackIntensityWhenSettingIsMissing(int hapticFeedbackIntensity) {
|
||||
if (hapticFeedbackIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
|
||||
return getDefaultIntensity(USAGE_HARDWARE_FEEDBACK);
|
||||
}
|
||||
return hapticFeedbackIntensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
synchronized (mLock) {
|
||||
StringBuilder vibrationIntensitiesString = new StringBuilder("{");
|
||||
for (int i = 0; i < mCurrentVibrationIntensities.size(); i++) {
|
||||
int usage = mCurrentVibrationIntensities.keyAt(i);
|
||||
int intensity = mCurrentVibrationIntensities.valueAt(i);
|
||||
vibrationIntensitiesString.append(VibrationAttributes.usageToString(usage))
|
||||
.append("=(").append(intensityToString(intensity))
|
||||
.append(",default:").append(intensityToString(getDefaultIntensity(usage)))
|
||||
.append("), ");
|
||||
}
|
||||
vibrationIntensitiesString.append('}');
|
||||
return "VibrationSettings{"
|
||||
+ "mVibrateInputDevices=" + mVibrateInputDevices
|
||||
+ ", mVibrateWhenRinging=" + mVibrateWhenRinging
|
||||
+ ", mApplyRampingRinger=" + mApplyRampingRinger
|
||||
+ "mVibratorConfig=" + mVibrationConfig
|
||||
+ ", mVibrateInputDevices=" + mVibrateInputDevices
|
||||
+ ", mBatterySaverMode=" + mBatterySaverMode
|
||||
+ ", mProcStatesCache=" + mUidObserver.mProcStatesCache
|
||||
+ ", mHapticChannelMaxVibrationAmplitude="
|
||||
+ getHapticChannelMaxVibrationAmplitude()
|
||||
+ ", mRampStepDuration=" + mRampStepDuration
|
||||
+ ", mRampDownDuration=" + mRampDownDuration
|
||||
+ ", mHardwareHapticFeedbackIntensity="
|
||||
+ intensityToString(getCurrentIntensity(USAGE_HARDWARE_FEEDBACK))
|
||||
+ ", mHapticFeedbackIntensity="
|
||||
+ intensityToString(getCurrentIntensity(USAGE_TOUCH))
|
||||
+ ", mHapticFeedbackDefaultIntensity="
|
||||
+ intensityToString(getDefaultIntensity(USAGE_TOUCH))
|
||||
+ ", mNotificationIntensity="
|
||||
+ intensityToString(getCurrentIntensity(USAGE_NOTIFICATION))
|
||||
+ ", mNotificationDefaultIntensity="
|
||||
+ intensityToString(getDefaultIntensity(USAGE_NOTIFICATION))
|
||||
+ ", mRingIntensity="
|
||||
+ intensityToString(getCurrentIntensity(USAGE_RINGTONE))
|
||||
+ ", mRingDefaultIntensity="
|
||||
+ intensityToString(getDefaultIntensity(USAGE_RINGTONE))
|
||||
+ ", mVibrationIntensities=" + vibrationIntensitiesString
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -466,16 +444,28 @@ final class VibrationSettings {
|
||||
/** Write current settings into given {@link ProtoOutputStream}. */
|
||||
public void dumpProto(ProtoOutputStream proto) {
|
||||
synchronized (mLock) {
|
||||
proto.write(VibratorManagerServiceDumpProto.ALARM_INTENSITY,
|
||||
getCurrentIntensity(USAGE_ALARM));
|
||||
proto.write(VibratorManagerServiceDumpProto.ALARM_DEFAULT_INTENSITY,
|
||||
getDefaultIntensity(USAGE_ALARM));
|
||||
proto.write(VibratorManagerServiceDumpProto.HARDWARE_FEEDBACK_INTENSITY,
|
||||
getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
|
||||
proto.write(VibratorManagerServiceDumpProto.HARDWARE_FEEDBACK_DEFAULT_INTENSITY,
|
||||
getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
|
||||
proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY,
|
||||
mHapticFeedbackIntensity);
|
||||
getCurrentIntensity(USAGE_TOUCH));
|
||||
proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY,
|
||||
getDefaultIntensity(USAGE_TOUCH));
|
||||
proto.write(VibratorManagerServiceDumpProto.MEDIA_INTENSITY,
|
||||
getCurrentIntensity(USAGE_MEDIA));
|
||||
proto.write(VibratorManagerServiceDumpProto.MEDIA_DEFAULT_INTENSITY,
|
||||
getDefaultIntensity(USAGE_MEDIA));
|
||||
proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_INTENSITY,
|
||||
mNotificationIntensity);
|
||||
getCurrentIntensity(USAGE_NOTIFICATION));
|
||||
proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_DEFAULT_INTENSITY,
|
||||
getDefaultIntensity(USAGE_NOTIFICATION));
|
||||
proto.write(VibratorManagerServiceDumpProto.RING_INTENSITY,
|
||||
mRingIntensity);
|
||||
getCurrentIntensity(USAGE_RINGTONE));
|
||||
proto.write(VibratorManagerServiceDumpProto.RING_DEFAULT_INTENSITY,
|
||||
getDefaultIntensity(USAGE_RINGTONE));
|
||||
}
|
||||
@@ -506,13 +496,29 @@ final class VibrationSettings {
|
||||
}
|
||||
}
|
||||
|
||||
private float getHapticChannelMaxVibrationAmplitude() {
|
||||
synchronized (mLock) {
|
||||
return mVibrator == null ? Float.NaN : mVibrator.getHapticChannelMaximumAmplitude();
|
||||
@VibrationIntensity
|
||||
private int toPositiveIntensity(int value, @VibrationIntensity int defaultValue) {
|
||||
if (value == Vibrator.VIBRATION_INTENSITY_OFF) {
|
||||
return defaultValue;
|
||||
}
|
||||
return toIntensity(value, defaultValue);
|
||||
}
|
||||
|
||||
private int getSystemSetting(String settingName, int defaultValue) {
|
||||
@VibrationIntensity
|
||||
private int toIntensity(int value, @VibrationIntensity int defaultValue) {
|
||||
if ((value < Vibrator.VIBRATION_INTENSITY_OFF)
|
||||
|| (value > Vibrator.VIBRATION_INTENSITY_HIGH)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean loadBooleanSetting(String settingKey) {
|
||||
return Settings.System.getIntForUser(mContext.getContentResolver(),
|
||||
settingKey, 0, UserHandle.USER_CURRENT) != 0;
|
||||
}
|
||||
|
||||
private int loadSystemSetting(String settingName, int defaultValue) {
|
||||
return Settings.System.getIntForUser(mContext.getContentResolver(),
|
||||
settingName, defaultValue, UserHandle.USER_CURRENT);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.vibrator;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
@@ -24,37 +25,8 @@ import android.os.Vibrator;
|
||||
/** Fake implementation of {@link Vibrator} for service tests. */
|
||||
final class FakeVibrator extends Vibrator {
|
||||
|
||||
private int mDefaultHapticFeedbackIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
private int mDefaultNotificationIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
private int mDefaultRingIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
|
||||
@Override
|
||||
public int getDefaultHapticFeedbackIntensity() {
|
||||
return mDefaultHapticFeedbackIntensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultNotificationVibrationIntensity() {
|
||||
return mDefaultNotificationIntensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultRingVibrationIntensity() {
|
||||
return mDefaultRingIntensity;
|
||||
}
|
||||
|
||||
public void setDefaultHapticFeedbackIntensity(
|
||||
@VibrationIntensity int defaultHapticFeedbackIntensity) {
|
||||
mDefaultHapticFeedbackIntensity = defaultHapticFeedbackIntensity;
|
||||
}
|
||||
|
||||
public void setDefaultNotificationVibrationIntensity(
|
||||
@VibrationIntensity int defaultNotificationIntensity) {
|
||||
mDefaultNotificationIntensity = defaultNotificationIntensity;
|
||||
}
|
||||
|
||||
public void setDefaultRingVibrationIntensity(@VibrationIntensity int defaultRingIntensity) {
|
||||
mDefaultRingIntensity = defaultRingIntensity;
|
||||
FakeVibrator(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
package com.android.server.vibrator;
|
||||
|
||||
import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
|
||||
import static android.os.VibrationAttributes.USAGE_RINGTONE;
|
||||
import static android.os.VibrationAttributes.USAGE_TOUCH;
|
||||
import static android.os.Vibrator.VIBRATION_INTENSITY_HIGH;
|
||||
import static android.os.Vibrator.VIBRATION_INTENSITY_LOW;
|
||||
import static android.os.Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
import static android.os.Vibrator.VIBRATION_INTENSITY_OFF;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
@@ -24,7 +32,6 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.os.Handler;
|
||||
import android.os.IExternalVibratorService;
|
||||
@@ -37,6 +44,7 @@ import android.os.test.TestLooper;
|
||||
import android.os.vibrator.PrebakedSegment;
|
||||
import android.os.vibrator.PrimitiveSegment;
|
||||
import android.os.vibrator.StepSegment;
|
||||
import android.os.vibrator.VibrationConfig;
|
||||
import android.os.vibrator.VibrationEffectSegment;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings;
|
||||
@@ -68,29 +76,31 @@ public class VibrationScalerTest {
|
||||
@Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
|
||||
|
||||
@Mock private PowerManagerInternal mPowerManagerInternalMock;
|
||||
@Mock private VibrationConfig mVibrationConfigMock;
|
||||
|
||||
private TestLooper mTestLooper;
|
||||
private ContextWrapper mContextSpy;
|
||||
private FakeVibrator mFakeVibrator;
|
||||
private VibrationSettings mVibrationSettings;
|
||||
private VibrationScaler mVibrationScaler;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mTestLooper = new TestLooper();
|
||||
mFakeVibrator = new FakeVibrator();
|
||||
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
|
||||
|
||||
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
|
||||
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
|
||||
when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mFakeVibrator);
|
||||
|
||||
LocalServices.removeServiceForTest(PowerManagerInternal.class);
|
||||
LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
|
||||
|
||||
Settings.System.putInt(contentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
|
||||
Settings.System.putInt(contentResolver, Settings.System.VIBRATE_WHEN_RINGING, 1);
|
||||
|
||||
mVibrationSettings = new VibrationSettings(
|
||||
mContextSpy, new Handler(mTestLooper.getLooper()));
|
||||
mContextSpy, new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
|
||||
mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings);
|
||||
|
||||
mVibrationSettings.onSystemReady();
|
||||
}
|
||||
|
||||
@@ -101,91 +111,80 @@ public class VibrationScalerTest {
|
||||
|
||||
@Test
|
||||
public void testGetExternalVibrationScale() {
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
assertEquals(IExternalVibratorService.SCALE_VERY_HIGH,
|
||||
mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
|
||||
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
|
||||
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM);
|
||||
assertEquals(IExternalVibratorService.SCALE_HIGH,
|
||||
mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
|
||||
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
|
||||
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE,
|
||||
mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
|
||||
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
|
||||
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM);
|
||||
assertEquals(IExternalVibratorService.SCALE_LOW,
|
||||
mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
|
||||
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
|
||||
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_HIGH);
|
||||
assertEquals(IExternalVibratorService.SCALE_VERY_LOW,
|
||||
mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
|
||||
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
|
||||
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
// Unexpected vibration intensity will be treated as SCALE_NONE.
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE,
|
||||
mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
|
||||
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scale_withPrebakedSegment_setsEffectStrengthBasedOnSettings() {
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
PrebakedSegment effect = new PrebakedSegment(VibrationEffect.EFFECT_CLICK,
|
||||
/* shouldFallback= */ false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
|
||||
|
||||
PrebakedSegment scaled = mVibrationScaler.scale(
|
||||
effect, VibrationAttributes.USAGE_NOTIFICATION);
|
||||
PrebakedSegment scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
scaled = mVibrationScaler.scale(effect, VibrationAttributes.USAGE_NOTIFICATION);
|
||||
VIBRATION_INTENSITY_MEDIUM);
|
||||
scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
scaled = mVibrationScaler.scale(effect, VibrationAttributes.USAGE_NOTIFICATION);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
scaled = mVibrationScaler.scale(effect, VibrationAttributes.USAGE_NOTIFICATION);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
|
||||
// Unexpected intensity setting will be mapped to STRONG.
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scale_withPrebakedEffect_setsEffectStrengthBasedOnSettings() {
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
VibrationEffect effect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
|
||||
|
||||
PrebakedSegment scaled = getFirstSegment(mVibrationScaler.scale(
|
||||
effect, VibrationAttributes.USAGE_NOTIFICATION));
|
||||
effect, USAGE_NOTIFICATION));
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
VIBRATION_INTENSITY_MEDIUM);
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(
|
||||
effect, VibrationAttributes.USAGE_NOTIFICATION));
|
||||
effect, USAGE_NOTIFICATION));
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(
|
||||
effect, VibrationAttributes.USAGE_NOTIFICATION));
|
||||
effect, USAGE_NOTIFICATION));
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(
|
||||
effect, VibrationAttributes.USAGE_NOTIFICATION));
|
||||
effect, USAGE_NOTIFICATION));
|
||||
// Unexpected intensity setting will be mapped to STRONG.
|
||||
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
}
|
||||
@@ -193,81 +192,77 @@ public class VibrationScalerTest {
|
||||
@Test
|
||||
public void scale_withOneShotAndWaveform_resolvesAmplitude() {
|
||||
// No scale, default amplitude still resolved
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
|
||||
StepSegment resolved = getFirstSegment(mVibrationScaler.scale(
|
||||
VibrationEffect.createOneShot(10, VibrationEffect.DEFAULT_AMPLITUDE),
|
||||
VibrationAttributes.USAGE_RINGTONE));
|
||||
USAGE_RINGTONE));
|
||||
assertTrue(resolved.getAmplitude() > 0);
|
||||
|
||||
resolved = getFirstSegment(mVibrationScaler.scale(
|
||||
VibrationEffect.createWaveform(new long[]{10},
|
||||
new int[]{VibrationEffect.DEFAULT_AMPLITUDE}, -1),
|
||||
VibrationAttributes.USAGE_RINGTONE));
|
||||
USAGE_RINGTONE));
|
||||
assertTrue(resolved.getAmplitude() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scale_withOneShotAndWaveform_scalesAmplitude() {
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM);
|
||||
|
||||
StepSegment scaled = getFirstSegment(mVibrationScaler.scale(
|
||||
VibrationEffect.createOneShot(128, 128), VibrationAttributes.USAGE_RINGTONE));
|
||||
VibrationEffect.createOneShot(128, 128), USAGE_RINGTONE));
|
||||
// Ringtone scales up.
|
||||
assertTrue(scaled.getAmplitude() > 0.5);
|
||||
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(
|
||||
VibrationEffect.createWaveform(new long[]{128}, new int[]{128}, -1),
|
||||
VibrationAttributes.USAGE_NOTIFICATION));
|
||||
USAGE_NOTIFICATION));
|
||||
// Notification scales down.
|
||||
assertTrue(scaled.getAmplitude() < 0.5);
|
||||
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(VibrationEffect.createOneShot(128, 128),
|
||||
VibrationAttributes.USAGE_TOUCH));
|
||||
USAGE_TOUCH));
|
||||
// Haptic feedback does not scale.
|
||||
assertEquals(128f / 255, scaled.getAmplitude(), 1e-5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scale_withComposed_scalesPrimitives() {
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM);
|
||||
|
||||
VibrationEffect composed = VibrationEffect.startComposition()
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f).compose();
|
||||
|
||||
PrimitiveSegment scaled = getFirstSegment(mVibrationScaler.scale(composed,
|
||||
VibrationAttributes.USAGE_RINGTONE));
|
||||
PrimitiveSegment scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_RINGTONE));
|
||||
// Ringtone scales up.
|
||||
assertTrue(scaled.getScale() > 0.5f);
|
||||
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(composed,
|
||||
VibrationAttributes.USAGE_NOTIFICATION));
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_NOTIFICATION));
|
||||
// Notification scales down.
|
||||
assertTrue(scaled.getScale() < 0.5f);
|
||||
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(composed, VibrationAttributes.USAGE_TOUCH));
|
||||
scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_TOUCH));
|
||||
// Haptic feedback does not scale.
|
||||
assertEquals(0.5, scaled.getScale(), 1e-5);
|
||||
}
|
||||
|
||||
private void setDefaultIntensity(@VibrationAttributes.Usage int usage,
|
||||
@Vibrator.VibrationIntensity int intensity) {
|
||||
when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
|
||||
}
|
||||
|
||||
private <T extends VibrationEffectSegment> T getFirstSegment(VibrationEffect.Composed effect) {
|
||||
return (T) effect.getSegments().get(0);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package com.android.server.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;
|
||||
@@ -35,6 +37,7 @@ import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -45,7 +48,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
@@ -55,7 +57,9 @@ import android.os.PowerSaveState;
|
||||
import android.os.UserHandle;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.test.TestLooper;
|
||||
import android.os.vibrator.VibrationConfig;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings;
|
||||
|
||||
@@ -87,6 +91,19 @@ public class VibrationSettingsTest {
|
||||
private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
|
||||
.setBatterySaverEnabled(true).build();
|
||||
|
||||
private static final int[] ALL_USAGES = new int[] {
|
||||
USAGE_UNKNOWN,
|
||||
USAGE_ACCESSIBILITY,
|
||||
USAGE_ALARM,
|
||||
USAGE_COMMUNICATION_REQUEST,
|
||||
USAGE_HARDWARE_FEEDBACK,
|
||||
USAGE_MEDIA,
|
||||
USAGE_NOTIFICATION,
|
||||
USAGE_PHYSICAL_EMULATION,
|
||||
USAGE_RINGTONE,
|
||||
USAGE_TOUCH,
|
||||
};
|
||||
|
||||
@Rule
|
||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule
|
||||
@@ -96,23 +113,23 @@ public class VibrationSettingsTest {
|
||||
private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
|
||||
@Mock
|
||||
private PowerManagerInternal mPowerManagerInternalMock;
|
||||
@Mock
|
||||
private VibrationConfig mVibrationConfigMock;
|
||||
|
||||
private TestLooper mTestLooper;
|
||||
private ContextWrapper mContextSpy;
|
||||
private AudioManager mAudioManager;
|
||||
private FakeVibrator mFakeVibrator;
|
||||
private VibrationSettings mVibrationSettings;
|
||||
private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mTestLooper = new TestLooper();
|
||||
mFakeVibrator = new FakeVibrator();
|
||||
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
|
||||
|
||||
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
|
||||
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
|
||||
when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mFakeVibrator);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
mRegisteredPowerModeListener = invocation.getArgument(0);
|
||||
return null;
|
||||
@@ -121,16 +138,18 @@ public class VibrationSettingsTest {
|
||||
LocalServices.removeServiceForTest(PowerManagerInternal.class);
|
||||
LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
|
||||
|
||||
setDefaultIntensity(VIBRATION_INTENSITY_MEDIUM);
|
||||
mAudioManager = mContextSpy.getSystemService(AudioManager.class);
|
||||
mVibrationSettings = new VibrationSettings(mContextSpy,
|
||||
new Handler(mTestLooper.getLooper()));
|
||||
mVibrationSettings.onSystemReady();
|
||||
new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
|
||||
|
||||
// Simulate System defaults.
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
|
||||
setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0);
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
|
||||
mVibrationSettings.onSystemReady();
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -145,12 +164,15 @@ public class VibrationSettingsTest {
|
||||
setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1);
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
verify(mListenerMock, times(7)).onChange();
|
||||
verify(mListenerMock, times(10)).onChange();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -192,9 +214,7 @@ public class VibrationSettingsTest {
|
||||
UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
|
||||
|
||||
for (int usage : expectedAllowedVibrations) {
|
||||
assertNull("Error for usage " + VibrationAttributes.usageToString(usage),
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(usage)));
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,10 +229,7 @@ public class VibrationSettingsTest {
|
||||
UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
|
||||
|
||||
for (int usage : expectedIgnoredVibrations) {
|
||||
assertEquals("Error for usage " + VibrationAttributes.usageToString(usage),
|
||||
Vibration.Status.IGNORED_BACKGROUND,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(usage)));
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,10 +238,9 @@ public class VibrationSettingsTest {
|
||||
mVibrationSettings.mUidObserver.onUidStateChanged(
|
||||
UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0);
|
||||
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_ALARM)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -238,9 +254,7 @@ public class VibrationSettingsTest {
|
||||
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
|
||||
|
||||
for (int usage : expectedAllowedVibrations) {
|
||||
assertNull("Error for usage " + VibrationAttributes.usageToString(usage),
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(usage)));
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,10 +271,7 @@ public class VibrationSettingsTest {
|
||||
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
|
||||
|
||||
for (int usage : expectedIgnoredVibrations) {
|
||||
assertEquals("Error for usage " + VibrationAttributes.usageToString(usage),
|
||||
Vibration.Status.IGNORED_FOR_POWER,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(usage)));
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_POWER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,130 +279,130 @@ public class VibrationSettingsTest {
|
||||
public void shouldIgnoreVibration_notInBatterySaverMode_allowsAnyUsage() {
|
||||
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
|
||||
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_COMMUNICATION_REQUEST)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withRingerModeSilent_ignoresRingtoneAndTouch() {
|
||||
// Vibrating settings on are overruled by ringer mode.
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
|
||||
setRingerMode(AudioManager.RINGER_MODE_SILENT);
|
||||
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_RINGER_MODE,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_RINGER_MODE,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_COMMUNICATION_REQUEST)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_HARDWARE_FEEDBACK)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_RINGTONE || usage == USAGE_TOUCH) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_RINGER_MODE);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withRingerModeVibrate_allowsAllVibrations() {
|
||||
// Vibrating settings off are overruled by ringer mode.
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
|
||||
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_PHYSICAL_EMULATION)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withRingerModeNormalAndRingSettingsOff_ignoresRingtoneOnly() {
|
||||
// Vibrating settings off are respected for normal ringer mode.
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
public void shouldIgnoreVibration_withRingerModeNormal_allowsAllVibrations() {
|
||||
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
|
||||
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_RINGER_MODE,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withRingerModeNormalAndRingSettingsOn_allowsAllVibrations() {
|
||||
public void shouldIgnoreVibration_withRingSettingsOff_disableRingtoneVibrations() {
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_RINGTONE) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withRingSettingsOn_allowsAllVibrations() {
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
|
||||
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_ALARM)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withRingerModeNormalAndRampingRingerOn_allowsAllVibrations() {
|
||||
public void shouldIgnoreVibration_withRampingRingerOn_allowsAllVibrations() {
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
|
||||
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
|
||||
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_COMMUNICATION_REQUEST)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withHapticFeedbackDisabled_ignoresTouchVibration() {
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
|
||||
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_TOUCH) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withHapticFeedbackSettingsOff_ignoresTouchVibration() {
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_HARDWARE_FEEDBACK)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_TOUCH) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withHardwareFeedbackSettingsOff_ignoresHardwareVibrations() {
|
||||
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_HARDWARE_FEEDBACK)));
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_PHYSICAL_EMULATION)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_HARDWARE_FEEDBACK || usage == USAGE_PHYSICAL_EMULATION) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreVibration_withNotificationSettingsOff_ignoresNotificationVibrations() {
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_ALARM)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_NOTIFICATION) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -402,15 +413,13 @@ public class VibrationSettingsTest {
|
||||
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_RINGTONE)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_ALARM)));
|
||||
assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(USAGE_TOUCH)));
|
||||
for (int usage : ALL_USAGES) {
|
||||
if (usage == USAGE_RINGTONE) {
|
||||
assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
|
||||
} else {
|
||||
assertVibrationNotIgnoredForUsage(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -423,90 +432,40 @@ public class VibrationSettingsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultIntensity_beforeSystemReady_returnsMediumToAllExceptAlarm() {
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
|
||||
mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_HIGH);
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_HIGH);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
public void getDefaultIntensity_returnsIntensityFromVibratorConfig() {
|
||||
setDefaultIntensity(VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
VibrationSettings vibrationSettings = new VibrationSettings(mContextSpy,
|
||||
new Handler(mTestLooper.getLooper()));
|
||||
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_ALARM));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_TOUCH));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
vibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultIntensity_returnsIntensityFromVibratorService() {
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
|
||||
mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_MEDIUM);
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_LOW);
|
||||
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_ALARM));
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_TOUCH));
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
|
||||
assertEquals(VIBRATION_INTENSITY_LOW,
|
||||
mVibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getDefaultIntensity(usage));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentIntensity_returnsIntensityFromSettings() {
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_OFF);
|
||||
mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_OFF);
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
|
||||
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
setDefaultIntensity(VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
|
||||
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_ALARM));
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
|
||||
assertEquals(VIBRATION_INTENSITY_LOW,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
|
||||
assertEquals(VIBRATION_INTENSITY_LOW,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_NOTIFICATION));
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_UNKNOWN));
|
||||
assertEquals(VIBRATION_INTENSITY_LOW,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
|
||||
for (int usage : ALL_USAGES) {
|
||||
assertEquals(errorMessageForUsage(usage),
|
||||
VIBRATION_INTENSITY_LOW,
|
||||
mVibrationSettings.getCurrentIntensity(usage));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentIntensity_updateTriggeredAfterUserSwitched() {
|
||||
mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
|
||||
setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_OFF);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
|
||||
@@ -524,8 +483,9 @@ public class VibrationSettingsTest {
|
||||
|
||||
@Test
|
||||
public void getCurrentIntensity_noHardwareFeedbackValueUsesHapticFeedbackValue() {
|
||||
mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_MEDIUM);
|
||||
setDefaultIntensity(USAGE_HARDWARE_FEEDBACK, VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
|
||||
mVibrationSettings.updateSettings();
|
||||
assertEquals(VIBRATION_INTENSITY_OFF, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
|
||||
// If haptic feedback is off, fallback to default value.
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
@@ -533,15 +493,11 @@ public class VibrationSettingsTest {
|
||||
assertEquals(VIBRATION_INTENSITY_MEDIUM,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
|
||||
|
||||
// Switching user is not working with FakeSettingsProvider.
|
||||
// Testing the broadcast flow manually.
|
||||
Settings.System.putIntForUser(mContextSpy.getContentResolver(),
|
||||
Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH,
|
||||
UserHandle.USER_CURRENT);
|
||||
mVibrationSettings.mUserReceiver.onReceive(mContextSpy,
|
||||
new Intent(Intent.ACTION_USER_SWITCHED));
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
|
||||
mVibrationSettings.updateSettings();
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
|
||||
// If haptic feedback is on, fallback to that value.
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
|
||||
assertEquals(VIBRATION_INTENSITY_HIGH,
|
||||
@@ -557,6 +513,33 @@ public class VibrationSettingsTest {
|
||||
assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_DOUBLE_CLICK));
|
||||
}
|
||||
|
||||
private void assertVibrationIgnoredForUsage(@VibrationAttributes.Usage int usage,
|
||||
Vibration.Status expectedStatus) {
|
||||
assertEquals(errorMessageForUsage(usage),
|
||||
expectedStatus,
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(usage)));
|
||||
}
|
||||
|
||||
private void assertVibrationNotIgnoredForUsage(@VibrationAttributes.Usage int usage) {
|
||||
assertNull(errorMessageForUsage(usage),
|
||||
mVibrationSettings.shouldIgnoreVibration(UID,
|
||||
VibrationAttributes.createForUsage(usage)));
|
||||
}
|
||||
|
||||
private String errorMessageForUsage(int usage) {
|
||||
return "Error for usage " + VibrationAttributes.usageToString(usage);
|
||||
}
|
||||
|
||||
private void setDefaultIntensity(@Vibrator.VibrationIntensity int intensity) {
|
||||
when(mVibrationConfigMock.getDefaultVibrationIntensity(anyInt())).thenReturn(intensity);
|
||||
}
|
||||
|
||||
private void setDefaultIntensity(@VibrationAttributes.Usage int usage,
|
||||
@Vibrator.VibrationIntensity int intensity) {
|
||||
when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
|
||||
}
|
||||
|
||||
private void setUserSetting(String settingName, int value) {
|
||||
Settings.System.putIntForUser(
|
||||
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
|
||||
|
||||
@@ -44,11 +44,13 @@ import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.test.TestLooper;
|
||||
import android.os.vibrator.PrebakedSegment;
|
||||
import android.os.vibrator.PrimitiveSegment;
|
||||
import android.os.vibrator.RampSegment;
|
||||
import android.os.vibrator.StepSegment;
|
||||
import android.os.vibrator.VibrationConfig;
|
||||
import android.os.vibrator.VibrationEffectSegment;
|
||||
import android.platform.test.annotations.LargeTest;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -101,6 +103,8 @@ public class VibrationThreadTest {
|
||||
private IBinder mVibrationToken;
|
||||
@Mock
|
||||
private IBatteryStats mIBatteryStatsMock;
|
||||
@Mock
|
||||
private VibrationConfig mVibrationConfigMock;
|
||||
|
||||
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
|
||||
private VibrationSettings mVibrationSettings;
|
||||
@@ -113,9 +117,13 @@ public class VibrationThreadTest {
|
||||
public void setUp() throws Exception {
|
||||
mTestLooper = new TestLooper();
|
||||
|
||||
when(mVibrationConfigMock.getDefaultVibrationIntensity(anyInt()))
|
||||
.thenReturn(Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
when(mVibrationConfigMock.getRampStepDurationMs()).thenReturn(TEST_RAMP_STEP_DURATION);
|
||||
|
||||
Context context = InstrumentationRegistry.getContext();
|
||||
mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()),
|
||||
/* rampDownDuration= */ 0, TEST_RAMP_STEP_DURATION);
|
||||
mVibrationConfigMock);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
mWakeLock = context.getSystemService(
|
||||
PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
|
||||
@@ -1111,9 +1119,7 @@ public class VibrationThreadTest {
|
||||
|
||||
@Test
|
||||
public void vibrate_waveformWithRampDown_addsRampDownAfterVibrationCompleted() {
|
||||
int rampDownDuration = 15;
|
||||
mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
|
||||
new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
|
||||
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
|
||||
@@ -1139,9 +1145,7 @@ public class VibrationThreadTest {
|
||||
|
||||
@Test
|
||||
public void vibrate_waveformWithRampDown_triggersCallbackWhenOriginalVibrationEnds() {
|
||||
int rampDownDuration = 10_000;
|
||||
mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
|
||||
new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
|
||||
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(10_000);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
|
||||
@@ -1174,9 +1178,7 @@ public class VibrationThreadTest {
|
||||
@Test
|
||||
public void vibrate_waveformCancelledWithRampDown_addsRampDownAfterVibrationCancelled()
|
||||
throws Exception {
|
||||
int rampDownDuration = 15;
|
||||
mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
|
||||
new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
|
||||
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
|
||||
@@ -1202,9 +1204,7 @@ public class VibrationThreadTest {
|
||||
|
||||
@Test
|
||||
public void vibrate_predefinedWithRampDown_doesNotAddRampDown() {
|
||||
int rampDownDuration = 15;
|
||||
mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
|
||||
new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
|
||||
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
|
||||
mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
|
||||
@@ -1224,9 +1224,7 @@ public class VibrationThreadTest {
|
||||
|
||||
@Test
|
||||
public void vibrate_composedWithRampDown_doesNotAddRampDown() {
|
||||
int rampDownDuration = 15;
|
||||
mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
|
||||
new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
|
||||
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
|
||||
IVibrator.CAP_COMPOSE_EFFECTS);
|
||||
@@ -1251,9 +1249,7 @@ public class VibrationThreadTest {
|
||||
|
||||
@Test
|
||||
public void vibrate_pwleWithRampDown_doesNotAddRampDown() {
|
||||
int rampDownDuration = 15;
|
||||
mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
|
||||
new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
|
||||
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
|
||||
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
|
||||
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
|
||||
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.vibrator;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -155,12 +156,13 @@ public class VibratorManagerServiceTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mTestLooper = new TestLooper();
|
||||
mVibrator = new FakeVibrator();
|
||||
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
|
||||
InputManager inputManager = InputManager.resetInstance(mIInputManagerMock);
|
||||
|
||||
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
|
||||
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
|
||||
|
||||
mVibrator = new FakeVibrator(mContextSpy);
|
||||
when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibrator);
|
||||
when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager);
|
||||
when(mContextSpy.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManagerMock);
|
||||
@@ -175,8 +177,13 @@ public class VibratorManagerServiceTest {
|
||||
}).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
|
||||
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
|
||||
setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
@@ -437,7 +444,7 @@ public class VibratorManagerServiceTest {
|
||||
UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
|
||||
|
||||
PrebakedSegment expected = new PrebakedSegment(
|
||||
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
|
||||
|
||||
// Only vibrators 1 and 3 have always-on capabilities.
|
||||
assertEquals(mVibratorProviders.get(1).getAlwaysOnEffect(1), expected);
|
||||
@@ -461,10 +468,10 @@ public class VibratorManagerServiceTest {
|
||||
UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
|
||||
|
||||
PrebakedSegment expectedClick = new PrebakedSegment(
|
||||
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
|
||||
|
||||
PrebakedSegment expectedTick = new PrebakedSegment(
|
||||
VibrationEffect.EFFECT_TICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
VibrationEffect.EFFECT_TICK, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
|
||||
|
||||
// Enables click on vibrator 1 and tick on vibrator 2 only.
|
||||
assertEquals(mVibratorProviders.get(1).getAlwaysOnEffect(1), expectedClick);
|
||||
@@ -539,7 +546,6 @@ public class VibratorManagerServiceTest {
|
||||
public void vibrate_withRingtone_usesRingtoneSettings() throws Exception {
|
||||
mockVibrators(1);
|
||||
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
|
||||
mVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK,
|
||||
VibrationEffect.EFFECT_HEAVY_CLICK, VibrationEffect.EFFECT_DOUBLE_CLICK);
|
||||
|
||||
@@ -932,55 +938,67 @@ public class VibratorManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void vibrate_withIntensitySettings_appliesSettingsToScaleVibrations() throws Exception {
|
||||
mVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
int defaultNotificationIntensity =
|
||||
mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION);
|
||||
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
defaultNotificationIntensity < Vibrator.VIBRATION_INTENSITY_HIGH
|
||||
? defaultNotificationIntensity + 1
|
||||
: defaultNotificationIntensity);
|
||||
|
||||
int defaultTouchIntensity =
|
||||
mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH);
|
||||
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW
|
||||
? defaultTouchIntensity - 1
|
||||
: defaultTouchIntensity);
|
||||
|
||||
setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
|
||||
mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
|
||||
setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH);
|
||||
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
|
||||
mockVibrators(1);
|
||||
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
|
||||
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
|
||||
IVibrator.CAP_COMPOSE_EFFECTS);
|
||||
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
|
||||
VibratorManagerService service = createSystemReadyService();
|
||||
|
||||
vibrate(service, CombinedVibration.startSequential()
|
||||
.addNext(1, VibrationEffect.createOneShot(20, 100))
|
||||
.addNext(1, VibrationEffect.createOneShot(100, 125))
|
||||
.combine(), NOTIFICATION_ATTRS);
|
||||
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
|
||||
service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
vibrate(service, VibrationEffect.startComposition()
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
|
||||
.compose(), HAPTIC_FEEDBACK_ATTRS);
|
||||
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2,
|
||||
service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
vibrate(service, VibrationEffect.startComposition()
|
||||
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
|
||||
.compose(), ALARM_ATTRS);
|
||||
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3,
|
||||
service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
vibrate(service, CombinedVibration.startParallel()
|
||||
.addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
|
||||
.combine(), ALARM_ATTRS);
|
||||
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 4,
|
||||
vibrate(service, VibrationEffect.createOneShot(100, 125), RINGTONE_ATTRS);
|
||||
assertFalse(waitUntil(s -> fakeVibrator.getEffectSegments().size() > 3,
|
||||
service, TEST_TIMEOUT_MILLIS));
|
||||
|
||||
vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
|
||||
assertEquals(3, fakeVibrator.getEffectSegments().size());
|
||||
|
||||
assertEquals(4, fakeVibrator.getEffectSegments().size());
|
||||
// Notification vibrations will be scaled with SCALE_HIGH or none if default is high.
|
||||
assertEquals(defaultNotificationIntensity < Vibrator.VIBRATION_INTENSITY_HIGH,
|
||||
0.6 < fakeVibrator.getAmplitudes().get(0));
|
||||
|
||||
// Notification vibrations will be scaled with SCALE_VERY_HIGH.
|
||||
assertTrue(0.6 < fakeVibrator.getAmplitudes().get(0));
|
||||
// Haptic feedback vibrations will be scaled with SCALE_LOW or none if default is low.
|
||||
assertEquals(defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW,
|
||||
0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale());
|
||||
|
||||
// Haptic feedback vibrations will be scaled with SCALE_LOW.
|
||||
assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale());
|
||||
assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale());
|
||||
|
||||
// Alarm vibration is always VIBRATION_INTENSITY_HIGH.
|
||||
PrebakedSegment expected = new PrebakedSegment(
|
||||
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
|
||||
assertEquals(expected, fakeVibrator.getEffectSegments().get(3));
|
||||
// Alarm vibration will be scaled with SCALE_NONE.
|
||||
assertEquals(1f,
|
||||
((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale(), 1e-5);
|
||||
|
||||
// Ring vibrations have intensity OFF and are not played.
|
||||
}
|
||||
@@ -1100,7 +1118,7 @@ public class VibratorManagerServiceTest {
|
||||
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
|
||||
mExternalVibratorService.onExternalVibrationStop(externalVibration);
|
||||
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE, scale);
|
||||
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
|
||||
assertEquals(Arrays.asList(false, true, false),
|
||||
mVibratorProviders.get(1).getExternalControlStates());
|
||||
}
|
||||
@@ -1127,8 +1145,8 @@ public class VibratorManagerServiceTest {
|
||||
ringtoneAudioAttrs, secondController);
|
||||
int secondScale = mExternalVibratorService.onExternalVibrationStart(secondVibration);
|
||||
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE, firstScale);
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE, secondScale);
|
||||
assertNotEquals(IExternalVibratorService.SCALE_MUTE, firstScale);
|
||||
assertNotEquals(IExternalVibratorService.SCALE_MUTE, secondScale);
|
||||
verify(firstController).mute();
|
||||
verify(secondController, never()).mute();
|
||||
// Set external control called only once.
|
||||
@@ -1151,7 +1169,7 @@ public class VibratorManagerServiceTest {
|
||||
ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
|
||||
mock(IExternalVibrationController.class));
|
||||
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE, scale);
|
||||
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
|
||||
|
||||
// Vibration is cancelled.
|
||||
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
|
||||
@@ -1163,7 +1181,6 @@ public class VibratorManagerServiceTest {
|
||||
public void onExternalVibration_withRingtone_usesRingerModeSettings() {
|
||||
mockVibrators(1);
|
||||
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
|
||||
mVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
|
||||
AudioAttributes audioAttrs = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
|
||||
.build();
|
||||
@@ -1181,13 +1198,13 @@ public class VibratorManagerServiceTest {
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
|
||||
createSystemReadyService();
|
||||
scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE, scale);
|
||||
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
|
||||
|
||||
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
|
||||
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
|
||||
createSystemReadyService();
|
||||
scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
|
||||
assertEquals(IExternalVibratorService.SCALE_NONE, scale);
|
||||
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
|
||||
}
|
||||
|
||||
private VibrationEffectSegment expectedPrebaked(int effectId) {
|
||||
@@ -1235,10 +1252,6 @@ public class VibratorManagerServiceTest {
|
||||
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
|
||||
}
|
||||
|
||||
private void setGlobalSetting(String settingName, int value) {
|
||||
Settings.Global.putInt(mContextSpy.getContentResolver(), settingName, value);
|
||||
}
|
||||
|
||||
private void vibrate(VibratorManagerService service, VibrationEffect effect,
|
||||
VibrationAttributes attrs) {
|
||||
vibrate(service, CombinedVibration.createParallel(effect), attrs);
|
||||
|
||||
Reference in New Issue
Block a user