From 396a10c5b028c5e969ff1aee127a108b1ac95570 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Fri, 19 Jan 2018 10:58:07 -0800 Subject: [PATCH] Delay coming out of doze until keyguard dismissed v2 (earlier attempt was reverted due to deadlock) Don't come out of doze when screen is on, but wait until the keyguard is dismissed as well. Pass along the keyguard dismissed to DeviceIdle Request exitIdle when notifications are clicked. Bug: 63527576 Test: Manual: Turn off screen adb shell dumpsys battery unplug adb shell dumpsys deviceidle step x4 Turn on screen, verify still in doze Unlock, verify out of doze Change-Id: Ic5129611d4f098723b31d62a27db8f50860697d4 --- .../android/server/DeviceIdleController.java | 43 ++++++++++++++++++- .../NotificationManagerService.java | 16 +++++++ .../tests/uiservicestests/AndroidManifest.xml | 1 + 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index a12c85aef85e7..44974ffd35099 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -141,6 +141,8 @@ public class DeviceIdleController extends SystemService private boolean mHasNetworkLocation; private Location mLastGenericLocation; private Location mLastGpsLocation; + // Current locked state of the screen + private boolean mScreenLocked; /** Device is currently active. */ private static final int STATE_ACTIVE = 0; @@ -156,6 +158,7 @@ public class DeviceIdleController extends SystemService private static final int STATE_IDLE = 5; /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */ private static final int STATE_IDLE_MAINTENANCE = 6; + private static String stateToString(int state) { switch (state) { case STATE_ACTIVE: return "ACTIVE"; @@ -547,6 +550,11 @@ public class DeviceIdleController extends SystemService "sms_temp_app_whitelist_duration"; private static final String KEY_NOTIFICATION_WHITELIST_DURATION = "notification_whitelist_duration"; + /** + * Whether to wait for the user to unlock the device before causing screen-on to + * exit doze. Default = true + */ + private static final String KEY_WAIT_FOR_UNLOCK = "wait_for_unlock"; /** * This is the time, after becoming inactive, that we go in to the first @@ -765,6 +773,8 @@ public class DeviceIdleController extends SystemService */ public long NOTIFICATION_WHITELIST_DURATION; + public boolean WAIT_FOR_UNLOCK; + private final ContentResolver mResolver; private final boolean mSmallBatteryDevice; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -855,6 +865,7 @@ public class DeviceIdleController extends SystemService KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L); NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis( KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L); + WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, false); } } @@ -962,6 +973,9 @@ public class DeviceIdleController extends SystemService pw.print(" "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("="); TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw); pw.println(); + + pw.print(" "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("="); + pw.println(WAIT_FOR_UNLOCK); } } @@ -1340,6 +1354,19 @@ public class DeviceIdleController extends SystemService } } + private ActivityManagerInternal.ScreenObserver mScreenObserver = + new ActivityManagerInternal.ScreenObserver() { + @Override + public void onAwakeStateChanged(boolean isAwake) { } + + @Override + public void onKeyguardStateChanged(boolean isShowing) { + synchronized (DeviceIdleController.this) { + DeviceIdleController.this.keyguardShowingLocked(isShowing); + } + } + }; + public DeviceIdleController(Context context) { super(context); mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml")); @@ -1406,6 +1433,7 @@ public class DeviceIdleController extends SystemService mNetworkConnected = true; mScreenOn = true; + mScreenLocked = false; // Start out assuming we are charging. If we aren't, we will at least get // a battery update the next time the level drops. mCharging = true; @@ -1501,6 +1529,8 @@ public class DeviceIdleController extends SystemService mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); + mLocalActivityManager.registerScreenObserver(mScreenObserver); + passWhiteListToForceAppStandbyTrackerLocked(); updateInteractivityLocked(); } @@ -1976,7 +2006,7 @@ public class DeviceIdleController extends SystemService } } else if (screenOn) { mScreenOn = true; - if (!mForceIdle) { + if (!mForceIdle && (!mScreenLocked || !mConstants.WAIT_FOR_UNLOCK)) { becomeActiveLocked("screen", Process.myUid()); } } @@ -1997,6 +2027,16 @@ public class DeviceIdleController extends SystemService } } + void keyguardShowingLocked(boolean showing) { + if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing); + if (mScreenLocked != showing) { + mScreenLocked = showing; + if (mScreenOn && !mForceIdle && !mScreenLocked) { + becomeActiveLocked("unlocked", Process.myUid()); + } + } + } + void scheduleReportActiveLocked(String activeReason, int activeUid) { Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason); mHandler.sendMessage(msg); @@ -3308,6 +3348,7 @@ public class DeviceIdleController extends SystemService pw.print(" mForceIdle="); pw.println(mForceIdle); pw.print(" mMotionSensor="); pw.println(mMotionSensor); pw.print(" mScreenOn="); pw.println(mScreenOn); + pw.print(" mScreenLocked="); pw.println(mScreenLocked); pw.print(" mNetworkConnected="); pw.println(mNetworkConnected); pw.print(" mCharging="); pw.println(mCharging); pw.print(" mMotionActive="); pw.println(mMotionListener.active); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 9865e35632858..727e7ee2ac18a 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -111,6 +111,7 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import android.os.IDeviceIdleController; import android.os.IInterface; import android.os.Looper; import android.os.Message; @@ -286,6 +287,7 @@ public class NotificationManagerService extends SystemService { private AlarmManager mAlarmManager; private ICompanionDeviceManager mCompanionManager; private AccessibilityManager mAccessibilityManager; + private IDeviceIdleController mDeviceIdleController; final IBinder mForegroundToken = new Binder(); private WorkerHandler mHandler; @@ -659,6 +661,7 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationClick(int callingUid, int callingPid, String key) { + exitIdle(); synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r == null) { @@ -683,6 +686,7 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex) { + exitIdle(); synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r == null) { @@ -812,6 +816,7 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationDirectReplied(String key) { + exitIdle(); synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { @@ -1280,6 +1285,8 @@ public class NotificationManagerService extends SystemService { mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); mCompanionManager = companionManager; mActivityManager = activityManager; + mDeviceIdleController = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); mHandler = new WorkerHandler(looper); mRankingThread.start(); @@ -1533,6 +1540,15 @@ public class NotificationManagerService extends SystemService { sendRegisteredOnlyBroadcast(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); } + private void exitIdle() { + try { + if (mDeviceIdleController != null) { + mDeviceIdleController.exitIdle("notification interaction"); + } + } catch (RemoteException e) { + } + } + private void updateNotificationChannelInt(String pkg, int uid, NotificationChannel channel, boolean fromListener) { if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) { diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml index 3475572914277..aabf9eab3c1fb 100644 --- a/services/tests/uiservicestests/AndroidManifest.xml +++ b/services/tests/uiservicestests/AndroidManifest.xml @@ -26,6 +26,7 @@ +