diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 15b63ec9356ef84ed758f124b2ffb106a1459e8e..a3f3ff5f79f0b6bd3bbdd91fab91a09600153d8f 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -870,7 +870,12 @@ public class TrustManagerService extends SystemService { continue; } - boolean trusted = aggregateIsTrusted(id); + final boolean trusted; + if (android.security.Flags.fixUnlockedDeviceRequiredKeys()) { + trusted = getUserTrustStateInner(id) == TrustState.TRUSTED; + } else { + trusted = aggregateIsTrusted(id); + } boolean showingKeyguard = true; boolean biometricAuthenticated = false; boolean currentUserIsUnlocked = false; diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp index a1b888aef9344f7d360c54be04998442f9d51906..c216bced81f00ebc3fb5356d9cda50a815d45366 100644 --- a/tests/TrustTests/Android.bp +++ b/tests/TrustTests/Android.bp @@ -25,6 +25,7 @@ android_test { "androidx.test.rules", "androidx.test.ext.junit", "androidx.test.uiautomator_uiautomator", + "flag-junit", "mockito-target-minus-junit4", "servicestests-utils", "truth-prebuilt", diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt index a7b8c4faba45b6a20b77522fd1f6382886d70ab9..1dfd5c06167b50ba31895268be54b7b5ffc06ad9 100644 --- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt @@ -16,6 +16,10 @@ package android.trust.test +import android.content.pm.PackageManager +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.service.trust.GrantTrustResult import android.trust.BaseTrustAgentService import android.trust.TrustTestActivity @@ -27,6 +31,7 @@ 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.Assume.assumeFalse import org.junit.Before import org.junit.Rule import org.junit.Test @@ -45,6 +50,7 @@ class GrantAndRevokeTrustTest { private val activityScenarioRule = ActivityScenarioRule(TrustTestActivity::class.java) private val lockStateTrackingRule = LockStateTrackingRule() private val trustAgentRule = TrustAgentRule<GrantAndRevokeTrustAgent>() + private val packageManager = getInstrumentation().getTargetContext().getPackageManager() @get:Rule val rule: RuleChain = RuleChain @@ -52,6 +58,7 @@ class GrantAndRevokeTrustTest { .around(ScreenLockRule()) .around(lockStateTrackingRule) .around(trustAgentRule) + .around(DeviceFlagsValueProvider.createCheckFlagsRule()) @Before fun manageTrust() { @@ -85,6 +92,51 @@ class GrantAndRevokeTrustTest { lockStateTrackingRule.assertLocked() } + @Test + @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + fun grantCannotActivelyUnlockDevice() { + // On automotive, trust agents can actively unlock the device. + assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) + + // Lock the device. + uiDevice.sleep() + lockStateTrackingRule.assertLocked() + + // Grant trust. + trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {} + + // The grant should not have unlocked the device. Wait a bit so that + // TrustManagerService probably will have finished processing the grant. + await() + lockStateTrackingRule.assertLocked() + + // Turn the screen on and off to cause TrustManagerService to refresh + // its deviceLocked state. Then verify the state is still locked. This + // part failed before the fix for b/296464083. + uiDevice.wakeUp() + uiDevice.sleep() + await() + lockStateTrackingRule.assertLocked() + } + + @Test + @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + fun grantCouldCauseWrongDeviceLockedStateDueToBug() { + // On automotive, trust agents can actively unlock the device. + assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) + + // Verify that b/296464083 exists. That is, when the device is locked + // and a trust agent grants trust, the deviceLocked state incorrectly + // becomes false even though the device correctly remains locked. + uiDevice.sleep() + lockStateTrackingRule.assertLocked() + trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {} + uiDevice.wakeUp() + uiDevice.sleep() + await() + lockStateTrackingRule.assertUnlockedButNotReally() + } + @Test fun grantDoesNotCallBack() { val callback = mock<(GrantTrustResult) -> Unit>() diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt index afcd1d3194f809598a553d50e5b108fa4d25c4ef..583cfc781bd01fed8c45c571cd8dd3c57d8faa77 100644 --- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt @@ -64,6 +64,13 @@ class LockStateTrackingRule : TestRule { wait("not trusted") { trustState.trusted == false } } + // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS + fun assertUnlockedButNotReally() { + wait("device unlocked") { !keyguardManager.isDeviceLocked } + wait("not trusted") { trustState.trusted == false } + wait("keyguard locked") { windowManager.isKeyguardLocked } + } + fun assertUnlockedAndTrusted() { wait("device unlocked") { !keyguardManager.isDeviceLocked } wait("trusted") { trustState.trusted == true }