summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/PowerManager.java73
-rw-r--r--core/java/android/os/PowerManagerInternal.java3
-rw-r--r--core/proto/android/server/vibrator/vibratormanagerservice.proto3
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java21
-rw-r--r--services/core/java/com/android/server/vibrator/Vibration.java30
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSettings.java56
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java111
9 files changed, 245 insertions, 73 deletions
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8f2d218a20c1..13ca2c34b27e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -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_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_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_HDMI: return "hdmi";
+ case GO_TO_SLEEP_REASON_QUIESCENT: return "quiescent";
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_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_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_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_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_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) {
@@ -733,6 +738,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
* doing factory resets.
@@ -2644,6 +2678,7 @@ public final class PowerManager {
*
* @hide
*/
+ @GoToSleepReason
public int getLastSleepReason() {
try {
return mService.getLastSleepReason();
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index ec4d3b6a2441..5ca0da2d3f97 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -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);
}
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index 2f2158d4d5a0..2a625b027c17 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -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
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 4075cddc302c..3c13abf4403c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -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,11 +6534,16 @@ 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);
}
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index 3e364314e10f..78b1c20ac4b2 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -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);
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index ac635a0746c5..f9ffd92a7a1c 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -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);
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index d7341cb37685..f0911ca62027 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -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);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
index b907c62be6fb..64950aa69e3b 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
@@ -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);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index 0a50e790215f..b214dd0ad2ba 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -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) {
+ // 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));
+ 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));
}
}