Start a new keyguard session on device sleep

One nuance of this is that a new keyguard session
will start if the user is on the lock screen and then
double presses the power button to launch camera due to the
following sequence of events:

[0ms] user is on the lock screen in KG session #1
[1ms] first power button press => device starts to
go to sleep, so new keyguard session begins KG session #2
[2ms] second power button press => camera is launched,
screen stays on instead of finishing going to sleep

Test: enable SessionTracker logs, see start and end
boundaries of Keyguard is update to include a new session
when the device goes to sleep
Test: atest SessionTrackerTest
Bug: 242628816

Change-Id: I40bdf7f746b7086bc9683f816e00913cd0fd49bf
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 719b5b6..13fc2e6 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -234,7 +234,10 @@
 
     /**
      * Session flag for {@link #registerSessionListener} indicating the listener
-     * is interested in sessions on the keygaurd
+     * is interested in sessions on the keygaurd.
+     * Keyguard Session Boundaries:
+     *     START_SESSION: device starts going to sleep OR the keyguard is newly shown
+     *     END_SESSION: device starts going to sleep OR keyguard is no longer showing
      * @hide
      */
     public static final int SESSION_KEYGUARD = 1 << 0;
diff --git a/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java b/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
index c7e4c5e..b98a92f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
@@ -49,7 +49,9 @@
 @SysUISingleton
 public class SessionTracker implements CoreStartable {
     private static final String TAG = "SessionTracker";
-    private static final boolean DEBUG = false;
+
+    // To enable logs: `adb shell setprop log.tag.SessionTracker DEBUG` & restart sysui
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     // At most 20 bits: ~1m possibilities, ~0.5% probability of collision in 100 values
     private final InstanceIdSequence mInstanceIdGenerator = new InstanceIdSequence(1 << 20);
@@ -81,8 +83,8 @@
         mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
         mKeyguardStateController.addCallback(mKeyguardStateCallback);
 
-        mKeyguardSessionStarted = mKeyguardStateController.isShowing();
-        if (mKeyguardSessionStarted) {
+        if (mKeyguardStateController.isShowing()) {
+            mKeyguardSessionStarted = true;
             startSession(SESSION_KEYGUARD);
         }
     }
@@ -136,12 +138,11 @@
             new KeyguardUpdateMonitorCallback() {
         @Override
         public void onStartedGoingToSleep(int why) {
-            // we need to register to the KeyguardUpdateMonitor lifecycle b/c it gets called
-            // before the WakefulnessLifecycle
             if (mKeyguardSessionStarted) {
-                return;
+                endSession(SESSION_KEYGUARD);
             }
 
+            // Start a new session whenever the device goes to sleep
             mKeyguardSessionStarted = true;
             startSession(SESSION_KEYGUARD);
         }
@@ -154,6 +155,9 @@
             boolean wasSessionStarted = mKeyguardSessionStarted;
             boolean keyguardShowing = mKeyguardStateController.isShowing();
             if (keyguardShowing && !wasSessionStarted) {
+                // the keyguard can start showing without the device going to sleep (ie: lockdown
+                // from the power button), so we start a new keyguard session when the keyguard is
+                // newly shown in addition to when the device starts going to sleep
                 mKeyguardSessionStarted = true;
                 startSession(SESSION_KEYGUARD);
             } else if (!keyguardShowing && wasSessionStarted) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/SessionTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/log/SessionTrackerTest.java
index dc5522e..aa54a1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/SessionTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/SessionTrackerTest.java
@@ -23,8 +23,10 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 
+import static org.junit.Assert.assertNotEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -171,6 +173,34 @@
     }
 
     @Test
+    public void testKeyguardSessionOnDeviceStartsSleepingTwiceInARow_startsNewKeyguardSession()
+            throws RemoteException {
+        // GIVEN session tracker started w/o any sessions
+        mSessionTracker.start();
+        captureKeyguardUpdateMonitorCallback();
+
+        // WHEN device starts going to sleep
+        mKeyguardUpdateMonitorCallback.onStartedGoingToSleep(0);
+
+        // THEN the keyguard session has a session id
+        final InstanceId firstSessionId = mSessionTracker.getSessionId(SESSION_KEYGUARD);
+        assertNotNull(firstSessionId);
+
+        // WHEN device starts going to sleep a second time
+        mKeyguardUpdateMonitorCallback.onStartedGoingToSleep(0);
+
+        // THEN there's a new keyguard session with a unique session id
+        final InstanceId secondSessionId = mSessionTracker.getSessionId(SESSION_KEYGUARD);
+        assertNotNull(secondSessionId);
+        assertNotEquals(firstSessionId, secondSessionId);
+
+        // THEN session start event gets sent to status bar service twice (once per going to
+        // sleep signal)
+        verify(mStatusBarService, times(2)).onSessionStarted(
+                eq(SESSION_KEYGUARD), any(InstanceId.class));
+    }
+
+    @Test
     public void testKeyguardSessionOnKeyguardShowingChange() throws RemoteException {
         // GIVEN session tracker started w/o any sessions
         mSessionTracker.start();