Merge "Camera quick affordance respects device policy." into tm-qpr-dev

This commit is contained in:
Ale Nijamkin
2023-02-14 18:31:09 +00:00
committed by Android (Google) Code Review
4 changed files with 157 additions and 48 deletions

View File

@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.data.quickaffordance
import android.app.StatusBarManager
import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.pm.PackageManager
import com.android.systemui.R
@@ -27,10 +28,14 @@ import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.settings.UserTracker
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.withContext
@SysUISingleton
class CameraQuickAffordanceConfig
@@ -39,6 +44,9 @@ constructor(
@Application private val context: Context,
private val packageManager: PackageManager,
private val cameraGestureHelper: Lazy<CameraGestureHelper>,
private val userTracker: UserTracker,
private val devicePolicyManager: DevicePolicyManager,
@Background private val backgroundDispatcher: CoroutineDispatcher,
) : KeyguardQuickAffordanceConfig {
override val key: String
@@ -79,7 +87,12 @@ constructor(
return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
}
private fun isLaunchable(): Boolean {
return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
private suspend fun isLaunchable(): Boolean {
return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) &&
withContext(backgroundDispatcher) {
!devicePolicyManager.getCameraDisabled(null, userTracker.userId) &&
devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId) and
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA == 0
}
}
}

View File

