{"record":{"id":"f972e6b1dc096fda","repo":"MuntashirAkon/AppManager","slug":"unknown-appopsmanager-mode","errorCode":null,"errorMessage":"Unknown AppOpsManager mode ","messagePattern":"Unknown AppOpsManager mode ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/self/SelfPermissions.java","lineNumber":216,"sourceCode":"    public static boolean checkStoragePermission() {\n        int callingUid = Users.getSelfOrRemoteUid();\n        if (callingUid == Ops.ROOT_UID) {\n            return true;\n        }\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n            String packageName = getCallingPackage(callingUid);\n            AppOpsManagerCompat appOps = new AppOpsManagerCompat();\n            int opMode = appOps.checkOpNoThrow(AppOpsManagerHidden.OP_MANAGE_EXTERNAL_STORAGE, callingUid, packageName);\n            switch (opMode) {\n                case AppOpsManager.MODE_DEFAULT:\n                    return checkSelfOrRemotePermission(Manifest.permission.MANAGE_EXTERNAL_STORAGE, callingUid);\n                case AppOpsManager.MODE_ALLOWED:\n                    return true;\n                case AppOpsManager.MODE_ERRORED:\n                case AppOpsManager.MODE_IGNORED:\n                    return false;\n                default:\n                    throw new IllegalStateException(\"Unknown AppOpsManager mode \" + opMode);\n            }\n        }\n        return checkSelfOrRemotePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, callingUid);\n    }\n\n    public static boolean checkCrossUserPermission(@UserIdInt int userId, boolean requireFullPermission) {\n        int callingUid = Users.getSelfOrRemoteUid();\n        return checkCrossUserPermission(userId, requireFullPermission, callingUid);\n    }\n\n    public static boolean checkCrossUserPermission(@UserIdInt int userId, boolean requireFullPermission, int callingUid) {\n        if (userId == UserHandleHidden.USER_NULL) {\n            userId = UserHandleHidden.myUserId();\n        }\n        if (userId < 0 && userId != UserHandleHidden.USER_ALL) {\n            throw new IllegalArgumentException(\"Invalid userId \" + userId);\n        }\n        if (isSystemOrRootOrShell(callingUid) || userId == UserHandleHidden.getUserId(callingUid)) {","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/self/SelfPermissions.java#L198-L234","documentation":"checkStoragePermission checks the result of an AppOpsManager operation and only knows MODE_ALLOWED, MODE_ERRORED and MODE_IGNORED. If the system returns any other AppOpsManager mode (e.g. MODE_DEFAULT), it throws IllegalStateException(\"Unknown AppOpsManager mode \" + opMode).","triggerScenarios":"Calling checkStoragePermission on an Android version/ROM where AppOpsManager returns MODE_DEFAULT or a vendor-specific mode for the storage op, e.g. when the op was never explicitly set for the calling uid.","commonSituations":"Running on modified/OEM ROMs with non-standard AppOps behavior, Android version changes that reinterpret AppOps modes, uids whose storage op has only the default mode.","solutions":["Handle MODE_DEFAULT explicitly by falling back to checkSelfOrRemotePermission instead of throwing.","Log the unknown opMode and treat it conservatively (deny) rather than crashing.","Update the switch to cover all AppOpsManager.MODE_* constants for the target SDK.","Reproduce and test on the specific ROM/Android version that returns the unknown mode."],"exampleFix":"// before\ndefault:\n    throw new IllegalStateException(\"Unknown AppOpsManager mode \" + opMode);\n// after\ncase AppOpsManager.MODE_DEFAULT:\n    return checkSelfOrRemotePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, callingUid);\ndefault:\n    return false;","handlingStrategy":"try-catch","validationCode":"int opMode = appOps.checkOpNoThrow(op, uid, packageName);\nif (opMode != AppOpsManager.MODE_ALLOWED\n        && opMode != AppOpsManager.MODE_ERRORED\n        && opMode != AppOpsManager.MODE_IGNORED\n        && opMode != AppOpsManager.MODE_DEFAULT) {\n    // unknown mode: skip the AppOps path and use a plain permission check\n}","typeGuard":null,"tryCatchPattern":"try {\n    hasStorage = SelfPermissions.checkStoragePermission(callingUid);\n} catch (IllegalStateException e) {\n    hasStorage = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)\n            == PackageManager.PERMISSION_GRANTED;\n}","preventionTips":["Test storage-permission checks on all supported Android versions and OEM ROMs.","Treat MODE_DEFAULT as 'fall back to regular permission check', never an exception.","Keep AppOps mode handling in sync with the target SDK's AppOpsManager constants.","Prefer the regular permission check as primary and AppOps only as refinement."],"tags":["android","appops","permissions","storage"],"backgroundTag":"invalid-enum-value","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}