Changes to support reducing noise in active unlock notifications.

1. Add additional trigger onUserMayRequestUnlock
  - point existing trigger points from SystemUI to this
2. Argument added to onUserRequestedUnlock to indicate if user wants to
   dismiss keyguard.
3. Callback for result of grantTrust calls.
  - curently only calls back if device was unlocked as a result of the
    call

See design: go/au-noise-reduction

Note: changes made to SystemUI are manually tested and may need
refactoring which is being skipped now to meet the API Freeze deadline.

Bug: 225231929
Test: atest TrustTests
Test: Manual interaction with wake & fingerprint sensor
CTS-Coverage-Bug: 213944235
Change-Id: I8d08229f09c9a1f2295b7eb464d12cad0c6b8303
diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp
index c9c6c5c..77f98e8 100644
--- a/tests/TrustTests/Android.bp
+++ b/tests/TrustTests/Android.bp
@@ -25,6 +25,8 @@
         "androidx.test.rules",
         "androidx.test.ext.junit",
         "androidx.test.uiautomator",
+        "mockito-target-minus-junit4",
+        "servicestests-utils",
         "truth-prebuilt",
     ],
     libs: [
diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt
index af7a98c..f864fed 100644
--- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt
+++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt
@@ -16,6 +16,7 @@
 
 package android.trust.test
 
+import android.service.trust.GrantTrustResult
 import android.trust.BaseTrustAgentService
 import android.trust.TrustTestActivity
 import android.trust.test.lib.LockStateTrackingRule
@@ -25,11 +26,13 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
 import androidx.test.uiautomator.UiDevice
+import com.android.server.testutils.mock
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
+import org.mockito.Mockito.verifyZeroInteractions
 
 /**
  * Test for testing revokeTrust & grantTrust for non-renewable trust.
@@ -66,7 +69,7 @@
 
     @Test
     fun grantKeepsDeviceUnlocked() {
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0)
+        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {}
         uiDevice.sleep()
 
         lockStateTrackingRule.assertUnlocked()
@@ -74,7 +77,7 @@
 
     @Test
     fun grantKeepsDeviceUnlocked_untilRevoked() {
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0)
+        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0) {}
         await()
         uiDevice.sleep()
         trustAgentRule.agent.revokeTrust()
@@ -82,6 +85,15 @@
         lockStateTrackingRule.assertLocked()
     }
 
+    @Test
+    fun grantDoesNotCallBack() {
+        val callback = mock<(GrantTrustResult) -> Unit>()
+        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0, callback)
+        await()
+
+        verifyZeroInteractions(callback)
+    }
+
     companion object {
         private const val TAG = "GrantAndRevokeTrustTest"
         private const val GRANT_MESSAGE = "granted by test"
diff --git a/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt b/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt
index 14c227b..3c6d54d 100644
--- a/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt
+++ b/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt
@@ -16,16 +16,20 @@
 
 package android.trust.test
 
+import android.service.trust.GrantTrustResult
+import android.service.trust.GrantTrustResult.STATUS_UNLOCKED_BY_GRANT
 import android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
 import android.trust.BaseTrustAgentService
 import android.trust.TrustTestActivity
 import android.trust.test.lib.LockStateTrackingRule
 import android.trust.test.lib.ScreenLockRule
 import android.trust.test.lib.TrustAgentRule
+import android.util.Log
 import androidx.test.ext.junit.rules.ActivityScenarioRule
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
 import androidx.test.uiautomator.UiDevice
+import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -70,7 +74,8 @@
         uiDevice.sleep()
         lockStateTrackingRule.assertLocked()
 
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
         uiDevice.wakeUp()
 
         lockStateTrackingRule.assertLocked()
@@ -78,7 +83,8 @@
 
     @Test
     fun grantTrustUnlockedDevice_deviceLocksOnScreenOff() {
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
         uiDevice.sleep()
 
         lockStateTrackingRule.assertLocked()
@@ -86,20 +92,48 @@
 
     @Test
     fun grantTrustLockedDevice_grantTrustOnLockedDeviceUnlocksDevice() {
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
         uiDevice.sleep()
 
         lockStateTrackingRule.assertLocked()
 
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
         uiDevice.wakeUp()
 
         lockStateTrackingRule.assertUnlocked()
     }
 
     @Test
+    fun grantTrustLockedDevice_callsBackWhenUnlocked() {
+        Log.i(TAG, "Granting renewable trust while unlocked")
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
+        await(1000)
+
+        Log.i(TAG, "Locking device")
+        uiDevice.sleep()
+
+        lockStateTrackingRule.assertLocked()
+
+        Log.i(TAG, "Renewing trust and unlocking")
+        var result: GrantTrustResult? = null
+        trustAgentRule.agent.grantTrust(
+                GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {
+            Log.i(TAG, "Callback received; status=${it.status}")
+            result = it
+        }
+        uiDevice.wakeUp()
+        lockStateTrackingRule.assertUnlocked()
+
+        assertThat(result?.status).isEqualTo(STATUS_UNLOCKED_BY_GRANT)
+    }
+
+    @Test
     fun grantTrustLockedDevice_revokeTrustPreventsSubsequentUnlock() {
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
         uiDevice.sleep()
 
         lockStateTrackingRule.assertLocked()
@@ -109,7 +143,8 @@
         uiDevice.wakeUp()
         await(500)
 
-        trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+        trustAgentRule.agent.grantTrust(
+            GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
 
         lockStateTrackingRule.assertLocked()
     }
diff --git a/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt b/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt
index f8783fb..8bd8340 100644
--- a/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt
+++ b/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt
@@ -32,7 +32,7 @@
 import org.junit.runner.RunWith
 
 /**
- * Test for testing the user unlock trigger.
+ * Test for the user unlock triggers.
  *
  * atest TrustTests:UserUnlockRequestTest
  */
@@ -53,13 +53,32 @@
     @Test
     fun reportUserRequestedUnlock_propagatesToAgent() {
         val oldCount = trustAgentRule.agent.onUserRequestedUnlockCallCount
-        trustManager.reportUserRequestedUnlock(userId)
+        trustManager.reportUserRequestedUnlock(userId, false)
         await()
 
         assertThat(trustAgentRule.agent.onUserRequestedUnlockCallCount)
             .isEqualTo(oldCount + 1)
     }
 
+    @Test
+    fun reportUserRequestedUnlock_propagatesToAgentWithDismissKeyguard() {
+        trustManager.reportUserRequestedUnlock(userId, true)
+        await()
+
+        assertThat(trustAgentRule.agent.lastCallDismissKeyguard)
+            .isTrue()
+    }
+
+    @Test
+    fun reportUserMayRequestUnlock_propagatesToAgent() {
+        val oldCount = trustAgentRule.agent.onUserMayRequestUnlockCallCount
+        trustManager.reportUserMayRequestUnlock(userId)
+        await()
+
+        assertThat(trustAgentRule.agent.onUserMayRequestUnlockCallCount)
+            .isEqualTo(oldCount + 1)
+    }
+
     companion object {
         private const val TAG = "UserUnlockRequestTest"
         private fun await() = Thread.sleep(250)
@@ -69,10 +88,20 @@
 class UserUnlockRequestTrustAgent : BaseTrustAgentService() {
     var onUserRequestedUnlockCallCount: Long = 0
         private set
+    var onUserMayRequestUnlockCallCount: Long = 0
+        private set
+    var lastCallDismissKeyguard: Boolean = false
+        private set
 
-    override fun onUserRequestedUnlock() {
-        Log.i(TAG, "onUserRequestedUnlock")
+    override fun onUserRequestedUnlock(dismissKeyguard: Boolean) {
+        Log.i(TAG, "onUserRequestedUnlock($dismissKeyguard)")
         onUserRequestedUnlockCallCount++
+        lastCallDismissKeyguard = dismissKeyguard
+    }
+
+    override fun onUserMayRequestUnlock() {
+        Log.i(TAG, "onUserMayRequestUnlock")
+        onUserMayRequestUnlockCallCount++
     }
 
     companion object {
diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt
index 834f212..00f457b 100644
--- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt
+++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt
@@ -56,12 +56,22 @@
         val maxWaits = 50
         var waitCount = 0
 
+        // First verify we get the call in LockState via TrustListener
         while ((lockState.locked == false) && waitCount < maxWaits) {
-            Log.i(TAG, "phone still locked, wait 50ms more ($waitCount)")
+            Log.i(TAG, "phone still unlocked (TrustListener), wait 50ms more ($waitCount)")
             Thread.sleep(50)
             waitCount++
         }
         assertThat(lockState.locked).isTrue()
+
+        // TODO(b/225231929): refactor checks into one loop and re-use for assertUnlocked
+        // Then verify we get the window manager locked
+        while (!windowManager.isKeyguardLocked && waitCount < maxWaits) {
+            Log.i(TAG, "phone still unlocked (WindowManager), wait 50ms more ($waitCount)")
+            Thread.sleep(50)
+            waitCount++
+        }
+        assertThat(windowManager.isKeyguardLocked).isTrue()
     }
 
     fun assertUnlocked() {
diff --git a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt
index 006525d..127653d 100644
--- a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt
+++ b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt
@@ -69,6 +69,17 @@
         while (windowManager.isKeyguardLocked && waitCount < maxWaits) {
             Log.i(TAG, "Keyguard still showing; attempting to dismiss and wait 50ms ($waitCount)")
             windowManager.dismissKeyguard(null, null)
+
+            // Sometimes, bouncer gets shown due to a race, so we have to put display to sleep
+            // and wake it back up to get it to go away
+            if (waitCount >= 10 && waitCount % 5 == 0) {
+                Log.i(TAG, "Escalation: attempting screen off/on to get rid of bouncer (+500ms)")
+                uiDevice.sleep()
+                Thread.sleep(250)
+                uiDevice.wakeUp()
+                Thread.sleep(250)
+            }
+
             Thread.sleep(50)
             waitCount++
         }