@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.data.quickaffordance
import android.app.StatusBarManager
import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.Intent
import com.android.systemui.ActivityIntentHelper
@@ -29,10 +30,13 @@ import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withContext
@SysUISingleton
class VideoCameraQuickAffordanceConfig
@@ -42,6 +46,8 @@ constructor(
private val cameraIntents: CameraIntentsWrapper,
private val activityIntentHelper: ActivityIntentHelper,
private val userTracker: UserTracker,
private val devicePolicyManager: DevicePolicyManager,
@Background private val backgroundDispatcher: CoroutineDispatcher,
) : KeyguardQuickAffordanceConfig {
private val intent: Intent by lazy {
@@ -63,8 +69,8 @@ constructor(
get() = R.drawable.ic_videocam
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
get() =
flowOf(
get() = flow {
emit(
if (isLaunchable()) {
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
icon =
@@ -77,6 +83,7 @@ constructor(
KeyguardQuickAffordanceConfig.LockScreenState.Hidden
}
)
}
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return if (isLaunchable()) {
@@ -95,11 +102,14 @@ constructor(
)
}
private fun isLaunchable(): Boolean {
private suspend fun isLaunchable(): Boolean {
return activityIntentHelper.getTargetActivityInfo(
intent,
userTracker.userId,
true,
) != null
) != null &&
withContext(backgroundDispatcher) {
!devicePolicyManager.getCameraDisabled(null, userTracker.userId)
}
}
}

View File

@@ -18,15 +18,19 @@
package com.android.systemui.keyguard.data.quickaffordance
import android.app.StatusBarManager
import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.pm.PackageManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.camera.CameraGestureHelper
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -44,21 +48,28 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
@Mock private lateinit var cameraGestureHelper: CameraGestureHelper
@Mock private lateinit var context: Context
@Mock private lateinit var packageManager: PackageManager
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var underTest: CameraQuickAffordanceConfig
private lateinit var testScope: TestScope
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
setLaunchable(true)
setLaunchable()
val testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
underTest =
CameraQuickAffordanceConfig(
context,
packageManager,
) {
cameraGestureHelper
}
{ cameraGestureHelper },
userTracker,
devicePolicyManager,
testDispatcher,
)
}
@Test
@@ -73,23 +84,57 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
fun `getPickerScreenState - default when launchable`() = runTest {
setLaunchable(true)
fun `getPickerScreenState - default when launchable`() =
testScope.runTest {
setLaunchable(true)
Truth.assertThat(underTest.getPickerScreenState())
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
}
Truth.assertThat(underTest.getPickerScreenState())
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
}
@Test
fun `getPickerScreenState - unavailable when not launchable`() = runTest {
setLaunchable(false)
fun `getPickerScreenState - unavailable when camera app not installed`() =
testScope.runTest {
setLaunchable(isCameraAppInstalled = false)
Truth.assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
Truth.assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
private fun setLaunchable(isLaunchable: Boolean) {
@Test
fun `getPickerScreenState - unavailable when camera disabled by admin`() =
testScope.runTest {
setLaunchable(isCameraDisabledByDeviceAdmin = true)
Truth.assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
@Test
fun `getPickerScreenState - unavailable when secure camera disabled by admin`() =
testScope.runTest {
setLaunchable(isSecureCameraDisabledByDeviceAdmin = true)
Truth.assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
private fun setLaunchable(
isCameraAppInstalled: Boolean = true,
isCameraDisabledByDeviceAdmin: Boolean = false,
isSecureCameraDisabledByDeviceAdmin: Boolean = false,
) {
whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY))
.thenReturn(isLaunchable)
.thenReturn(isCameraAppInstalled)
whenever(devicePolicyManager.getCameraDisabled(null, userTracker.userId))
.thenReturn(isCameraDisabledByDeviceAdmin)
whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
.thenReturn(
if (isSecureCameraDisabledByDeviceAdmin) {
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
} else {
0
}
)
}
}

View File

@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data.quickaffordance
import android.app.admin.DevicePolicyManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.ActivityIntentHelper
@@ -24,11 +25,14 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.camera.CameraIntentsWrapper
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -44,59 +48,94 @@ import org.mockito.MockitoAnnotations
class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
@Mock private lateinit var activityIntentHelper: ActivityIntentHelper
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var underTest: VideoCameraQuickAffordanceConfig
private lateinit var userTracker: UserTracker
private lateinit var testScope: TestScope
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
val testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
userTracker = FakeUserTracker()
underTest =
VideoCameraQuickAffordanceConfig(
context = context,
cameraIntents = CameraIntentsWrapper(context),
activityIntentHelper = activityIntentHelper,
userTracker = FakeUserTracker(),
userTracker = userTracker,
devicePolicyManager = devicePolicyManager,
backgroundDispatcher = testDispatcher,
)
}
@Test
fun `lockScreenState - visible when launchable`() = runTest {
setLaunchable(true)
fun `lockScreenState - visible when launchable`() =
testScope.runTest {
setLaunchable()
val lockScreenState = collectLastValue(underTest.lockScreenState)
val lockScreenState = collectLastValue(underTest.lockScreenState)
assertThat(lockScreenState())
.isInstanceOf(KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java)
}
assertThat(lockScreenState())
.isInstanceOf(KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java)
}
@Test
fun `lockScreenState - hidden when not launchable`() = runTest {
setLaunchable(false)
fun `lockScreenState - hidden when app not installed on device`() =
testScope.runTest {
setLaunchable(isVideoCameraAppInstalled = false)
val lockScreenState = collectLastValue(underTest.lockScreenState)
val lockScreenState = collectLastValue(underTest.lockScreenState)
assertThat(lockScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
}
assertThat(lockScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
}
@Test
fun `getPickerScreenState - default when launchable`() = runTest {
setLaunchable(true)
fun `lockScreenState - hidden when camera disabled by admin`() =
testScope.runTest {
setLaunchable(isCameraDisabledByAdmin = true)
assertThat(underTest.getPickerScreenState())
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
}
val lockScreenState = collectLastValue(underTest.lockScreenState)
assertThat(lockScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
}
@Test
fun `getPickerScreenState - unavailable when not launchable`() = runTest {
setLaunchable(false)
fun `getPickerScreenState - default when launchable`() =
testScope.runTest {
setLaunchable()
assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
assertThat(underTest.getPickerScreenState())
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
}
private fun setLaunchable(isLaunchable: Boolean) {
@Test
fun `getPickerScreenState - unavailable when app not installed on device`() =
testScope.runTest {
setLaunchable(isVideoCameraAppInstalled = false)
assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
@Test
fun `getPickerScreenState - unavailable when camera disabled by admin`() =
testScope.runTest {
setLaunchable(isCameraDisabledByAdmin = true)
assertThat(underTest.getPickerScreenState())
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
}
private fun setLaunchable(
isVideoCameraAppInstalled: Boolean = true,
isCameraDisabledByAdmin: Boolean = false,
) {
whenever(
activityIntentHelper.getTargetActivityInfo(
any(),
@@ -105,11 +144,13 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
)
)
.thenReturn(
if (isLaunchable) {
if (isVideoCameraAppInstalled) {
mock()
} else {
null
}
)
whenever(devicePolicyManager.getCameraDisabled(null, userTracker.userId))
.thenReturn(isCameraDisabledByAdmin)
}
}