Merge "Check sleep reason and time before cancelling vibrations" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-05-16 22:02:05 +00:00
committed by Android (Google) Code Review
9 changed files with 246 additions and 74 deletions

View File

@@ -463,21 +463,22 @@ public final class PowerManager {
/**
* @hide
*/
public static String sleepReasonToString(int sleepReason) {
public static String sleepReasonToString(@GoToSleepReason int sleepReason) {
switch (sleepReason) {
case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
case GO_TO_SLEEP_REASON_APPLICATION: return "application";
case GO_TO_SLEEP_REASON_DEVICE_ADMIN: return "device_admin";
case GO_TO_SLEEP_REASON_TIMEOUT: return "timeout";
case GO_TO_SLEEP_REASON_LID_SWITCH: return "lid_switch";
case GO_TO_SLEEP_REASON_POWER_BUTTON: return "power_button";
case GO_TO_SLEEP_REASON_HDMI: return "hdmi";
case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive";
case GO_TO_SLEEP_REASON_DEVICE_FOLD: return "device_folded";
case GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED: return "display_group_removed";
case GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF: return "display_groups_turned_off";
case GO_TO_SLEEP_REASON_DEVICE_FOLD: return "device_folded";
case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
case GO_TO_SLEEP_REASON_HDMI: return "hdmi";
case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive";
case GO_TO_SLEEP_REASON_LID_SWITCH: return "lid_switch";
case GO_TO_SLEEP_REASON_POWER_BUTTON: return "power_button";
case GO_TO_SLEEP_REASON_QUIESCENT: return "quiescent";
case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
case GO_TO_SLEEP_REASON_TIMEOUT: return "timeout";
default: return Integer.toString(sleepReason);
}
}
@@ -576,18 +577,20 @@ public final class PowerManager {
* @hide
*/
@IntDef(prefix = { "GO_TO_SLEEP_REASON_" }, value = {
GO_TO_SLEEP_REASON_ACCESSIBILITY,
GO_TO_SLEEP_REASON_APPLICATION,
GO_TO_SLEEP_REASON_DEVICE_ADMIN,
GO_TO_SLEEP_REASON_TIMEOUT,
GO_TO_SLEEP_REASON_DEVICE_FOLD,
GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED,
GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF,
GO_TO_SLEEP_REASON_FORCE_SUSPEND,
GO_TO_SLEEP_REASON_HDMI,
GO_TO_SLEEP_REASON_INATTENTIVE,
GO_TO_SLEEP_REASON_LID_SWITCH,
GO_TO_SLEEP_REASON_POWER_BUTTON,
GO_TO_SLEEP_REASON_HDMI,
GO_TO_SLEEP_REASON_SLEEP_BUTTON,
GO_TO_SLEEP_REASON_ACCESSIBILITY,
GO_TO_SLEEP_REASON_FORCE_SUSPEND,
GO_TO_SLEEP_REASON_INATTENTIVE,
GO_TO_SLEEP_REASON_QUIESCENT,
GO_TO_SLEEP_REASON_DEVICE_FOLD
GO_TO_SLEEP_REASON_SLEEP_BUTTON,
GO_TO_SLEEP_REASON_TIMEOUT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface GoToSleepReason{}
@@ -704,6 +707,8 @@ public final class PowerManager {
}
/**
* Information related to the device waking up, triggered by {@link #wakeUp}.
*
* @hide
*/
public static class WakeData {
@@ -712,9 +717,9 @@ public final class PowerManager {
this.wakeReason = wakeReason;
this.sleepDuration = sleepDuration;
}
public long wakeTime;
public @WakeReason int wakeReason;
public long sleepDuration;
public final long wakeTime;
public final @WakeReason int wakeReason;
public final long sleepDuration;
@Override
public boolean equals(@Nullable Object o) {
@@ -732,6 +737,35 @@ public final class PowerManager {
}
}
/**
* Information related to the device going to sleep, triggered by {@link #goToSleep}.
*
* @hide
*/
public static class SleepData {
public SleepData(long goToSleepUptimeMillis, @GoToSleepReason int goToSleepReason) {
this.goToSleepUptimeMillis = goToSleepUptimeMillis;
this.goToSleepReason = goToSleepReason;
}
public final long goToSleepUptimeMillis;
public final @GoToSleepReason int goToSleepReason;
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof SleepData) {
final SleepData other = (SleepData) o;
return goToSleepUptimeMillis == other.goToSleepUptimeMillis
&& goToSleepReason == other.goToSleepReason;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(goToSleepUptimeMillis, goToSleepReason);
}
}
/**
* The value to pass as the 'reason' argument to reboot() to reboot into
* recovery mode for tasks other than applying system updates, such as
@@ -2644,6 +2678,7 @@ public final class PowerManager {
*
* @hide
*/
@GoToSleepReason
public int getLastSleepReason() {
try {
return mService.getLastSleepReason();

View File

@@ -330,6 +330,9 @@ public abstract class PowerManagerInternal {
/** Returns information about the last wakeup event. */
public abstract PowerManager.WakeData getLastWakeup();
/** Returns information about the last event to go to sleep. */
public abstract PowerManager.SleepData getLastGoToSleep();
/** Allows power button to intercept a power key button press. */
public abstract boolean interceptPowerKeyDown(KeyEvent event);
}

View File

@@ -86,7 +86,7 @@ message VibrationAttributesProto {
optional int32 flags = 3;
}
// Next id: 7
// Next id: 8
message VibrationProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional int64 start_time = 1;
@@ -95,6 +95,7 @@ message VibrationProto {
optional CombinedVibrationEffectProto original_effect = 4;
optional VibrationAttributesProto attributes = 5;
optional int32 status = 6;
optional int64 duration_ms = 7;
}
// Next id: 25

View File

@@ -72,8 +72,8 @@ import android.os.Looper;
import android.os.Message;
import android.os.ParcelDuration;
import android.os.PowerManager;
import android.os.PowerManager.GoToSleepReason;
import android.os.PowerManager.ServiceType;
import android.os.PowerManager.WakeData;
import android.os.PowerManager.WakeReason;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
@@ -352,7 +352,7 @@ public final class PowerManagerService extends SystemService
// Last reason the device went to sleep.
private @WakeReason int mLastGlobalWakeReason;
private int mLastGlobalSleepReason;
private @GoToSleepReason int mLastGlobalSleepReason;
// Timestamp of last time power boost interaction was sent.
private long mLastInteractivePowerHintTime;
@@ -6350,20 +6350,26 @@ public final class PowerManagerService extends SystemService
}
}
@GoToSleepReason
private int getLastSleepReasonInternal() {
synchronized (mLock) {
return mLastGlobalSleepReason;
}
}
@VisibleForTesting
private PowerManager.WakeData getLastWakeupInternal() {
synchronized (mLock) {
return new WakeData(mLastGlobalWakeTime, mLastGlobalWakeReason,
return new PowerManager.WakeData(mLastGlobalWakeTime, mLastGlobalWakeReason,
mLastGlobalWakeTime - mLastGlobalSleepTime);
}
}
private PowerManager.SleepData getLastGoToSleepInternal() {
synchronized (mLock) {
return new PowerManager.SleepData(mLastGlobalSleepTime, mLastGlobalSleepReason);
}
}
/**
* If the user presses power while the proximity sensor is enabled and keeping
* the screen off, then turn the screen back on by telling display manager to
@@ -6528,10 +6534,15 @@ public final class PowerManagerService extends SystemService
}
@Override
public WakeData getLastWakeup() {
public PowerManager.WakeData getLastWakeup() {
return getLastWakeupInternal();
}
@Override
public PowerManager.SleepData getLastGoToSleep() {
return getLastGoToSleepInternal();
}
@Override
public boolean interceptPowerKeyDown(KeyEvent event) {
return interceptPowerKeyDownInternal(event);

View File

@@ -71,8 +71,8 @@ final class Vibration {
IGNORED_SUPERSEDED,
}
/** Start time in CLOCK_BOOTTIME base. */
public final long startTime;
/** Start time using {@link SystemClock#uptimeMillis()}, for calculations. */
public final long startUptimeMillis;
public final VibrationAttributes attrs;
public final long id;
public final int uid;
@@ -94,11 +94,14 @@ final class Vibration {
/**
* Start/end times in unix epoch time. Only to be used for debugging purposes and to correlate
* with other system events, any duration calculations should be done use {@link #startTime} so
* as not to be affected by discontinuities created by RTC adjustments.
* with other system events, any duration calculations should be done use
* {@link #startUptimeMillis} so as not to be affected by discontinuities created by RTC
* adjustments.
*/
private final long mStartTimeDebug;
private long mEndTimeDebug;
/** End time using {@link SystemClock#uptimeMillis()}, for calculations. */
private long mEndUptimeMillis;
private Status mStatus;
/** A {@link CountDownLatch} to enable waiting for completion. */
@@ -109,7 +112,7 @@ final class Vibration {
this.token = token;
this.mEffect = effect;
this.id = id;
this.startTime = SystemClock.elapsedRealtime();
this.startUptimeMillis = SystemClock.uptimeMillis();
this.attrs = attrs;
this.uid = uid;
this.opPkg = opPkg;
@@ -131,6 +134,7 @@ final class Vibration {
return;
}
mStatus = status;
mEndUptimeMillis = SystemClock.uptimeMillis();
mEndTimeDebug = System.currentTimeMillis();
mCompletionLatch.countDown();
}
@@ -225,15 +229,17 @@ final class Vibration {
/** Return {@link Vibration.DebugInfo} with read-only debug information about this vibration. */
public Vibration.DebugInfo getDebugInfo() {
long durationMs = hasEnded() ? mEndUptimeMillis - startUptimeMillis : -1;
return new Vibration.DebugInfo(
mStartTimeDebug, mEndTimeDebug, mEffect, mOriginalEffect, /* scale= */ 0, attrs,
uid, opPkg, reason, mStatus);
mStartTimeDebug, mEndTimeDebug, durationMs, mEffect, mOriginalEffect,
/* scale= */ 0, attrs, uid, opPkg, reason, mStatus);
}
/** Debug information about vibrations. */
static final class DebugInfo {
private final long mStartTimeDebug;
private final long mEndTimeDebug;
private final long mDurationMs;
private final CombinedVibration mEffect;
private final CombinedVibration mOriginalEffect;
private final float mScale;
@@ -243,11 +249,12 @@ final class Vibration {
private final String mReason;
private final Status mStatus;
DebugInfo(long startTimeDebug, long endTimeDebug, CombinedVibration effect,
CombinedVibration originalEffect, float scale, VibrationAttributes attrs,
int uid, String opPkg, String reason, Status status) {
DebugInfo(long startTimeDebug, long endTimeDebug, long durationMs,
CombinedVibration effect, CombinedVibration originalEffect, float scale,
VibrationAttributes attrs, int uid, String opPkg, String reason, Status status) {
mStartTimeDebug = startTimeDebug;
mEndTimeDebug = endTimeDebug;
mDurationMs = durationMs;
mEffect = effect;
mOriginalEffect = originalEffect;
mScale = scale;
@@ -266,6 +273,8 @@ final class Vibration {
.append(", endTime: ")
.append(mEndTimeDebug == 0 ? null
: DEBUG_DATE_FORMAT.format(new Date(mEndTimeDebug)))
.append(", durationMs: ")
.append(mDurationMs)
.append(", status: ")
.append(mStatus.name().toLowerCase())
.append(", effect: ")
@@ -290,6 +299,7 @@ final class Vibration {
final long token = proto.start(fieldId);
proto.write(VibrationProto.START_TIME, mStartTimeDebug);
proto.write(VibrationProto.END_TIME, mEndTimeDebug);
proto.write(VibrationProto.DURATION_MS, mDurationMs);
proto.write(VibrationProto.STATUS, mStatus.ordinal());
final long attrsToken = proto.start(VibrationProto.ATTRIBUTES);

View File

@@ -52,6 +52,7 @@ import android.os.Vibrator;
import android.os.Vibrator.VibrationIntensity;
import android.os.vibrator.VibrationConfig;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
@@ -121,6 +122,19 @@ final class VibrationSettings {
USAGE_PHYSICAL_EMULATION,
USAGE_HARDWARE_FEEDBACK));
/**
* Set of reasons for {@link PowerManager} going to sleep events that allows vibrations to
* continue running.
*
* <p>Some examples are timeout and inattentive, which indicates automatic screen off events.
* When a vibration is playing during one of these screen off events then it will not be
* cancelled by the service.
*/
private static final Set<Integer> POWER_MANAGER_SLEEP_REASON_ALLOWLIST = new HashSet<>(
Arrays.asList(
PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT));
private static final IntentFilter USER_SWITCHED_INTENT_FILTER =
new IntentFilter(Intent.ACTION_USER_SWITCHED);
private static final IntentFilter INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER =
@@ -135,7 +149,8 @@ final class VibrationSettings {
private final Object mLock = new Object();
private final Context mContext;
private final String mSystemUiPackage;
private final SettingsContentObserver mSettingObserver;
@VisibleForTesting
final SettingsContentObserver mSettingObserver;
@VisibleForTesting
final UidObserver mUidObserver;
@VisibleForTesting
@@ -150,6 +165,9 @@ final class VibrationSettings {
@GuardedBy("mLock")
@Nullable
private AudioManager mAudioManager;
@GuardedBy("mLock")
@Nullable
private PowerManagerInternal mPowerManagerInternal;
@GuardedBy("mLock")
private boolean mVibrateInputDevices;
@@ -199,10 +217,16 @@ final class VibrationSettings {
}
public void onSystemReady() {
PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class);
AudioManager am = mContext.getSystemService(AudioManager.class);
int ringerMode = am.getRingerModeInternal();
synchronized (mLock) {
mAudioManager = mContext.getSystemService(AudioManager.class);
mRingerMode = mAudioManager.getRingerModeInternal();
mPowerManagerInternal = pm;
mAudioManager = am;
mRingerMode = ringerMode;
}
try {
ActivityManager.getService().registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
@@ -211,7 +235,6 @@ final class VibrationSettings {
// ignored; both services live in system_server
}
PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class);
pm.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
@@ -381,7 +404,27 @@ final class VibrationSettings {
* @return true if the vibration should be cancelled when the screen goes off, false otherwise.
*/
public boolean shouldCancelVibrationOnScreenOff(int uid, String opPkg,
@VibrationAttributes.Usage int usage) {
@VibrationAttributes.Usage int usage, long vibrationStartUptimeMillis) {
PowerManagerInternal pm;
synchronized (mLock) {
pm = mPowerManagerInternal;
}
if (pm != null) {
// The SleepData from PowerManager may refer to a more recent sleep than the broadcast
// that triggered this method call. That's ok because only automatic sleeps would be
// ignored here and not cancel a vibration, and those are usually triggered by timeout
// or inactivity, so it's unlikely that it will override a more active goToSleep reason.
PowerManager.SleepData sleepData = pm.getLastGoToSleep();
if ((sleepData.goToSleepUptimeMillis < vibrationStartUptimeMillis)
|| POWER_MANAGER_SLEEP_REASON_ALLOWLIST.contains(sleepData.goToSleepReason)) {
// Ignore screen off events triggered before the vibration started, and all
// automatic "go to sleep" events from allowlist.
Slog.d(TAG, "Ignoring screen off event triggered at uptime "
+ sleepData.goToSleepUptimeMillis + " for reason "
+ PowerManager.sleepReasonToString(sleepData.goToSleepReason));
return false;
}
}
if (!SYSTEM_VIBRATION_SCREEN_OFF_USAGE_ALLOWLIST.contains(usage)) {
// Usages not allowed even for system vibrations should always be cancelled.
return true;
@@ -628,7 +671,8 @@ final class VibrationSettings {
}
/** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
private final class SettingsContentObserver extends ContentObserver {
@VisibleForTesting
final class SettingsContentObserver extends ContentObserver {
SettingsContentObserver(Handler handler) {
super(handler);
}

View File

@@ -47,6 +47,7 @@ import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Trace;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
@@ -405,7 +406,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
// Force update of user settings before checking if this vibration effect should
// be ignored or scaled.
mVibrationSettings.update();
mVibrationSettings.mSettingObserver.onChange(false);
}
synchronized (mLock) {
@@ -1103,7 +1104,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
Vibration vib = conductor.getVibration();
return mVibrationSettings.shouldCancelVibrationOnScreenOff(
vib.uid, vib.opPkg, vib.attrs.getUsage());
vib.uid, vib.opPkg, vib.attrs.getUsage(), vib.startUptimeMillis);
}
@GuardedBy("mLock")
@@ -1308,13 +1309,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
public final ExternalVibration externalVibration;
public int scale;
private final long mStartUptimeMillis;
private final long mStartTimeDebug;
private long mEndUptimeMillis;
private long mEndTimeDebug;
private Vibration.Status mStatus;
private ExternalVibrationHolder(ExternalVibration externalVibration) {
this.externalVibration = externalVibration;
this.scale = IExternalVibratorService.SCALE_NONE;
mStartUptimeMillis = SystemClock.uptimeMillis();
mStartTimeDebug = System.currentTimeMillis();
mStatus = Vibration.Status.RUNNING;
}
@@ -1325,6 +1330,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return;
}
mStatus = status;
mEndUptimeMillis = SystemClock.uptimeMillis();
mEndTimeDebug = System.currentTimeMillis();
}
@@ -1341,11 +1347,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
public Vibration.DebugInfo getDebugInfo() {
long durationMs = mEndUptimeMillis == 0 ? -1 : mEndUptimeMillis - mStartUptimeMillis;
return new Vibration.DebugInfo(
mStartTimeDebug, mEndTimeDebug, /* effect= */ null, /* originalEffect= */ null,
scale, externalVibration.getVibrationAttributes(),
externalVibration.getUid(), externalVibration.getPackage(),
/* reason= */ null, mStatus);
mStartTimeDebug, mEndTimeDebug, durationMs,
/* effect= */ null, /* originalEffect= */ null, scale,
externalVibration.getVibrationAttributes(), externalVibration.getUid(),
externalVibration.getPackage(), /* reason= */ null, mStatus);
}
}

View File

@@ -277,6 +277,6 @@ public class VibrationScalerTest {
Settings.System.putIntForUser(
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
// FakeSettingsProvider don't support testing triggering ContentObserver yet.
mVibrationSettings.update();
mVibrationSettings.mSettingObserver.onChange(false);
}
}

View File

@@ -54,6 +54,7 @@ import android.content.Intent;
import android.content.pm.PackageManagerInternal;
import android.media.AudioManager;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.Process;
@@ -146,6 +147,8 @@ public class VibrationSettingsTest {
mVibrationSettings = new VibrationSettings(mContextSpy,
new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
mockGoToSleep(/* goToSleepTime= */ 0, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
// Simulate System defaults.
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0);
@@ -164,18 +167,10 @@ public class VibrationSettingsTest {
public void addListener_settingsChangeTriggerListener() {
mVibrationSettings.addListener(mListenerMock);
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);
mVibrationSettings.mSettingObserver.onChange(false);
mVibrationSettings.mSettingObserver.onChange(false);
verify(mListenerMock, times(10)).onChange();
verify(mListenerMock, times(2)).onChange();
}
@Test
@@ -479,50 +474,112 @@ public class VibrationSettingsTest {
}
@Test
public void shouldCancelVibrationOnScreenOff_withNonSystemPackageAndUid_returnsAlwaysTrue() {
public void shouldCancelVibrationOnScreenOff_withEventBeforeVibration_returnsAlwaysFalse() {
long vibrateStartTime = 100;
mockGoToSleep(vibrateStartTime - 10, PowerManager.GO_TO_SLEEP_REASON_APPLICATION);
for (int usage : ALL_USAGES) {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(UID, "some.app", usage));
// Non-system vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, "some.app", usage, vibrateStartTime));
// Vibration with UID zero
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage, vibrateStartTime));
// System vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage, vibrateStartTime));
// SysUI vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
}
}
@Test
public void shouldCancelVibrationOnScreenOff_withSleepReasonInAllowlist_returnsAlwaysFalse() {
long vibrateStartTime = 100;
int[] allowedSleepReasons = new int[] {
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
};
for (int sleepReason : allowedSleepReasons) {
mockGoToSleep(vibrateStartTime + 10, sleepReason);
for (int usage : ALL_USAGES) {
// Non-system vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, "some.app", usage, vibrateStartTime));
// Vibration with UID zero
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage, vibrateStartTime));
// System vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage, vibrateStartTime));
// SysUI vibration
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
}
}
}
@Test
public void shouldCancelVibrationOnScreenOff_withNonSystem_returnsTrueIfReasonNotInAllowlist() {
long vibrateStartTime = 100;
mockGoToSleep(vibrateStartTime + 10, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
for (int usage : ALL_USAGES) {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, "some.app", usage, vibrateStartTime));
}
}
@Test
public void shouldCancelVibrationOnScreenOff_withUidZero_returnsFalseForTouchAndHardware() {
long vibrateStartTime = 100;
mockGoToSleep(vibrateStartTime + 10, PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
for (int usage : ALL_USAGES) {
if (usage == USAGE_TOUCH || usage == USAGE_HARDWARE_FEEDBACK
|| usage == USAGE_PHYSICAL_EMULATION) {
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage));
/* uid= */ 0, "", usage, vibrateStartTime));
} else {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
/* uid= */ 0, "", usage));
/* uid= */ 0, "", usage, vibrateStartTime));
}
}
}
@Test
public void shouldCancelVibrationOnScreenOff_withSystemUid_returnsFalseForTouchAndHardware() {
long vibrateStartTime = 100;
mockGoToSleep(vibrateStartTime + 10, PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD);
for (int usage : ALL_USAGES) {
if (usage == USAGE_TOUCH || usage == USAGE_HARDWARE_FEEDBACK
|| usage == USAGE_PHYSICAL_EMULATION) {
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage));
Process.SYSTEM_UID, "", usage, vibrateStartTime));
} else {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
Process.SYSTEM_UID, "", usage));
Process.SYSTEM_UID, "", usage, vibrateStartTime));
}
}
}
@Test
public void shouldCancelVibrationOnScreenOff_withSysUi_returnsFalseForTouchAndHardware() {
public void shouldCancelVibrationOnScreenOff_withSysUiPkg_returnsFalseForTouchAndHardware() {
long vibrateStartTime = 100;
mockGoToSleep(vibrateStartTime + 10, PowerManager.GO_TO_SLEEP_REASON_HDMI);
for (int usage : ALL_USAGES) {
if (usage == USAGE_TOUCH || usage == USAGE_HARDWARE_FEEDBACK
|| usage == USAGE_PHYSICAL_EMULATION) {
assertFalse(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage));
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
} else {
assertTrue(mVibrationSettings.shouldCancelVibrationOnScreenOff(
UID, SYSUI_PACKAGE_NAME, usage));
UID, SYSUI_PACKAGE_NAME, usage, vibrateStartTime));
}
}
}
@@ -581,7 +638,6 @@ public class VibrationSettingsTest {
public void getCurrentIntensity_noHardwareFeedbackValueUsesHapticFeedbackValue() {
setDefaultIntensity(USAGE_HARDWARE_FEEDBACK, VIBRATION_INTENSITY_MEDIUM);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
mVibrationSettings.update();
assertEquals(VIBRATION_INTENSITY_OFF, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
// If haptic feedback is off, fallback to default value.
assertEquals(VIBRATION_INTENSITY_MEDIUM,
@@ -590,7 +646,6 @@ public class VibrationSettingsTest {
mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
mVibrationSettings.update();
assertEquals(VIBRATION_INTENSITY_HIGH,
mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
// If haptic feedback is on, fallback to that value.
@@ -648,19 +703,25 @@ public class VibrationSettingsTest {
Settings.System.putStringForUser(
mContextSpy.getContentResolver(), settingName, null, UserHandle.USER_CURRENT);
// FakeSettingsProvider doesn't support testing triggering ContentObserver yet.
mVibrationSettings.update();
mVibrationSettings.mSettingObserver.onChange(false);
}
private void setUserSetting(String settingName, int value) {
Settings.System.putIntForUser(
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
// FakeSettingsProvider doesn't support testing triggering ContentObserver yet.
mVibrationSettings.update();
mVibrationSettings.mSettingObserver.onChange(false);
}
private void setRingerMode(int ringerMode) {
mAudioManager.setRingerModeInternal(ringerMode);
assertEquals(ringerMode, mAudioManager.getRingerModeInternal());
mVibrationSettings.update();
mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
}
private void mockGoToSleep(long sleepTime, int reason) {
when(mPowerManagerInternalMock.getLastGoToSleep()).thenReturn(
new PowerManager.SleepData(sleepTime, reason));
}
}