Merge "[Partial Screensharing] Support enterprise policy" into udc-dev

This commit is contained in:
Yalan Yiue
2023-06-06 10:33:34 +00:00
committed by Android (Google) Code Review
5 changed files with 50 additions and 107 deletions

View File

@@ -38,8 +38,6 @@ import com.android.internal.app.ResolverListController
import com.android.internal.app.chooser.NotSelectableTargetInfo import com.android.internal.app.chooser.NotSelectableTargetInfo
import com.android.internal.app.chooser.TargetInfo import com.android.internal.app.chooser.TargetInfo
import com.android.systemui.R 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.MediaProjectionAppSelectorComponent
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
@@ -53,7 +51,6 @@ import javax.inject.Inject
class MediaProjectionAppSelectorActivity( class MediaProjectionAppSelectorActivity(
private val componentFactory: MediaProjectionAppSelectorComponent.Factory, private val componentFactory: MediaProjectionAppSelectorComponent.Factory,
private val activityLauncher: AsyncActivityLauncher, private val activityLauncher: AsyncActivityLauncher,
private val featureFlags: FeatureFlags,
/** This is used to override the dependency in a screenshot test */ /** This is used to override the dependency in a screenshot test */
@VisibleForTesting @VisibleForTesting
private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)? private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)?
@@ -62,9 +59,8 @@ class MediaProjectionAppSelectorActivity(
@Inject @Inject
constructor( constructor(
componentFactory: MediaProjectionAppSelectorComponent.Factory, componentFactory: MediaProjectionAppSelectorComponent.Factory,
activityLauncher: AsyncActivityLauncher, activityLauncher: AsyncActivityLauncher
featureFlags: FeatureFlags ) : this(componentFactory, activityLauncher, listControllerFactory = null)
) : this(componentFactory, activityLauncher, featureFlags, listControllerFactory = null)
private lateinit var configurationController: ConfigurationController private lateinit var configurationController: ConfigurationController
private lateinit var controller: MediaProjectionAppSelectorController private lateinit var controller: MediaProjectionAppSelectorController
@@ -108,11 +104,7 @@ class MediaProjectionAppSelectorActivity(
override fun appliedThemeResId(): Int = R.style.Theme_SystemUI_MediaProjectionAppSelector override fun appliedThemeResId(): Int = R.style.Theme_SystemUI_MediaProjectionAppSelector
override fun createBlockerEmptyStateProvider(): EmptyStateProvider = override fun createBlockerEmptyStateProvider(): EmptyStateProvider =
if (featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) { component.emptyStateProvider
component.emptyStateProvider
} else {
object : EmptyStateProvider {}
}
override fun createListController(userHandle: UserHandle): ResolverListController = override fun createListController(userHandle: UserHandle): ResolverListController =
listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle) listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)

View File

