Merge "[Partial Screensharing] Add enterprise policies resolver" into tm-qpr-dev
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index 1edb837..e665d83 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -34,8 +34,8 @@
import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider
import com.android.systemui.mediaprojection.appselector.view.MediaProjectionRecentsViewController
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.shared.system.ActivityManagerWrapper
+import com.android.systemui.mediaprojection.devicepolicy.MediaProjectionDevicePolicyModule
+import com.android.systemui.mediaprojection.devicepolicy.PersonalProfile
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl
import com.android.systemui.statusbar.policy.ConfigurationController
import dagger.Binds
@@ -54,13 +54,12 @@
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUserHandle
-@Qualifier @Retention(AnnotationRetention.BINARY) annotation class PersonalProfile
-
-@Qualifier @Retention(AnnotationRetention.BINARY) annotation class WorkProfile
-
@Retention(AnnotationRetention.RUNTIME) @Scope annotation class MediaProjectionAppSelectorScope
-@Module(subcomponents = [MediaProjectionAppSelectorComponent::class])
+@Module(
+ subcomponents = [MediaProjectionAppSelectorComponent::class],
+ includes = [MediaProjectionDevicePolicyModule::class]
+)
interface MediaProjectionModule {
@Binds
@IntoMap
@@ -110,20 +109,6 @@
): ConfigurationController = ConfigurationControllerImpl(activity)
@Provides
- @PersonalProfile
- @MediaProjectionAppSelectorScope
- fun personalUserHandle(activityManagerWrapper: ActivityManagerWrapper): UserHandle {
- // Current foreground user is the 'personal' profile
- return UserHandle.of(activityManagerWrapper.currentUserId)
- }
-
- @Provides
- @WorkProfile
- @MediaProjectionAppSelectorScope
- fun workProfileUserHandle(userTracker: UserTracker): UserHandle? =
- userTracker.userProfiles.find { it.isManagedProfile }?.userHandle
-
- @Provides
@HostUserHandle
@MediaProjectionAppSelectorScope
fun hostUserHandle(activity: MediaProjectionAppSelectorActivity): UserHandle {
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt
new file mode 100644
index 0000000..829b0dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.mediaprojection.appselector
+
+import android.content.Context
+import android.os.UserHandle
+import com.android.internal.R as AndroidR
+import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState
+import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider
+import com.android.internal.app.ResolverListAdapter
+import com.android.systemui.R
+import com.android.systemui.mediaprojection.devicepolicy.PersonalProfile
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
+import javax.inject.Inject
+
+@MediaProjectionAppSelectorScope
+class MediaProjectionBlockerEmptyStateProvider
+@Inject
+constructor(
+ @HostUserHandle private val hostAppHandle: UserHandle,
+ @PersonalProfile private val personalProfileHandle: UserHandle,
+ private val policyResolver: ScreenCaptureDevicePolicyResolver,
+ private val context: Context
+) : EmptyStateProvider {
+
+ override fun getEmptyState(resolverListAdapter: ResolverListAdapter): EmptyState? {
+ val screenCaptureAllowed =
+ policyResolver.isScreenCaptureAllowed(
+ targetAppUserHandle = resolverListAdapter.userHandle,
+ hostAppUserHandle = hostAppHandle
+ )
+
+ val isHostAppInPersonalProfile = hostAppHandle == personalProfileHandle
+
+ val subtitle =
+ if (isHostAppInPersonalProfile) {
+ AndroidR.string.resolver_cant_share_with_personal_apps_explanation
+ } else {
+ AndroidR.string.resolver_cant_share_with_work_apps_explanation
+ }
+
+ if (!screenCaptureAllowed) {
+ return object : EmptyState {
+ override fun getSubtitle(): String = context.resources.getString(subtitle)
+ override fun getTitle(): String =
+ context.resources.getString(
+ R.string.screen_capturing_disabled_by_policy_dialog_title
+ )
+ override fun onEmptyStateShown() {
+ // TODO(b/237397740) report analytics
+ }
+ override fun shouldSkipDataRebuild(): Boolean = true
+ }
+ }
+ return null
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/MediaProjectionDevicePolicyModule.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/MediaProjectionDevicePolicyModule.kt
new file mode 100644
index 0000000..13b71a7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/MediaProjectionDevicePolicyModule.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.mediaprojection.devicepolicy
+
+import android.os.UserHandle
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shared.system.ActivityManagerWrapper
+import dagger.Module
+import dagger.Provides
+import javax.inject.Qualifier
+
+@Qualifier @Retention(AnnotationRetention.BINARY) annotation class WorkProfile
+
+@Qualifier @Retention(AnnotationRetention.BINARY) annotation class PersonalProfile
+
+/** Module for media projection device policy related dependencies */
+@Module
+class MediaProjectionDevicePolicyModule {
+ @Provides
+ @PersonalProfile
+ fun personalUserHandle(activityManagerWrapper: ActivityManagerWrapper): UserHandle {
+ // Current foreground user is the 'personal' profile
+ return UserHandle.of(activityManagerWrapper.currentUserId)
+ }
+
+ @Provides
+ @WorkProfile
+ fun workProfileUserHandle(userTracker: UserTracker): UserHandle? =
+ userTracker.userProfiles.find { it.isManagedProfile }?.userHandle
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
new file mode 100644
index 0000000..6bd33e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.mediaprojection.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.os.UserHandle
+import android.os.UserManager
+import javax.inject.Inject
+
+/**
+ * Utility class to resolve if screen capture allowed for a particular target app/host app pair. It
+ * caches the state of the policies, so you need to create a new instance of this class if you want
+ * to react to updated policies state.
+ */
+class ScreenCaptureDevicePolicyResolver
+@Inject
+constructor(
+ private val devicePolicyManager: DevicePolicyManager,
+ private val userManager: UserManager,
+ @PersonalProfile private val personalProfileUserHandle: UserHandle,
+ @WorkProfile private val workProfileUserHandle: UserHandle?
+) {
+
+ /**
+ * Returns true if [hostAppUserHandle] is allowed to perform screen capture of
+ * [targetAppUserHandle]
+ */
+ fun isScreenCaptureAllowed(
+ targetAppUserHandle: UserHandle,
+ hostAppUserHandle: UserHandle,
+ ): Boolean {
+ if (hostAppUserHandle.isWorkProfile() && workProfileScreenCaptureDisabled) {
+ // Disable screen capturing as host apps should not capture the screen
+ return false
+ }
+
+ if (!hostAppUserHandle.isWorkProfile() && personalProfileScreenCaptureDisabled) {
+ // Disable screen capturing as personal apps should not capture the screen
+ return false
+ }
+
+ if (targetAppUserHandle.isWorkProfile()) {
+ // Work profile target
+ if (workProfileScreenCaptureDisabled) {
+ // Do not allow sharing work profile apps as work profile capturing is disabled
+ return false
+ }
+ } else {
+ // Personal profile target
+ if (hostAppUserHandle.isWorkProfile() && disallowSharingIntoManagedProfile) {
+ // Do not allow sharing of personal apps into work profile apps
+ return false
+ }
+
+ if (personalProfileScreenCaptureDisabled) {
+ // Disable screen capturing as personal apps should not be captured
+ return false
+ }
+ }
+
+ return true
+ }
+
+ /**
+ * Returns true if [hostAppUserHandle] is NOT allowed to capture an app from any profile,
+ * could be useful to finish the screen capture flow as soon as possible when the screen
+ * could not be captured at all.
+ */
+ fun isScreenCaptureCompletelyDisabled(hostAppUserHandle: UserHandle): Boolean {
+ val isWorkAppsCaptureDisabled =
+ if (workProfileUserHandle != null) {
+ !isScreenCaptureAllowed(
+ targetAppUserHandle = workProfileUserHandle,
+ hostAppUserHandle = hostAppUserHandle
+ )
+ } else true
+
+ val isPersonalAppsCaptureDisabled =
+ !isScreenCaptureAllowed(
+ targetAppUserHandle = personalProfileUserHandle,
+ hostAppUserHandle = hostAppUserHandle
+ )
+
+ return isWorkAppsCaptureDisabled && isPersonalAppsCaptureDisabled
+ }
+
+ private val personalProfileScreenCaptureDisabled: Boolean by lazy {
+ devicePolicyManager.getScreenCaptureDisabled(
+ /* admin */ null,
+ personalProfileUserHandle.identifier
+ )
+ }
+
+ private val workProfileScreenCaptureDisabled: Boolean by lazy {
+ workProfileUserHandle?.let {
+ devicePolicyManager.getScreenCaptureDisabled(/* admin */ null, it.identifier)
+ }
+ ?: false
+ }
+
+ private val disallowSharingIntoManagedProfile: Boolean by lazy {
+ workProfileUserHandle?.let {
+ userManager.hasUserRestrictionForUser(
+ UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,
+ it
+ )
+ }
+ ?: false
+ }
+
+ private fun UserHandle?.isWorkProfile(): Boolean = this == workProfileUserHandle
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDisabledDialog.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDisabledDialog.kt
new file mode 100644
index 0000000..a6b3da0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDisabledDialog.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.mediaprojection.devicepolicy
+
+import android.content.Context
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+
+/** Dialog that shows that screen capture is disabled on this device. */
+class ScreenCaptureDisabledDialog(context: Context) : SystemUIDialog(context) {
+
+ init {
+ setTitle(context.getString(R.string.screen_capturing_disabled_by_policy_dialog_title))
+ setMessage(
+ context.getString(R.string.screen_capturing_disabled_by_policy_dialog_description)
+ )
+ setIcon(R.drawable.ic_cast)
+ setButton(BUTTON_POSITIVE, context.getString(android.R.string.ok)) { _, _ -> cancel() }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
new file mode 100644
index 0000000..e8b6f9b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
@@ -0,0 +1,703 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.mediaprojection.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.os.UserHandle
+import android.os.UserManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.Parameterized.Parameters
+import org.mockito.ArgumentMatchers.any
+
+abstract class BaseScreenCaptureDevicePolicyResolverTest(private val precondition: Preconditions) :
+ SysuiTestCase() {
+
+ abstract class Preconditions(
+ val personalScreenCaptureDisabled: Boolean,
+ val workScreenCaptureDisabled: Boolean,
+ val disallowShareIntoManagedProfile: Boolean
+ )
+
+ protected val devicePolicyManager: DevicePolicyManager = mock()
+ protected val userManager: UserManager = mock()
+
+ protected val personalUserHandle: UserHandle = UserHandle.of(123)
+ protected val workUserHandle: UserHandle = UserHandle.of(456)
+
+ protected val policyResolver =
+ ScreenCaptureDevicePolicyResolver(
+ devicePolicyManager,
+ userManager,
+ personalUserHandle,
+ workUserHandle
+ )
+
+ @Before
+ fun setUp() {
+ setUpPolicies()
+ }
+
+ private fun setUpPolicies() {
+ whenever(
+ devicePolicyManager.getScreenCaptureDisabled(
+ any(),
+ eq(personalUserHandle.identifier)
+ )
+ )
+ .thenReturn(precondition.personalScreenCaptureDisabled)
+
+ whenever(devicePolicyManager.getScreenCaptureDisabled(any(), eq(workUserHandle.identifier)))
+ .thenReturn(precondition.workScreenCaptureDisabled)
+
+ whenever(
+ userManager.hasUserRestrictionForUser(
+ eq(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE),
+ eq(workUserHandle)
+ )
+ )
+ .thenReturn(precondition.disallowShareIntoManagedProfile)
+ }
+}
+
+@RunWith(Parameterized::class)
+@SmallTest
+class IsAllowedScreenCaptureDevicePolicyResolverTest(
+ private val test: IsScreenCaptureAllowedTestCase
+) : BaseScreenCaptureDevicePolicyResolverTest(test.given) {
+
+ companion object {
+ @Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams() =
+ listOf(
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false,
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true,
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false,
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true,
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = true,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ 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(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ IsScreenCaptureAllowedTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ isTargetInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureAllowed = false,
+ ),
+ )
+ }
+
+ class Preconditions(
+ personalScreenCaptureDisabled: Boolean,
+ workScreenCaptureDisabled: Boolean,
+ disallowShareIntoManagedProfile: Boolean,
+ val isHostInWorkProfile: Boolean,
+ val isTargetInWorkProfile: Boolean,
+ ) :
+ BaseScreenCaptureDevicePolicyResolverTest.Preconditions(
+ personalScreenCaptureDisabled,
+ workScreenCaptureDisabled,
+ disallowShareIntoManagedProfile
+ )
+
+ data class IsScreenCaptureAllowedTestCase(
+ val given: Preconditions,
+ val expectedScreenCaptureAllowed: Boolean
+ ) {
+ override fun toString(): String =
+ "isScreenCaptureAllowed: " +
+ "host[${if (given.isHostInWorkProfile) "work" else "personal"} profile], " +
+ "target[${if (given.isTargetInWorkProfile) "work" else "personal"} profile], " +
+ "personal screen capture disabled = ${given.personalScreenCaptureDisabled}, " +
+ "work screen capture disabled = ${given.workScreenCaptureDisabled}, " +
+ "disallow share into managed profile = ${given.disallowShareIntoManagedProfile}, " +
+ "expected screen capture allowed = $expectedScreenCaptureAllowed"
+ }
+
+ @Test
+ fun test() {
+ val targetAppUserHandle =
+ if (test.given.isTargetInWorkProfile) workUserHandle else personalUserHandle
+ val hostAppUserHandle =
+ if (test.given.isHostInWorkProfile) workUserHandle else personalUserHandle
+
+ val screenCaptureAllowed =
+ policyResolver.isScreenCaptureAllowed(targetAppUserHandle, hostAppUserHandle)
+
+ assertWithMessage("Screen capture policy resolved incorrectly")
+ .that(screenCaptureAllowed)
+ .isEqualTo(test.expectedScreenCaptureAllowed)
+ }
+}
+
+@RunWith(Parameterized::class)
+@SmallTest
+class IsCompletelyNotAllowedScreenCaptureDevicePolicyResolverTest(
+ private val test: IsScreenCaptureCompletelyDisabledTestCase
+) : BaseScreenCaptureDevicePolicyResolverTest(test.given) {
+
+ companion object {
+ @Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams() =
+ listOf(
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = false,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureCompletelyDisabled = false,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = false,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureCompletelyDisabled = false,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = false,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = false,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = false,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureCompletelyDisabled = false,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ personalScreenCaptureDisabled = false,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = 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(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = false
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ ),
+ IsScreenCaptureCompletelyDisabledTestCase(
+ given =
+ Preconditions(
+ isHostInWorkProfile = true,
+ personalScreenCaptureDisabled = true,
+ workScreenCaptureDisabled = true,
+ disallowShareIntoManagedProfile = true
+ ),
+ expectedScreenCaptureCompletelyDisabled = true,
+ )
+ )
+ }
+
+ class Preconditions(
+ personalScreenCaptureDisabled: Boolean,
+ workScreenCaptureDisabled: Boolean,
+ disallowShareIntoManagedProfile: Boolean,
+ val isHostInWorkProfile: Boolean,
+ ) :
+ BaseScreenCaptureDevicePolicyResolverTest.Preconditions(
+ personalScreenCaptureDisabled,
+ workScreenCaptureDisabled,
+ disallowShareIntoManagedProfile
+ )
+
+ data class IsScreenCaptureCompletelyDisabledTestCase(
+ val given: Preconditions,
+ val expectedScreenCaptureCompletelyDisabled: Boolean
+ ) {
+ override fun toString(): String =
+ "isScreenCaptureCompletelyDisabled: " +
+ "host[${if (given.isHostInWorkProfile) "work" else "personal"} profile], " +
+ "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"
+ }
+
+ @Test
+ fun test() {
+ val hostAppUserHandle =
+ if (test.given.isHostInWorkProfile) workUserHandle else personalUserHandle
+
+ val completelyDisabled = policyResolver.isScreenCaptureCompletelyDisabled(hostAppUserHandle)
+
+ assertWithMessage("Screen capture policy resolved incorrectly")
+ .that(completelyDisabled)
+ .isEqualTo(test.expectedScreenCaptureCompletelyDisabled)
+ }
+}