From ce5baf60d1ab5808077b289815b5e8f7bff15e14 Mon Sep 17 00:00:00 2001 From: Alex Salo Date: Fri, 15 Nov 2019 17:10:28 -0800 Subject: [PATCH] Add a flag to allow extending the check post dim Allow to keep checking attention after the screen dim event, for X millis, where X is a DeviceConfig flag. Also move the duration of the check pre-dim to a flag controlled variable Bug: 143902763 Test: manually verified + unit test updated; added tests to make sure flag cannot cause problems Change-Id: I94118d657c8215e07d758170749e9992c19d6535 --- core/res/res/values/config.xml | 2 - core/res/res/values/symbols.xml | 1 - .../server/power/AttentionDetector.java | 76 ++++++++--- .../server/power/PowerManagerService.java | 6 +- .../server/power/AttentionDetectorTest.java | 124 ++++++++++++++++-- 5 files changed, 178 insertions(+), 31 deletions(-) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 76d95618b67cd..d66e0ce19c0c3 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2148,8 +2148,6 @@ 5 330000 - - 2000 - diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java index ed7d23483be7f..eec0d5f35c5ce 100644 --- a/services/core/java/com/android/server/power/AttentionDetector.java +++ b/services/core/java/com/android/server/power/AttentionDetector.java @@ -16,6 +16,7 @@ package com.android.server.power; +import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE; import static android.provider.Settings.System.ADAPTIVE_SLEEP; import android.Manifest; @@ -33,6 +34,7 @@ import android.os.PowerManagerInternal; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.provider.Settings; import android.service.attention.AttentionService; import android.util.Slog; @@ -58,6 +60,22 @@ public class AttentionDetector { private static final String TAG = "AttentionDetector"; private static final boolean DEBUG = false; + /** + * DeviceConfig flag name, describes how much in advance to start checking attention before the + * dim event. + */ + static final String KEY_PRE_DIM_CHECK_DURATION_MILLIS = "pre_dim_check_duration_millis"; + + /** Default value in absence of {@link DeviceConfig} override. */ + static final long DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS = 2_000; + + /** DeviceConfig flag name, describes how long to run the check beyond the screen dim event. */ + static final String KEY_POST_DIM_CHECK_DURATION_MILLIS = + "post_dim_check_duration_millis"; + + /** Default value in absence of {@link DeviceConfig} override. */ + static final long DEFAULT_POST_DIM_CHECK_DURATION_MILLIS = 0; + private Context mContext; private boolean mIsSettingEnabled; @@ -89,11 +107,6 @@ public class AttentionDetector { @VisibleForTesting protected int mRequestId; - /** - * {@link android.service.attention.AttentionService} API timeout. - */ - private long mMaxAttentionApiTimeoutMillis; - /** * Last known user activity. */ @@ -124,6 +137,9 @@ public class AttentionDetector { @VisibleForTesting AttentionCallbackInternalImpl mCallback; + /** Keep the last used post dim timeout for the dumpsys. */ + private long mLastPostDimTimeout; + public AttentionDetector(Runnable onUserAttention, Object lock) { mOnUserAttention = onUserAttention; mLock = lock; @@ -149,8 +165,6 @@ public class AttentionDetector { mWindowManager = LocalServices.getService(WindowManagerInternal.class); mMaximumExtensionMillis = context.getResources().getInteger( com.android.internal.R.integer.config_attentionMaximumExtension); - mMaxAttentionApiTimeoutMillis = context.getResources().getInteger( - com.android.internal.R.integer.config_attentionApiTimeout); try { final UserSwitchObserver observer = new UserSwitchObserver(); @@ -169,7 +183,8 @@ public class AttentionDetector { }, UserHandle.USER_ALL); } - public long updateUserActivity(long nextScreenDimming) { + /** To be called in {@link PowerManagerService#updateUserActivitySummaryLocked}. */ + public long updateUserActivity(long nextScreenDimming, long dimDurationMillis) { if (nextScreenDimming == mLastActedOnNextScreenDimming || !mIsSettingEnabled || mWindowManager.isKeyguardShowingAndNotOccluded()) { @@ -184,7 +199,7 @@ public class AttentionDetector { } final long now = SystemClock.uptimeMillis(); - final long whenToCheck = nextScreenDimming - getAttentionTimeout(); + final long whenToCheck = nextScreenDimming - getPreDimCheckDurationMillis(); final long whenToStopExtending = mLastUserActivityTime + mMaximumExtensionMillis; if (now < whenToCheck) { if (DEBUG) { @@ -213,7 +228,9 @@ public class AttentionDetector { mLastActedOnNextScreenDimming = nextScreenDimming; mCallback = new AttentionCallbackInternalImpl(mRequestId); Slog.v(TAG, "Checking user attention, ID: " + mRequestId); - final boolean sent = mAttentionManager.checkAttention(getAttentionTimeout(), mCallback); + final boolean sent = mAttentionManager.checkAttention( + getPreDimCheckDurationMillis() + getPostDimCheckDurationMillis(dimDurationMillis), + mCallback); if (!sent) { mRequested.set(false); } @@ -272,11 +289,6 @@ public class AttentionDetector { } } - @VisibleForTesting - long getAttentionTimeout() { - return mMaxAttentionApiTimeoutMillis; - } - /** * {@see AttentionManagerInternal#isAttentionServiceSupported} */ @@ -301,12 +313,44 @@ public class AttentionDetector { pw.println("AttentionDetector:"); pw.println(" mIsSettingEnabled=" + mIsSettingEnabled); pw.println(" mMaximumExtensionMillis=" + mMaximumExtensionMillis); - pw.println(" mMaxAttentionApiTimeoutMillis=" + mMaxAttentionApiTimeoutMillis); + pw.println(" preDimCheckDurationMillis=" + getPreDimCheckDurationMillis()); + pw.println(" postDimCheckDurationMillis=" + mLastPostDimTimeout); pw.println(" mLastUserActivityTime(excludingAttention)=" + mLastUserActivityTime); pw.println(" mAttentionServiceSupported=" + isAttentionServiceSupported()); pw.println(" mRequested=" + mRequested); } + /** How long to check before the screen dims, capped at the dim duration. */ + @VisibleForTesting + protected long getPreDimCheckDurationMillis() { + final long millis = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, + DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS); + + if (millis < 0 || millis > 13_000) { + Slog.w(TAG, "Bad flag value supplied for: " + KEY_PRE_DIM_CHECK_DURATION_MILLIS); + return DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS; + } + + return millis; + } + + /** How long to check after the screen dims, capped at the dim duration. */ + @VisibleForTesting + protected long getPostDimCheckDurationMillis(long dimDurationMillis) { + final long millis = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, + DEFAULT_POST_DIM_CHECK_DURATION_MILLIS); + + if (millis < 0 || millis > 10_000) { + Slog.w(TAG, "Bad flag value supplied for: " + KEY_POST_DIM_CHECK_DURATION_MILLIS); + return DEFAULT_POST_DIM_CHECK_DURATION_MILLIS; + } + + mLastPostDimTimeout = Math.min(millis, dimDurationMillis); + return mLastPostDimTimeout; + } + @VisibleForTesting final class AttentionCallbackInternalImpl extends AttentionCallbackInternal { private final int mId; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 9cfd09563bfa2..114a16a96f07b 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -2140,9 +2140,11 @@ public final class PowerManagerService extends SystemService nextTimeout = -1; } - if ((mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0 + if (((mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0 + || (mUserActivitySummary & USER_ACTIVITY_SCREEN_DIM) != 0) && (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) == 0) { - nextTimeout = mAttentionDetector.updateUserActivity(nextTimeout); + nextTimeout = mAttentionDetector.updateUserActivity(nextTimeout, + screenDimDuration); } if (nextProfileTimeout > 0) { diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java index 44769180824e3..642cedb4c852e 100644 --- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java +++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java @@ -17,6 +17,12 @@ package com.android.server.power; import static android.os.BatteryStats.Uid.NUM_USER_ACTIVITY_TYPES; +import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE; + +import static com.android.server.power.AttentionDetector.DEFAULT_POST_DIM_CHECK_DURATION_MILLIS; +import static com.android.server.power.AttentionDetector.DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS; +import static com.android.server.power.AttentionDetector.KEY_POST_DIM_CHECK_DURATION_MILLIS; +import static com.android.server.power.AttentionDetector.KEY_PRE_DIM_CHECK_DURATION_MILLIS; import static com.google.common.truth.Truth.assertThat; @@ -37,6 +43,7 @@ import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.SystemClock; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.provider.Settings; import android.service.attention.AttentionService; import android.test.AndroidTestCase; @@ -53,6 +60,7 @@ import org.mockito.MockitoAnnotations; @SmallTest public class AttentionDetectorTest extends AndroidTestCase { + private static final long DEFAULT_DIM_DURATION_MILLIS = 6_000L; @Mock private PackageManager mPackageManager; @@ -63,7 +71,8 @@ public class AttentionDetectorTest extends AndroidTestCase { @Mock private Runnable mOnUserAttention; private TestableAttentionDetector mAttentionDetector; - private long mAttentionTimeout; + private AttentionDetector mRealAttentionDetector; + private long mPreDimCheckDuration; private long mNextDimming; private int mIsSettingEnabled; @@ -77,6 +86,7 @@ public class AttentionDetectorTest extends AndroidTestCase { .thenReturn(true); when(mWindowManagerInternal.isKeyguardShowingAndNotOccluded()).thenReturn(false); mAttentionDetector = new TestableAttentionDetector(); + mRealAttentionDetector = new AttentionDetector(mOnUserAttention, new Object()); mAttentionDetector.onWakefulnessChangeStarted(PowerManagerInternal.WAKEFULNESS_AWAKE); mAttentionDetector.setAttentionServiceSupported(true); mNextDimming = SystemClock.uptimeMillis() + 3000L; @@ -94,6 +104,13 @@ public class AttentionDetectorTest extends AndroidTestCase { public void tearDown() { Settings.System.putIntForUser(getContext().getContentResolver(), Settings.System.ADAPTIVE_SLEEP, mIsSettingEnabled, UserHandle.USER_CURRENT); + + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, + Long.toString(DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS), false); + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, + Long.toString(DEFAULT_POST_DIM_CHECK_DURATION_MILLIS), false); } @Test @@ -175,7 +192,7 @@ public class AttentionDetectorTest extends AndroidTestCase { long now = SystemClock.uptimeMillis(); mNextDimming = now; mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH); - mAttentionDetector.updateUserActivity(mNextDimming + 5000L); + mAttentionDetector.updateUserActivity(mNextDimming + 5000L, DEFAULT_DIM_DURATION_MILLIS); verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any()); } @@ -184,7 +201,8 @@ public class AttentionDetectorTest extends AndroidTestCase { long now = SystemClock.uptimeMillis(); mNextDimming = now; mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH); - long nextTimeout = mAttentionDetector.updateUserActivity(mNextDimming + 5000L); + long nextTimeout = mAttentionDetector.updateUserActivity(mNextDimming + 5000L, + DEFAULT_DIM_DURATION_MILLIS); assertThat(nextTimeout).isEqualTo(mNextDimming + 5000L); } @@ -192,7 +210,7 @@ public class AttentionDetectorTest extends AndroidTestCase { public void testOnUserActivity_ignoresAfterMaximumExtension() { long now = SystemClock.uptimeMillis(); mAttentionDetector.onUserActivity(now - 15000L, PowerManager.USER_ACTIVITY_EVENT_TOUCH); - mAttentionDetector.updateUserActivity(now + 2000L); + mAttentionDetector.updateUserActivity(now + 2000L, DEFAULT_DIM_DURATION_MILLIS); verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any()); } @@ -203,7 +221,8 @@ public class AttentionDetectorTest extends AndroidTestCase { assertThat(when).isLessThan(mNextDimming); clearInvocations(mAttentionManagerInternal); - long redundantWhen = mAttentionDetector.updateUserActivity(mNextDimming); + long redundantWhen = mAttentionDetector.updateUserActivity(mNextDimming, + DEFAULT_DIM_DURATION_MILLIS); assertThat(redundantWhen).isEqualTo(mNextDimming); verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any()); } @@ -212,7 +231,8 @@ public class AttentionDetectorTest extends AndroidTestCase { public void testOnUserActivity_skipsIfAlreadyScheduled() { registerAttention(); reset(mAttentionManagerInternal); - long when = mAttentionDetector.updateUserActivity(mNextDimming + 1); + long when = mAttentionDetector.updateUserActivity(mNextDimming + 1, + DEFAULT_DIM_DURATION_MILLIS); verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any()); assertThat(when).isLessThan(mNextDimming); } @@ -300,11 +320,95 @@ public class AttentionDetectorTest extends AndroidTestCase { verify(mOnUserAttention, never()).run(); } + @Test + public void testGetPreDimCheckDurationMillis_handlesGoodFlagValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, "555", false); + assertThat(mRealAttentionDetector.getPreDimCheckDurationMillis()).isEqualTo(555); + } + + @Test + public void testGetPreDimCheckDurationMillis_rejectsNegativeValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, "-50", false); + assertThat(mRealAttentionDetector.getPreDimCheckDurationMillis()).isEqualTo( + DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS); + } + + @Test + public void testGetPreDimCheckDurationMillis_rejectsTooBigValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, "20000", false); + assertThat(mRealAttentionDetector.getPreDimCheckDurationMillis()).isEqualTo( + DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS); + } + + @Test + public void testGetPreDimCheckDurationMillis_handlesBadFlagValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, "20000k", false); + assertThat(mRealAttentionDetector.getPreDimCheckDurationMillis()).isEqualTo( + DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS); + + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_PRE_DIM_CHECK_DURATION_MILLIS, "0.25", false); + assertThat(mRealAttentionDetector.getPreDimCheckDurationMillis()).isEqualTo( + DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS); + } + + @Test + public void testGetPostDimCheckDurationMillis_handlesGoodFlagValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, "333", false); + assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis( + DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(333); + } + + @Test + public void testGetPostDimCheckDurationMillis_capsGoodFlagValueByMaxDimDuration() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, "7000", false); + assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(6500)).isEqualTo(6500); + } + + @Test + public void testGetPostDimCheckDurationMillis_rejectsNegativeValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, "-50", false); + assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis( + DEFAULT_DIM_DURATION_MILLIS)).isEqualTo( + DEFAULT_POST_DIM_CHECK_DURATION_MILLIS); + } + + @Test + public void testGetPostDimCheckDurationMillis_rejectsTooBigValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, "20000", false); + assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis( + DEFAULT_DIM_DURATION_MILLIS)).isEqualTo( + DEFAULT_POST_DIM_CHECK_DURATION_MILLIS); + } + + @Test + public void testGetPostDimCheckDurationMillis_handlesBadFlagValue() { + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, "20000k", false); + assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis( + DEFAULT_DIM_DURATION_MILLIS)).isEqualTo( + DEFAULT_POST_DIM_CHECK_DURATION_MILLIS); + + DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, + KEY_POST_DIM_CHECK_DURATION_MILLIS, "0.25", false); + assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis( + DEFAULT_DIM_DURATION_MILLIS)).isEqualTo( + DEFAULT_POST_DIM_CHECK_DURATION_MILLIS); + } + private long registerAttention() { - mAttentionTimeout = 4000L; + mPreDimCheckDuration = 4000L; mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_TOUCH); - return mAttentionDetector.updateUserActivity(mNextDimming); + return mAttentionDetector.updateUserActivity(mNextDimming, DEFAULT_DIM_DURATION_MILLIS); } private class TestableAttentionDetector extends AttentionDetector { @@ -329,8 +433,8 @@ public class AttentionDetectorTest extends AndroidTestCase { } @Override - public long getAttentionTimeout() { - return mAttentionTimeout; + public long getPreDimCheckDurationMillis() { + return mPreDimCheckDuration; } } }