Redact ISOBMFF boxes with 'free'

Test: atest MediaStore_Video_MediaTest
Bug: 135499138
Change-Id: I1cc556ee145aea93457b59ceefd8b157956d6f43
(cherry picked from commit 360b9d305e7d06272f248ebf62abdcbe59996bf8)
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index bbfc212..8928999 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -5366,7 +5366,8 @@
 
         // Figure out if we need to redact contents
         final boolean redactionNeeded = callerIsOwner ? false : isRedactionNeeded(uri);
-        final long[] redactionRanges = redactionNeeded ? getRedactionRanges(file) : EmptyArray.LONG;
+        final RedactionInfo redactionInfo = redactionNeeded ? getRedactionRanges(file)
+                : new RedactionInfo(EmptyArray.LONG, EmptyArray.LONG);
 
         // Yell if caller requires original, since we can't give it to them
         // unless they have access granted above
@@ -5402,8 +5403,13 @@
         try {
             // First, handle any redaction that is needed for caller
             final ParcelFileDescriptor pfd;
-            if (redactionRanges.length > 0) {
-                pfd = RedactingFileDescriptor.open(getContext(), file, modeBits, redactionRanges);
+            if (redactionInfo.redactionRanges.length > 0) {
+                pfd = RedactingFileDescriptor.open(
+                        getContext(),
+                        file,
+                        modeBits,
+                        redactionInfo.redactionRanges,
+                        redactionInfo.freeOffsets);
             } else {
                 pfd = ParcelFileDescriptor.open(file, modeBits);
             }
@@ -5503,13 +5509,19 @@
             IsoInterface.BOX_GPS0,
     };
 
-    /**
-     * Find the set of ranges that should be redacted from the given file, ready
-     * to pass to {@link RedactingFileDescriptor}.
-     */
-    private long[] getRedactionRanges(File file) {
+    private static final class RedactionInfo {
+        public final long[] redactionRanges;
+        public final long[] freeOffsets;
+        public RedactionInfo(long[] redactionRanges, long[] freeOffsets) {
+            this.redactionRanges = redactionRanges;
+            this.freeOffsets = freeOffsets;
+        }
+    }
+
+    private RedactionInfo getRedactionRanges(File file) {
         Trace.traceBegin(TRACE_TAG_DATABASE, "getRedactionRanges");
         final LongArray res = new LongArray();
+        final LongArray freeOffsets = new LongArray();
         try (FileInputStream is = new FileInputStream(file)) {
             final ExifInterface exif = new ExifInterface(is.getFD());
             for (String tag : REDACTED_EXIF_TAGS) {
@@ -5523,7 +5535,12 @@
             final IsoInterface iso = IsoInterface.fromFileDescriptor(is.getFD());
             for (int box : REDACTED_ISO_BOXES) {
                 final long[] ranges = iso.getBoxRanges(box);
-                res.addAll(LongArray.wrap(ranges));
+                for (int i = 0; i < ranges.length; i += 2) {
+                    long boxTypeOffset = ranges[i] - 4;
+                    freeOffsets.add(boxTypeOffset);
+                    res.add(boxTypeOffset);
+                    res.add(ranges[i + 1]);
+                }
             }
 
             // Redact xmp where present
@@ -5536,7 +5553,7 @@
             Log.w(TAG, "Failed to redact " + file + ": " + e);
         }
         Trace.traceEnd(TRACE_TAG_DATABASE);
-        return res.toArray();
+        return new RedactionInfo(res.toArray(), freeOffsets.toArray());
     }
 
     private boolean checkCallingPermissionGlobal(Uri uri, boolean forWrite) {