Merge "Block write access to media for non-owners." into qt-dev
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 080ff73..b9fc186 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
 import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
 import static android.app.AppOpsManager.OP_READ_MEDIA_AUDIO;
 import static android.app.AppOpsManager.OP_READ_MEDIA_IMAGES;
@@ -1721,6 +1722,33 @@
         return checkPermissionAndAppOp(mContext, enforce, pid, uid, packageName, permission, op);
     }
 
+    private boolean noteAppOpAllowingLegacy(boolean enforce,
+            int pid, int uid, String packageName, int op) {
+        final int mode = mAppOps.noteOpNoThrow(op, uid, packageName);
+        switch (mode) {
+            case AppOpsManager.MODE_ALLOWED:
+                return true;
+            case AppOpsManager.MODE_DEFAULT:
+            case AppOpsManager.MODE_IGNORED:
+            case AppOpsManager.MODE_ERRORED:
+                // Legacy apps technically have the access granted by this op,
+                // even when the op is denied
+                if ((mAppOps.checkOpNoThrow(OP_LEGACY_STORAGE, uid,
+                        packageName) == AppOpsManager.MODE_ALLOWED)) return true;
+
+                if (enforce) {
+                    throw new SecurityException("Op " + AppOpsManager.opToName(op) + " "
+                            + AppOpsManager.modeToName(mode) + " for package " + packageName);
+                } else {
+                    return false;
+                }
+            default:
+                throw new IllegalStateException(
+                        AppOpsManager.opToName(op) + " has unknown mode "
+                                + AppOpsManager.modeToName(mode));
+        }
+    }
+
     // Callers must hold both the old and new permissions, so that we can
     // handle obscure cases like when an app targets Q but was installed on
     // a device that was originally running on P before being upgraded to Q.
@@ -1730,8 +1758,7 @@
             int pid, int uid, String packageName) {
         if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                 READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false;
-        mAppOps.noteOpNoThrow(OP_READ_MEDIA_AUDIO, uid, packageName);
-        return true;
+        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_READ_MEDIA_AUDIO);
     }
 
     /** {@hide} */
@@ -1739,8 +1766,7 @@
             int pid, int uid, String packageName) {
         if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                 WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false;
-        mAppOps.noteOpNoThrow(OP_WRITE_MEDIA_AUDIO, uid, packageName);
-        return true;
+        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_WRITE_MEDIA_AUDIO);
     }
 
     /** {@hide} */
@@ -1748,8 +1774,7 @@
             int pid, int uid, String packageName) {
         if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                 READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false;
-        mAppOps.noteOpNoThrow(OP_READ_MEDIA_VIDEO, uid, packageName);
-        return true;
+        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_READ_MEDIA_VIDEO);
     }
 
     /** {@hide} */
@@ -1757,8 +1782,7 @@
             int pid, int uid, String packageName) {
         if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                 WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false;
-        mAppOps.noteOpNoThrow(OP_WRITE_MEDIA_VIDEO, uid, packageName);
-        return true;
+        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_WRITE_MEDIA_VIDEO);
     }
 
     /** {@hide} */
@@ -1766,8 +1790,7 @@
             int pid, int uid, String packageName) {
         if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                 READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false;
-        mAppOps.noteOpNoThrow(OP_READ_MEDIA_IMAGES, uid, packageName);
-        return true;
+        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_READ_MEDIA_IMAGES);
     }
 
     /** {@hide} */
@@ -1775,8 +1798,7 @@
             int pid, int uid, String packageName) {
         if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                 WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false;
-        mAppOps.noteOpNoThrow(OP_WRITE_MEDIA_IMAGES, uid, packageName);
-        return true;
+        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_WRITE_MEDIA_IMAGES);
     }
 
     /** {@hide} */