Snap for 6869386 from 76c0c8b4bc09caf87b8dd338d90aab772e5422d4 to rvc-qpr1-release

Change-Id: I975991f4fa4a7e663b473083c0d4d524c7c07311
diff --git a/src/com/android/providers/media/LocalCallingIdentity.java b/src/com/android/providers/media/LocalCallingIdentity.java
index 6f554b4..4d3700b 100644
--- a/src/com/android/providers/media/LocalCallingIdentity.java
+++ b/src/com/android/providers/media/LocalCallingIdentity.java
@@ -34,6 +34,7 @@
 import static com.android.providers.media.util.PermissionUtils.checkPermissionWriteImages;
 import static com.android.providers.media.util.PermissionUtils.checkPermissionWriteStorage;
 import static com.android.providers.media.util.PermissionUtils.checkPermissionWriteVideo;
+import static com.android.providers.media.util.PermissionUtils.checkWriteImagesOrVideoAppOps;
 
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
@@ -213,6 +214,8 @@
     public static final int PERMISSION_WRITE_VIDEO = 1 << 20;
     public static final int PERMISSION_WRITE_IMAGES = 1 << 21;
 
+    public static final int PERMISSION_IS_SYSTEM_GALLERY = 1 <<22;
+
     private int hasPermission;
     private int hasPermissionResolved;
 
@@ -271,6 +274,9 @@
             case PERMISSION_WRITE_IMAGES:
                 return checkPermissionWriteImages(
                         context, pid, uid, getPackageName(), attributionTag);
+            case PERMISSION_IS_SYSTEM_GALLERY:
+                return checkWriteImagesOrVideoAppOps(
+                        context, uid, getPackageName(), attributionTag);
             default:
                 return false;
         }
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index d3b6515..772ee64 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -44,6 +44,7 @@
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_REDACTION_NEEDED;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_SELF;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_SHELL;
+import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_SYSTEM_GALLERY;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_READ_AUDIO;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_READ_IMAGES;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_READ_VIDEO;
@@ -6295,7 +6296,15 @@
         final LocalCallingIdentity token =
                 clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
         try {
-            return uid != android.os.Process.SHELL_UID && isCallingPackageManager();
+            if (uid != android.os.Process.SHELL_UID && isCallingPackageManager()) {
+                return true;
+            }
+            // We bypass db operations for legacy system galleries with W_E_S (see b/167307393).
+            // Tracking a longer term solution in b/168784136.
+            if (isCallingPackageLegacyWrite() && isCallingPackageSystemGallery()) {
+                return true;
+            }
+            return false;
         } finally {
             restoreLocalCallingIdentity(token);
         }
@@ -7727,6 +7736,10 @@
         return builder.build();
     }
 
+    private boolean isCallingPackageSystemGallery() {
+        return mCallingIdentity.get().hasPermission(PERMISSION_IS_SYSTEM_GALLERY);
+    }
+
     @Deprecated
     private String getCallingPackageOrSelf() {
         return mCallingIdentity.get().getPackageName();
diff --git a/src/com/android/providers/media/util/PermissionUtils.java b/src/com/android/providers/media/util/PermissionUtils.java
index fc10b78..adbe0e2 100644
--- a/src/com/android/providers/media/util/PermissionUtils.java
+++ b/src/com/android/providers/media/util/PermissionUtils.java
@@ -185,6 +185,20 @@
                 generateAppOpMessage(packageName, sOpDescription.get()));
     }
 
+    /**
+     * Returns {@code true} if the given package has write images or write video app op, which
+     * indicates the package is a system gallery.
+     */
+    public static boolean checkWriteImagesOrVideoAppOps(@NonNull Context context, int uid,
+            @NonNull String packageName, @Nullable String attributionTag) {
+        return checkAppOp(
+                context, OPSTR_WRITE_MEDIA_IMAGES, uid, packageName, attributionTag,
+                generateAppOpMessage(packageName, sOpDescription.get()))
+                || checkAppOp(
+                        context, OPSTR_WRITE_MEDIA_VIDEO, uid, packageName, attributionTag,
+                generateAppOpMessage(packageName, sOpDescription.get()));
+    }
+
     @VisibleForTesting
     static boolean checkNoIsolatedStorageGranted(@NonNull Context context, int uid,
             @NonNull String packageName, @Nullable String attributionTag) {
@@ -223,6 +237,27 @@
     }
 
     /**
+     * Checks *only* App Ops.
+     */
+    private static boolean checkAppOp(@NonNull Context context,
+            @NonNull String op, int uid, @NonNull String packageName,
+            @Nullable String attributionTag, @Nullable String opMessage) {
+        final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+        final int mode = appOps.noteOpNoThrow(op, uid, packageName, attributionTag, opMessage);
+        switch (mode) {
+            case AppOpsManager.MODE_ALLOWED:
+                return true;
+            case AppOpsManager.MODE_DEFAULT:
+            case AppOpsManager.MODE_IGNORED:
+            case AppOpsManager.MODE_ERRORED:
+                return false;
+            default:
+                throw new IllegalStateException(op + " has unknown mode " + mode);
+        }
+    }
+
+
+    /**
      * Checks *only* App Ops, also returns true for legacy apps.
      */
     private static boolean checkAppOpAllowingLegacy(@NonNull Context context,