Merge "[3/n] Add cache to PackageManager#getActivityInfo usage" into main
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
index 0e4a6b9..9ea0532 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
@@ -38,6 +38,8 @@
         get() = context.getPackageManager()
     private val defaultHomePackage: String?
         get() = pkgManager.getHomeActivities(ArrayList())?.packageName
+    private val packageInfoCache = mutableMapOf<String, Boolean>()
+
 
     /**
      * If the top activity should be exempt from desktop windowing and forced back to fullscreen.
@@ -94,14 +96,16 @@
             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
+            return packageInfoCache.getOrPut(packageName) {
+                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.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
index 88c6e49..5ac6800 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
@@ -46,6 +46,8 @@
 import org.mockito.kotlin.any
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
 
 /**
@@ -111,6 +113,32 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION)
+    fun testIsTopActivityExemptCachedPermissionCheckIsUsed() {
+        allowOverlayPermission(arrayOf())
+        assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+            createFreeformTask(/* displayId */ 0)
+                .apply {
+                    isActivityStackTransparent = true
+                    isTopActivityNoDisplay = false
+                    numActivities = 1
+                    baseActivity = baseActivityTest
+                }))
+        assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+            createFreeformTask(/* displayId */ 0)
+                .apply {
+                    isActivityStackTransparent = true
+                    isTopActivityNoDisplay = false
+                    numActivities = 1
+                    baseActivity = baseActivityTest
+                }))
+        verify(packageManager, times(1)).getPackageInfo(
+            eq("com.test.dummypackage"),
+            eq(PackageManager.GET_PERMISSIONS)
+        )
+    }
+
+    @Test
     fun testIsTopActivityExemptFromDesktopWindowing_noActivitiesInStack() {
         assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
             createFreeformTask(/* displayId */ 0)