Merge "Introduce media and alarm vibration intensity settings"
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