diff options
| author | Jeff Sharkey <jsharkey@android.com> | 2018-07-31 10:45:37 -0600 |
|---|---|---|
| committer | Jeff Sharkey <jsharkey@android.com> | 2018-10-26 09:32:29 -0600 |
| commit | bc2ae008785cc23aa5fa2fe92b1f1d1efef6fb51 (patch) | |
| tree | f347f089c50be9d12b08006c353a6b679d488a09 /core/java/android/os/FileUtils.java | |
| parent | ffe3226069984e6c8e3f7bf08941d74c2afd3fdc (diff) | |
Magic to keep "_data" paths working.
As part of the storage changes in Q, we're removing the ability for
apps to directly access storage devices like /sdcard/. (Instead,
they'll need to go through ContentResolver.openFileDescriptor() to
gain access.) However, in several places we're returning raw
filesystem paths in the "_data" column. An initial attempt to simply
redact these with "/dev/null" shows that many popular apps are
depending on these paths, and become non-functional.
So we need to somehow return "_data" paths that apps can manually
open. We explored tricks like /proc/self/fd/ and FUSE, but neither
of those are feasible. Instead, we've created a cursor that returns
paths of this form:
/mnt/content/media/audio/12
And we then hook Libcore.os to intercept open() syscalls made by
Java code and redirect these to CR.openFileDescriptor() with Uris
like this:
content://media/audio/12
This appears to be enough to keep most popular apps working! Note
that it doesn't support apps that try opening the returned paths
from native code, which we'll hopefully be solving via direct
developer outreach.
Since this feature is a bit risky, it's guarded with a feature flag
that's disabled by default; a future CL will actually enable it,
offering a simple CL to revert in the case of trouble.
Bug: 111268862, 111960973
Test: atest cts/tests/tests/provider/src/android/provider/cts/MediaStore*
Change-Id: Ied15e62b46852aef73725f63d7648da390c4e03e
Diffstat (limited to 'core/java/android/os/FileUtils.java')
| -rw-r--r-- | core/java/android/os/FileUtils.java | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index f71fdd7fdac1..0b90f5437826 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -22,16 +22,19 @@ import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; import static android.os.ParcelFileDescriptor.MODE_TRUNCATE; import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY; +import static android.system.OsConstants.F_OK; import static android.system.OsConstants.O_APPEND; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDONLY; import static android.system.OsConstants.O_RDWR; import static android.system.OsConstants.O_TRUNC; import static android.system.OsConstants.O_WRONLY; +import static android.system.OsConstants.R_OK; import static android.system.OsConstants.SPLICE_F_MORE; import static android.system.OsConstants.SPLICE_F_MOVE; import static android.system.OsConstants.S_ISFIFO; import static android.system.OsConstants.S_ISREG; +import static android.system.OsConstants.W_OK; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1300,6 +1303,23 @@ public class FileUtils { } /** {@hide} */ + public static int translateModeAccessToPosix(int mode) { + if (mode == F_OK) { + // There's not an exact mapping, so we attempt a read-only open to + // determine if a file exists + return O_RDONLY; + } else if ((mode & (R_OK | W_OK)) == (R_OK | W_OK)) { + return O_RDWR; + } else if ((mode & R_OK) == R_OK) { + return O_RDONLY; + } else if ((mode & W_OK) == W_OK) { + return O_WRONLY; + } else { + throw new IllegalArgumentException("Bad mode: " + mode); + } + } + + /** {@hide} */ @VisibleForTesting public static class MemoryPipe extends Thread implements AutoCloseable { private final FileDescriptor[] pipe; |
