[Partial Screensharing] Support enterprise policy
Implemented recent tasks filtering, removed the feature flag, and update the unit tests. Fixes: 263950746 Test: MediaProjectionAppSelectorControllerTest Change-Id: Ie91947481f93a84ba851bc36afd663c0e9e82fb7
This commit is contained in:
@@ -38,8 +38,6 @@ import com.android.internal.app.ResolverListController
|
||||
import com.android.internal.app.chooser.NotSelectableTargetInfo
|
||||
import com.android.internal.app.chooser.TargetInfo
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorComponent
|
||||
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController
|
||||
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
|
||||
@@ -53,7 +51,6 @@ import javax.inject.Inject
|
||||
class MediaProjectionAppSelectorActivity(
|
||||
private val componentFactory: MediaProjectionAppSelectorComponent.Factory,
|
||||
private val activityLauncher: AsyncActivityLauncher,
|
||||
private val featureFlags: FeatureFlags,
|
||||
/** This is used to override the dependency in a screenshot test */
|
||||
@VisibleForTesting
|
||||
private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)?
|
||||
@@ -62,9 +59,8 @@ class MediaProjectionAppSelectorActivity(
|
||||
@Inject
|
||||
constructor(
|
||||
componentFactory: MediaProjectionAppSelectorComponent.Factory,
|
||||
activityLauncher: AsyncActivityLauncher,
|
||||
featureFlags: FeatureFlags
|
||||
) : this(componentFactory, activityLauncher, featureFlags, listControllerFactory = null)
|
||||
activityLauncher: AsyncActivityLauncher
|
||||
) : this(componentFactory, activityLauncher, listControllerFactory = null)
|
||||
|
||||
private lateinit var configurationController: ConfigurationController
|
||||
private lateinit var controller: MediaProjectionAppSelectorController
|
||||
@@ -108,11 +104,7 @@ class MediaProjectionAppSelectorActivity(
|
||||
override fun appliedThemeResId(): Int = R.style.Theme_SystemUI_MediaProjectionAppSelector
|
||||
|
||||
override fun createBlockerEmptyStateProvider(): EmptyStateProvider =
|
||||
if (featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
|
||||
component.emptyStateProvider
|
||||
} else {
|
||||
object : EmptyStateProvider {}
|
||||
}
|
||||
component.emptyStateProvider
|
||||
|
||||
override fun createListController(userHandle: UserHandle): ResolverListController =
|
||||
listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)
|
||||
|
||||
@@ -18,9 +18,9 @@ package com.android.systemui.mediaprojection.appselector
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.os.UserHandle
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.mediaprojection.appselector.data.RecentTask
|
||||
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
|
||||
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.cancel
|
||||
@@ -32,7 +32,7 @@ class MediaProjectionAppSelectorController
|
||||
constructor(
|
||||
private val recentTaskListProvider: RecentTaskListProvider,
|
||||
private val view: MediaProjectionAppSelectorView,
|
||||
private val flags: FeatureFlags,
|
||||
private val devicePolicyResolver: ScreenCaptureDevicePolicyResolver,
|
||||
@HostUserHandle private val hostUserHandle: UserHandle,
|
||||
@MediaProjectionAppSelector private val scope: CoroutineScope,
|
||||
@MediaProjectionAppSelector private val appSelectorComponentName: ComponentName,
|
||||
@@ -54,11 +54,13 @@ constructor(
|
||||
scope.cancel()
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all recent tasks that are different from the profile of the host app to avoid any
|
||||
* cross-profile sharing
|
||||
*/
|
||||
private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = this
|
||||
/** Removes all recent tasks that should be blocked according to the policy */
|
||||
private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = filter {
|
||||
devicePolicyResolver.isScreenCaptureAllowed(
|
||||
targetAppUserHandle = UserHandle.of(it.userId),
|
||||
hostAppUserHandle = hostUserHandle
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<RecentTask>.filterAppSelector(): List<RecentTask> = filter {
|
||||
// Only take tasks that is not the app selector
|
||||
|
||||
@@ -47,7 +47,7 @@ constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
if (!hostAppUserHandle.isWorkProfile() && personalProfileScreenCaptureDisabled) {
|
||||
if (personalProfileScreenCaptureDisabled) {
|
||||
// Disable screen capturing as personal apps should not capture the screen
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -5,14 +5,15 @@ import android.os.UserHandle
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.mediaprojection.appselector.data.RecentTask
|
||||
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
|
||||
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.verify
|
||||
@@ -27,23 +28,28 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() {
|
||||
private val callerPackageName = "com.test.caller"
|
||||
private val callerComponentName = ComponentName(callerPackageName, "Caller")
|
||||
|
||||
private val hostUserHandle = UserHandle.of(123)
|
||||
private val otherUserHandle = UserHandle.of(456)
|
||||
private val personalUserHandle = UserHandle.of(123)
|
||||
private val workUserHandle = UserHandle.of(456)
|
||||
|
||||
private val view: MediaProjectionAppSelectorView = mock()
|
||||
private val featureFlags: FeatureFlags = mock()
|
||||
private val policyResolver: ScreenCaptureDevicePolicyResolver = mock()
|
||||
|
||||
private val controller =
|
||||
MediaProjectionAppSelectorController(
|
||||
taskListProvider,
|
||||
view,
|
||||
featureFlags,
|
||||
hostUserHandle,
|
||||
policyResolver,
|
||||
personalUserHandle,
|
||||
scope,
|
||||
appSelectorComponentName,
|
||||
callerPackageName
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
givenCaptureAllowed(isAllow = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun initNoRecentTasks_bindsEmptyList() {
|
||||
taskListProvider.tasks = emptyList()
|
||||
@@ -132,73 +138,57 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesDisabled_bindsAllTasks() {
|
||||
givenEnterprisePoliciesFeatureFlag(enabled = false)
|
||||
|
||||
fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_bindsAllTasks() {
|
||||
val tasks =
|
||||
listOf(
|
||||
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = workUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = workUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
|
||||
)
|
||||
taskListProvider.tasks = tasks
|
||||
|
||||
controller.init()
|
||||
|
||||
// TODO (b/263950746): Cross-profile filtering is removed for now. This should be brought
|
||||
// back with the future fix
|
||||
verify(view)
|
||||
.bind(
|
||||
listOf(
|
||||
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = workUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = workUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() {
|
||||
givenEnterprisePoliciesFeatureFlag(enabled = true)
|
||||
|
||||
fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_blocksAllTasks() {
|
||||
val tasks =
|
||||
listOf(
|
||||
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = workUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = workUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
|
||||
)
|
||||
taskListProvider.tasks = tasks
|
||||
|
||||
givenCaptureAllowed(isAllow = false)
|
||||
controller.init()
|
||||
|
||||
// TODO(b/233348916) should filter depending on the policies
|
||||
verify(view)
|
||||
.bind(
|
||||
listOf(
|
||||
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||
)
|
||||
)
|
||||
verify(view).bind(emptyList())
|
||||
}
|
||||
|
||||
private fun givenEnterprisePoliciesFeatureFlag(enabled: Boolean) {
|
||||
whenever(featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES))
|
||||
.thenReturn(enabled)
|
||||
private fun givenCaptureAllowed(isAllow: Boolean) {
|
||||
whenever(policyResolver.isScreenCaptureAllowed(any(), any())).thenReturn(isAllow)
|
||||
}
|
||||
|
||||
private fun createRecentTask(
|
||||
taskId: Int,
|
||||
topActivityComponent: ComponentName? = null,
|
||||
userId: Int = hostUserHandle.identifier
|
||||
userId: Int = personalUserHandle.identifier
|
||||
): RecentTask {
|
||||
return RecentTask(
|
||||
taskId = taskId,
|
||||
|
||||
@@ -400,28 +400,6 @@ class IsAllowedScreenCaptureDevicePolicyResolverTest(
|
||||
),
|
||||
expectedScreenCaptureAllowed = false,
|
||||
),
|
||||
IsScreenCaptureAllowedTestCase(
|
||||
given =
|
||||
Preconditions(
|
||||
isHostInWorkProfile = true,
|
||||
isTargetInWorkProfile = true,
|
||||
personalScreenCaptureDisabled = true,
|
||||
workScreenCaptureDisabled = false,
|
||||
disallowShareIntoManagedProfile = false
|
||||
),
|
||||
expectedScreenCaptureAllowed = true,
|
||||
),
|
||||
IsScreenCaptureAllowedTestCase(
|
||||
given =
|
||||
Preconditions(
|
||||
isHostInWorkProfile = true,
|
||||
isTargetInWorkProfile = true,
|
||||
personalScreenCaptureDisabled = true,
|
||||
workScreenCaptureDisabled = false,
|
||||
disallowShareIntoManagedProfile = true
|
||||
),
|
||||
expectedScreenCaptureAllowed = true,
|
||||
),
|
||||
IsScreenCaptureAllowedTestCase(
|
||||
given =
|
||||
Preconditions(
|
||||
@@ -621,26 +599,6 @@ class IsCompletelyNotAllowedScreenCaptureDevicePolicyResolverTest(
|
||||
),
|
||||
expectedScreenCaptureCompletelyDisabled = true,
|
||||
),
|
||||
IsScreenCaptureCompletelyDisabledTestCase(
|
||||
given =
|
||||
Preconditions(
|
||||
isHostInWorkProfile = true,
|
||||
personalScreenCaptureDisabled = true,
|
||||
workScreenCaptureDisabled = false,
|
||||
disallowShareIntoManagedProfile = false
|
||||
),
|
||||
expectedScreenCaptureCompletelyDisabled = false,
|
||||
),
|
||||
IsScreenCaptureCompletelyDisabledTestCase(
|
||||
given =
|
||||
Preconditions(
|
||||
isHostInWorkProfile = true,
|
||||
personalScreenCaptureDisabled = true,
|
||||
workScreenCaptureDisabled = false,
|
||||
disallowShareIntoManagedProfile = true
|
||||
),
|
||||
expectedScreenCaptureCompletelyDisabled = false,
|
||||
),
|
||||
IsScreenCaptureCompletelyDisabledTestCase(
|
||||
given =
|
||||
Preconditions(
|
||||
@@ -686,7 +644,8 @@ class IsCompletelyNotAllowedScreenCaptureDevicePolicyResolverTest(
|
||||
"personal screen capture disabled = ${given.personalScreenCaptureDisabled}, " +
|
||||
"work screen capture disabled = ${given.workScreenCaptureDisabled}, " +
|
||||
"disallow share into managed profile = ${given.disallowShareIntoManagedProfile}, " +
|
||||
"expected screen capture completely disabled = $expectedScreenCaptureCompletelyDisabled"
|
||||
"expected screen capture completely disabled = " +
|
||||
"$expectedScreenCaptureCompletelyDisabled"
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user