Merge "Fix screenshot failure with transcoding"

This commit is contained in:
TreeHugger Robot
2020-12-17 20:52:32 +00:00
committed by Android (Google) Code Review
2 changed files with 70 additions and 4 deletions

View File

@@ -83,6 +83,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -115,6 +116,9 @@ public final class FileUtils {
private FileUtils() {
}
private static final String CAMERA_DIR_LOWER_CASE = "/storage/emulated/" + UserHandle.myUserId()
+ "/dcim/camera";
/** Regular expression for safe filenames: no spaces or metacharacters.
*
* Use a preload holder so that FileUtils can be compile-time initialized.
@@ -1432,18 +1436,27 @@ public final class FileUtils {
}
}
// TODO(b/170488060): Consider better approach
/** {@hide} */
@VisibleForTesting
public static FileDescriptor convertToModernFd(FileDescriptor fd) {
try {
Context context = AppGlobals.getInitialApplication();
File realFile = ParcelFileDescriptor.getFile(fd);
String fileName = realFile.getName();
boolean isCameraVideo = !fileName.startsWith(".") && fileName.endsWith(".mp4")
&& contains(CAMERA_DIR_LOWER_CASE, realFile.getAbsolutePath().toLowerCase(
Locale.ROOT));
if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false)
|| UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
// If transcode is enabled we optimize by default, unless explicitly disabled.
// Never convert modern fd for MediaProvider, because this requires
|| UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)
|| !isCameraVideo) {
// 1. If transcode is enabled we optimize by default, unless explicitly disabled.
// 2. Never convert modern fd for MediaProvider, because this requires
// MediaStore#scanFile and can cause infinite loops when MediaProvider scans
// 3. Only convert published mp4 videos in the DCIM/Camera dir
return null;
}
File realFile = ParcelFileDescriptor.getFile(fd);
Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
ContentResolver resolver = context.getContentResolver();

View File

@@ -16,6 +16,7 @@
package android.os;
import static android.os.FileUtils.convertToModernFd;
import static android.os.FileUtils.roundStorageSize;
import static android.os.FileUtils.translateModeAccessToPosix;
import static android.os.FileUtils.translateModePfdToPosix;
@@ -45,6 +46,8 @@ import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -67,6 +70,7 @@ import org.junit.runner.RunWith;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
@@ -562,6 +566,55 @@ public class FileUtilsTest {
assertEquals(O_RDWR, translateModeAccessToPosix(R_OK | W_OK | X_OK));
}
@Test
public void testConvertToModernFd() throws Exception {
final String nonce = String.valueOf(System.nanoTime());
final File cameraDir = new File("/storage/emulated/0/DCIM/Camera");
final File nonCameraDir = new File("/storage/emulated/0/Pictures");
cameraDir.mkdirs();
nonCameraDir.mkdirs();
final File validVideoCameraDir = new File(cameraDir, "validVideo-" + nonce + ".mp4");
final File validImageCameraDir = new File(cameraDir, "validImage-" + nonce + ".jpg");
final File invalidVideoCameraDir = new File(cameraDir, ".invalidVideo-" + nonce + ".mp4");
final File validVideoNonCameraDir = new File(nonCameraDir, "validVideo-" + nonce + ".mp4");
final File validImageNonCameraDir = new File(nonCameraDir, "validImage-" + nonce + ".jpg");
try {
FileDescriptor pfdValidVideoCameraDir =
ParcelFileDescriptor.open(validVideoCameraDir,
MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
FileDescriptor pfdValidImageCameraDir =
ParcelFileDescriptor.open(validImageCameraDir,
MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
FileDescriptor pfdInvalidVideoCameraDir =
ParcelFileDescriptor.open(invalidVideoCameraDir,
MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
FileDescriptor pfdValidVideoNonCameraDir =
ParcelFileDescriptor.open(validVideoNonCameraDir,
MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
FileDescriptor pfdValidImageNonCameraDir =
ParcelFileDescriptor.open(validImageNonCameraDir,
MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
assertNotNull(convertToModernFd(pfdValidVideoCameraDir));
assertNull(convertToModernFd(pfdValidImageCameraDir));
assertNull(convertToModernFd(pfdInvalidVideoCameraDir));
assertNull(convertToModernFd(pfdValidVideoNonCameraDir));
assertNull(convertToModernFd(pfdValidImageNonCameraDir));
} finally {
validVideoCameraDir.delete();
validImageCameraDir.delete();
invalidVideoCameraDir.delete();
validVideoNonCameraDir.delete();
validImageNonCameraDir.delete();
}
}
private static void assertTranslate(String string, int posix, int pfd) {
assertEquals(posix, translateModeStringToPosix(string));
assertEquals(string, translateModePosixToString(posix));