Loading libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt +31 −6 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.wm.shell.shared.desktopmode import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION import android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS import android.content.pm.PackageManager import android.window.DesktopModeFlags import com.android.internal.R Loading @@ -32,8 +34,10 @@ import com.android.internal.R class DesktopModeCompatPolicy(private val context: Context) { private val systemUiPackage: String = context.resources.getString(R.string.config_systemUi) private val pkgManager: PackageManager get() = context.getPackageManager() private val defaultHomePackage: String? get() = context.getPackageManager().getHomeActivities(ArrayList())?.packageName get() = pkgManager.getHomeActivities(ArrayList())?.packageName /** * If the top activity should be exempt from desktop windowing and forced back to fullscreen. Loading @@ -47,11 +51,12 @@ class DesktopModeCompatPolicy(private val context: Context) { fun isTopActivityExemptFromDesktopWindowing(packageName: String?, numActivities: Int, isTopActivityNoDisplay: Boolean, isActivityStackTransparent: Boolean) = DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue && ((isSystemUiTask(packageName) || isPartOfDefaultHomePackageOrNoHomeAvailable(packageName) || isTransparentTask(isActivityStackTransparent, numActivities)) && !isTopActivityNoDisplay) DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue && ((isSystemUiTask(packageName) || isPartOfDefaultHomePackageOrNoHomeAvailable(packageName) || (isTransparentTask(isActivityStackTransparent, numActivities) && hasFullscreenTransparentPermission(packageName))) && !isTopActivityNoDisplay) /** * Whether the caption insets should be excluded from configuration for system to handle. Loading Loading @@ -83,6 +88,26 @@ class DesktopModeCompatPolicy(private val context: Context) { private fun isSystemUiTask(packageName: String?) = packageName == systemUiPackage // Checks if the app for the given package has the SYSTEM_ALERT_WINDOW permission. private fun hasFullscreenTransparentPermission(packageName: String?): Boolean { if (DesktopModeFlags.ENABLE_MODALS_FULLSCREEN_WITH_PERMISSIONS.isTrue) { if (packageName == null) { return false } return try { val packageInfo = pkgManager.getPackageInfo( packageName, PackageManager.GET_PERMISSIONS ) packageInfo?.requestedPermissions?.contains(SYSTEM_ALERT_WINDOW) == true } catch (e: PackageManager.NameNotFoundException) { false // Package not found } } // If the flag is disabled we make this condition neutral. return true } /** * Returns true if the tasks base activity is part of the default home package, or there is * currently no default home package available. Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt +47 −0 Original line number Diff line number Diff line Loading @@ -16,13 +16,16 @@ package com.android.wm.shell.shared.desktopmode import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.app.TaskInfo import android.compat.testing.PlatformCompatChangeRule import android.content.ComponentName import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Process import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest Loading @@ -39,7 +42,9 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyString import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever Loading @@ -55,6 +60,7 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { private lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy private val packageManager: PackageManager = mock() private val homeActivities = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "") private val baseActivityTest = ComponentName("com.test.dummypackage", "TestClass") @Before fun setUp() { Loading @@ -64,6 +70,7 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { } @Test @DisableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION) fun testIsTopActivityExemptFromDesktopWindowing_onlyTransparentActivitiesInStack() { assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing( createFreeformTask(/* displayId */ 0) Loading @@ -71,6 +78,35 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { isActivityStackTransparent = true isTopActivityNoDisplay = false numActivities = 1 baseActivity = baseActivityTest })) } @Test @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION) fun testIsTopActivityExemptWithPermission_onlyTransparentActivitiesInStack() { allowOverlayPermission(arrayOf(SYSTEM_ALERT_WINDOW)) assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing( createFreeformTask(/* displayId */ 0) .apply { isActivityStackTransparent = true isTopActivityNoDisplay = false numActivities = 1 baseActivity = baseActivityTest })) } @Test @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION) fun testIsTopActivityExemptWithNoPermission_onlyTransparentActivitiesInStack() { allowOverlayPermission(arrayOf()) assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing( createFreeformTask(/* displayId */ 0) .apply { isActivityStackTransparent = true isTopActivityNoDisplay = false numActivities = 1 baseActivity = baseActivityTest })) } Loading Loading @@ -219,4 +255,15 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { } } } fun allowOverlayPermission(permissions: Array<String>) { val packageInfo = mock<PackageInfo>() packageInfo.requestedPermissions = permissions whenever( packageManager.getPackageInfo( anyString(), eq(PackageManager.GET_PERMISSIONS) ) ).thenReturn(packageInfo) } } Loading
libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt +31 −6 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.wm.shell.shared.desktopmode import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION import android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS import android.content.pm.PackageManager import android.window.DesktopModeFlags import com.android.internal.R Loading @@ -32,8 +34,10 @@ import com.android.internal.R class DesktopModeCompatPolicy(private val context: Context) { private val systemUiPackage: String = context.resources.getString(R.string.config_systemUi) private val pkgManager: PackageManager get() = context.getPackageManager() private val defaultHomePackage: String? get() = context.getPackageManager().getHomeActivities(ArrayList())?.packageName get() = pkgManager.getHomeActivities(ArrayList())?.packageName /** * If the top activity should be exempt from desktop windowing and forced back to fullscreen. Loading @@ -47,11 +51,12 @@ class DesktopModeCompatPolicy(private val context: Context) { fun isTopActivityExemptFromDesktopWindowing(packageName: String?, numActivities: Int, isTopActivityNoDisplay: Boolean, isActivityStackTransparent: Boolean) = DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue && ((isSystemUiTask(packageName) || isPartOfDefaultHomePackageOrNoHomeAvailable(packageName) || isTransparentTask(isActivityStackTransparent, numActivities)) && !isTopActivityNoDisplay) DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue && ((isSystemUiTask(packageName) || isPartOfDefaultHomePackageOrNoHomeAvailable(packageName) || (isTransparentTask(isActivityStackTransparent, numActivities) && hasFullscreenTransparentPermission(packageName))) && !isTopActivityNoDisplay) /** * Whether the caption insets should be excluded from configuration for system to handle. Loading Loading @@ -83,6 +88,26 @@ class DesktopModeCompatPolicy(private val context: Context) { private fun isSystemUiTask(packageName: String?) = packageName == systemUiPackage // Checks if the app for the given package has the SYSTEM_ALERT_WINDOW permission. private fun hasFullscreenTransparentPermission(packageName: String?): Boolean { if (DesktopModeFlags.ENABLE_MODALS_FULLSCREEN_WITH_PERMISSIONS.isTrue) { if (packageName == null) { return false } return try { val packageInfo = pkgManager.getPackageInfo( packageName, PackageManager.GET_PERMISSIONS ) packageInfo?.requestedPermissions?.contains(SYSTEM_ALERT_WINDOW) == true } catch (e: PackageManager.NameNotFoundException) { false // Package not found } } // If the flag is disabled we make this condition neutral. return true } /** * Returns true if the tasks base activity is part of the default home package, or there is * currently no default home package available. Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt +47 −0 Original line number Diff line number Diff line Loading @@ -16,13 +16,16 @@ package com.android.wm.shell.shared.desktopmode import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.app.TaskInfo import android.compat.testing.PlatformCompatChangeRule import android.content.ComponentName import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Process import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest Loading @@ -39,7 +42,9 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyString import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever Loading @@ -55,6 +60,7 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { private lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy private val packageManager: PackageManager = mock() private val homeActivities = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "") private val baseActivityTest = ComponentName("com.test.dummypackage", "TestClass") @Before fun setUp() { Loading @@ -64,6 +70,7 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { } @Test @DisableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION) fun testIsTopActivityExemptFromDesktopWindowing_onlyTransparentActivitiesInStack() { assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing( createFreeformTask(/* displayId */ 0) Loading @@ -71,6 +78,35 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { isActivityStackTransparent = true isTopActivityNoDisplay = false numActivities = 1 baseActivity = baseActivityTest })) } @Test @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION) fun testIsTopActivityExemptWithPermission_onlyTransparentActivitiesInStack() { allowOverlayPermission(arrayOf(SYSTEM_ALERT_WINDOW)) assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing( createFreeformTask(/* displayId */ 0) .apply { isActivityStackTransparent = true isTopActivityNoDisplay = false numActivities = 1 baseActivity = baseActivityTest })) } @Test @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION) fun testIsTopActivityExemptWithNoPermission_onlyTransparentActivitiesInStack() { allowOverlayPermission(arrayOf()) assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing( createFreeformTask(/* displayId */ 0) .apply { isActivityStackTransparent = true isTopActivityNoDisplay = false numActivities = 1 baseActivity = baseActivityTest })) } Loading Loading @@ -219,4 +255,15 @@ class DesktopModeCompatPolicyTest : ShellTestCase() { } } } fun allowOverlayPermission(permissions: Array<String>) { val packageInfo = mock<PackageInfo>() packageInfo.requestedPermissions = permissions whenever( packageManager.getPackageInfo( anyString(), eq(PackageManager.GET_PERMISSIONS) ) ).thenReturn(packageInfo) } }