@@ -18,9 +18,9 @@ package com.android.systemui.mediaprojection.appselector
import android.content.ComponentName import android.content.ComponentName
import android.os.UserHandle 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.RecentTask
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@@ -32,7 +32,7 @@ class MediaProjectionAppSelectorController
constructor( constructor(
private val recentTaskListProvider: RecentTaskListProvider, private val recentTaskListProvider: RecentTaskListProvider,
private val view: MediaProjectionAppSelectorView, private val view: MediaProjectionAppSelectorView,
private val flags: FeatureFlags, private val devicePolicyResolver: ScreenCaptureDevicePolicyResolver,
@HostUserHandle private val hostUserHandle: UserHandle, @HostUserHandle private val hostUserHandle: UserHandle,
@MediaProjectionAppSelector private val scope: CoroutineScope, @MediaProjectionAppSelector private val scope: CoroutineScope,
@MediaProjectionAppSelector private val appSelectorComponentName: ComponentName, @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName,
@@ -54,11 +54,13 @@ constructor(
scope.cancel() scope.cancel()
} }
/** /** Removes all recent tasks that should be blocked according to the policy */
* Removes all recent tasks that are different from the profile of the host app to avoid any private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = filter {
* cross-profile sharing devicePolicyResolver.isScreenCaptureAllowed(
*/ targetAppUserHandle = UserHandle.of(it.userId),
private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = this hostAppUserHandle = hostUserHandle
)
}
private fun List<RecentTask>.filterAppSelector(): List<RecentTask> = filter { private fun List<RecentTask>.filterAppSelector(): List<RecentTask> = filter {
// Only take tasks that is not the app selector // Only take tasks that is not the app selector

View File

@@ -47,7 +47,7 @@ constructor(
return false return false
} }
if (!hostAppUserHandle.isWorkProfile() && personalProfileScreenCaptureDisabled) { if (personalProfileScreenCaptureDisabled) {
// Disable screen capturing as personal apps should not capture the screen // Disable screen capturing as personal apps should not capture the screen
return false return false
} }

View File

@@ -5,14 +5,15 @@ import android.os.UserHandle
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase 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.RecentTask
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider 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.mock
import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
@@ -27,23 +28,28 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() {
private val callerPackageName = "com.test.caller" private val callerPackageName = "com.test.caller"
private val callerComponentName = ComponentName(callerPackageName, "Caller") private val callerComponentName = ComponentName(callerPackageName, "Caller")
private val hostUserHandle = UserHandle.of(123) private val personalUserHandle = UserHandle.of(123)
private val otherUserHandle = UserHandle.of(456) private val workUserHandle = UserHandle.of(456)
private val view: MediaProjectionAppSelectorView = mock() private val view: MediaProjectionAppSelectorView = mock()
private val featureFlags: FeatureFlags = mock() private val policyResolver: ScreenCaptureDevicePolicyResolver = mock()
private val controller = private val controller =
MediaProjectionAppSelectorController( MediaProjectionAppSelectorController(
taskListProvider, taskListProvider,
view, view,
featureFlags, policyResolver,
hostUserHandle, personalUserHandle,
scope, scope,
appSelectorComponentName, appSelectorComponentName,
callerPackageName callerPackageName
) )
@Before
fun setup() {
givenCaptureAllowed(isAllow = true)
}
@Test @Test
fun initNoRecentTasks_bindsEmptyList() { fun initNoRecentTasks_bindsEmptyList() {
taskListProvider.tasks = emptyList() taskListProvider.tasks = emptyList()
@@ -132,73 +138,57 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() {
} }
@Test @Test
fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesDisabled_bindsAllTasks() { fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_bindsAllTasks() {
givenEnterprisePoliciesFeatureFlag(enabled = false)
val tasks = val tasks =
listOf( listOf(
createRecentTask(taskId = 1, userId = hostUserHandle.identifier), createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
createRecentTask(taskId = 2, userId = otherUserHandle.identifier), createRecentTask(taskId = 2, userId = workUserHandle.identifier),
createRecentTask(taskId = 3, userId = hostUserHandle.identifier), createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
createRecentTask(taskId = 4, userId = otherUserHandle.identifier), createRecentTask(taskId = 4, userId = workUserHandle.identifier),
createRecentTask(taskId = 5, userId = hostUserHandle.identifier), createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
) )
taskListProvider.tasks = tasks taskListProvider.tasks = tasks
controller.init() controller.init()
// TODO (b/263950746): Cross-profile filtering is removed for now. This should be brought
// back with the future fix
verify(view) verify(view)
.bind( .bind(
listOf( listOf(
createRecentTask(taskId = 1, userId = hostUserHandle.identifier), createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
createRecentTask(taskId = 2, userId = otherUserHandle.identifier), createRecentTask(taskId = 2, userId = workUserHandle.identifier),
createRecentTask(taskId = 3, userId = hostUserHandle.identifier), createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
createRecentTask(taskId = 4, userId = otherUserHandle.identifier), createRecentTask(taskId = 4, userId = workUserHandle.identifier),
createRecentTask(taskId = 5, userId = hostUserHandle.identifier), createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
) )
) )
} }
@Test @Test
fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() { fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_blocksAllTasks() {
givenEnterprisePoliciesFeatureFlag(enabled = true)
val tasks = val tasks =
listOf( listOf(
createRecentTask(taskId = 1, userId = hostUserHandle.identifier), createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
createRecentTask(taskId = 2, userId = otherUserHandle.identifier), createRecentTask(taskId = 2, userId = workUserHandle.identifier),
createRecentTask(taskId = 3, userId = hostUserHandle.identifier), createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
createRecentTask(taskId = 4, userId = otherUserHandle.identifier), createRecentTask(taskId = 4, userId = workUserHandle.identifier),
createRecentTask(taskId = 5, userId = hostUserHandle.identifier), createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
) )
taskListProvider.tasks = tasks taskListProvider.tasks = tasks
givenCaptureAllowed(isAllow = false)
controller.init() controller.init()
// TODO(b/233348916) should filter depending on the policies verify(view).bind(emptyList())
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),
)
)
} }
private fun givenEnterprisePoliciesFeatureFlag(enabled: Boolean) { private fun givenCaptureAllowed(isAllow: Boolean) {
whenever(featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) whenever(policyResolver.isScreenCaptureAllowed(any(), any())).thenReturn(isAllow)
.thenReturn(enabled)
} }
private fun createRecentTask( private fun createRecentTask(
taskId: Int, taskId: Int,
topActivityComponent: ComponentName? = null, topActivityComponent: ComponentName? = null,
userId: Int = hostUserHandle.identifier userId: Int = personalUserHandle.identifier
): RecentTask { ): RecentTask {
return RecentTask( return RecentTask(
taskId = taskId, taskId = taskId,

View File

@@ -400,28 +400,6 @@ class IsAllowedScreenCaptureDevicePolicyResolverTest(
), ),
expectedScreenCaptureAllowed = false, 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( IsScreenCaptureAllowedTestCase(
given = given =
Preconditions( Preconditions(
@@ -621,26 +599,6 @@ class IsCompletelyNotAllowedScreenCaptureDevicePolicyResolverTest(
), ),
expectedScreenCaptureCompletelyDisabled = true, 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( IsScreenCaptureCompletelyDisabledTestCase(
given = given =
Preconditions( Preconditions(
@@ -686,7 +644,8 @@ class IsCompletelyNotAllowedScreenCaptureDevicePolicyResolverTest(
"personal screen capture disabled = ${given.personalScreenCaptureDisabled}, " + "personal screen capture disabled = ${given.personalScreenCaptureDisabled}, " +
"work screen capture disabled = ${given.workScreenCaptureDisabled}, " + "work screen capture disabled = ${given.workScreenCaptureDisabled}, " +
"disallow share into managed profile = ${given.disallowShareIntoManagedProfile}, " + "disallow share into managed profile = ${given.disallowShareIntoManagedProfile}, " +
"expected screen capture completely disabled = $expectedScreenCaptureCompletelyDisabled" "expected screen capture completely disabled = " +
"$expectedScreenCaptureCompletelyDisabled"
} }
@Test @Test