[Android] Create a permission cache to avoid some performance issues

Nicolas Pomepuy git at videolan.org
Fri Apr 4 12:55:27 UTC 2025


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Thu Apr  3 11:49:00 2025 +0200| [cd19717135e7de5043a2d9d5a881bb3dc3fbdd38] | committer: Duncan McNamara

Create a permission cache to avoid some performance issues

Fixes #3181

> https://code.videolan.org/videolan/vlc-android/commit/cd19717135e7de5043a2d9d5a881bb3dc3fbdd38
---

 .../src/org/videolan/vlc/util/Permissions.kt       | 49 ++++++++++++++++++----
 1 file changed, 42 insertions(+), 7 deletions(-)

diff --git a/application/vlc-android/src/org/videolan/vlc/util/Permissions.kt b/application/vlc-android/src/org/videolan/vlc/util/Permissions.kt
index c26f5111c7..da95e16dd9 100644
--- a/application/vlc-android/src/org/videolan/vlc/util/Permissions.kt
+++ b/application/vlc-android/src/org/videolan/vlc/util/Permissions.kt
@@ -49,7 +49,6 @@ import org.videolan.resources.AppContextProvider
 import org.videolan.resources.SCHEME_PACKAGE
 import org.videolan.resources.util.isExternalStorageManager
 import org.videolan.tools.Settings
-import org.videolan.tools.isCallable
 import org.videolan.tools.putSingle
 import org.videolan.vlc.BuildConfig
 import org.videolan.vlc.R
@@ -75,6 +74,8 @@ object Permissions {
 
     var sAlertDialog: Dialog? = null
 
+    var cache = mutableMapOf<PermissionType, Pair<Long, Boolean>>()
+
     /*
      * Marshmallow permission system management
      */
@@ -102,17 +103,40 @@ object Permissions {
         return !AndroidUtil.isMarshMallowOrLater || android.provider.Settings.System.canWrite(context)
     }
 
-    fun canReadStorage(context: Context): Boolean {
-        return !AndroidUtil.isMarshMallowOrLater ||
+    fun getFromCache (context: Context, permissionType: PermissionType) : Boolean {
+        cache[permissionType]?.let {
+            if (it.first < System.currentTimeMillis() - 5000L) {
+                cache.remove(permissionType)
+            } else {
+                return it.second
+            }
+        }
+        return when (permissionType) {
+            PermissionType.STORAGE -> canReadStorage(context, true)
+            PermissionType.AUDIO -> canReadAudios(context, true)
+            else -> canReadVideos(context, true)
+        }
+    }
+
+    fun canReadStorage(context: Context, skipCache: Boolean = false): Boolean {
+        if (!skipCache) {
+            return getFromCache(context, PermissionType.STORAGE)
+        }
+        val result =  !AndroidUtil.isMarshMallowOrLater ||
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) isExternalStorageManager() || isAnyFileFinePermissionGranted(context)
                 else ContextCompat.checkSelfPermission(
                     context,
                     Manifest.permission.READ_EXTERNAL_STORAGE
                 ) == PackageManager.PERMISSION_GRANTED || isExternalStorageManager()
+        cache.put(PermissionType.STORAGE, Pair(System.currentTimeMillis(), result))
+        return result
     }
 
-    fun canReadVideos(context: Context): Boolean {
-        return Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU &&
+    fun canReadVideos(context: Context, skipCache: Boolean = false): Boolean {
+        if (!skipCache) {
+            return getFromCache(context, PermissionType.VIDEO)
+        }
+        val result =  Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU &&
                 (ContextCompat.checkSelfPermission(
                     context,
                     Manifest.permission.READ_EXTERNAL_STORAGE
@@ -121,11 +145,16 @@ object Permissions {
                     context,
                     Manifest.permission.READ_MEDIA_VIDEO
                 ) == PackageManager.PERMISSION_GRANTED || isExternalStorageManager()))
+        cache.put(PermissionType.VIDEO, Pair(System.currentTimeMillis(), result))
+        return result
 
     }
 
-    fun canReadAudios(context: Context): Boolean {
-        return Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU &&
+    fun canReadAudios(context: Context, skipCache: Boolean = false): Boolean {
+        if (!skipCache) {
+            return getFromCache(context, PermissionType.AUDIO)
+        }
+        val result =  Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU &&
                 (ContextCompat.checkSelfPermission(
                     context,
                     Manifest.permission.READ_EXTERNAL_STORAGE
@@ -134,6 +163,8 @@ object Permissions {
                     context,
                     Manifest.permission.READ_MEDIA_AUDIO
                 ) == PackageManager.PERMISSION_GRANTED || isExternalStorageManager()))
+        cache.put(PermissionType.AUDIO, Pair(System.currentTimeMillis(), result))
+        return result
 
     }
 
@@ -373,4 +404,8 @@ object Permissions {
         }
         return true
     }
+
+    enum class PermissionType {
+        STORAGE, AUDIO, VIDEO
+    }
 }



More information about the Android mailing list