Merge "Check sleep reason and time before cancelling vibrations" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
79dc62bfef
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user