diff options
-rw-r--r-- | api/current.txt | 3 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 14 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 35 | ||||
-rw-r--r-- | core/java/android/content/ContextWrapper.java | 5 | ||||
-rw-r--r-- | core/java/android/os/Environment.java | 4 | ||||
-rw-r--r-- | services/core/java/com/android/server/MountService.java | 12 | ||||
-rw-r--r-- | test-runner/src/android/test/mock/MockContext.java | 5 | ||||
-rw-r--r-- | tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java | 6 |
8 files changed, 84 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index 73decfb..265c682 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6902,6 +6902,7 @@ package android.content { method public abstract java.io.File[] getExternalCacheDirs(); method public abstract java.io.File getExternalFilesDir(java.lang.String); method public abstract java.io.File[] getExternalFilesDirs(java.lang.String); + method public abstract java.io.File[] getExternalMediaDirs(); method public abstract java.io.File getFileStreamPath(java.lang.String); method public abstract java.io.File getFilesDir(); method public abstract android.os.Looper getMainLooper(); @@ -7070,6 +7071,7 @@ package android.content { method public java.io.File[] getExternalCacheDirs(); method public java.io.File getExternalFilesDir(java.lang.String); method public java.io.File[] getExternalFilesDirs(java.lang.String); + method public java.io.File[] getExternalMediaDirs(); method public java.io.File getFileStreamPath(java.lang.String); method public java.io.File getFilesDir(); method public android.os.Looper getMainLooper(); @@ -28268,6 +28270,7 @@ package android.test.mock { method public java.io.File[] getExternalCacheDirs(); method public java.io.File getExternalFilesDir(java.lang.String); method public java.io.File[] getExternalFilesDirs(java.lang.String); + method public java.io.File[] getExternalMediaDirs(); method public java.io.File getFileStreamPath(java.lang.String); method public java.io.File getFilesDir(); method public android.os.Looper getMainLooper(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index ff8688d..8ffa6fe 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -249,6 +249,8 @@ class ContextImpl extends Context { private File[] mExternalFilesDirs; @GuardedBy("mSync") private File[] mExternalCacheDirs; + @GuardedBy("mSync") + private File[] mExternalMediaDirs; private static final String[] EMPTY_FILE_LIST = {}; @@ -1032,6 +1034,18 @@ class ContextImpl extends Context { } @Override + public File[] getExternalMediaDirs() { + synchronized (mSync) { + if (mExternalMediaDirs == null) { + mExternalMediaDirs = Environment.buildExternalStorageAppMediaDirs(getPackageName()); + } + + // Create dirs if needed + return ensureDirsExistOrFilter(mExternalMediaDirs); + } + } + + @Override public File getFileStreamPath(String name) { return makeFilename(getFilesDir(), name); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 2ff85c6..d3a979c 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -40,6 +40,7 @@ import android.os.Looper; import android.os.StatFs; import android.os.UserHandle; import android.os.UserManager; +import android.provider.MediaStore; import android.util.AttributeSet; import android.view.DisplayAdjustments; import android.view.Display; @@ -929,6 +930,40 @@ public abstract class Context { public abstract File[] getExternalCacheDirs(); /** + * Returns absolute paths to application-specific directories on all + * external storage devices where the application can place media files. + * These files are scanned and made available to other apps through + * {@link MediaStore}. + * <p> + * This is like {@link #getExternalFilesDirs} in that these files will be + * deleted when the application is uninstalled, however there are some + * important differences: + * <ul> + * <li>External files are not always available: they will disappear if the + * user mounts the external storage on a computer or removes it. + * <li>There is no security enforced with these files. + * </ul> + * <p> + * External storage devices returned here are considered a permanent part of + * the device, including both emulated external storage and physical media + * slots, such as SD cards in a battery compartment. The returned paths do + * not include transient devices, such as USB flash drives. + * <p> + * An application may store data on any or all of the returned devices. For + * example, an app may choose to store large files on the device with the + * most available space, as measured by {@link StatFs}. + * <p> + * No permissions are required to read or write to the returned paths; they + * are always accessible to the calling app. Write access outside of these + * paths on secondary external storage devices is not available. + * <p> + * Returned paths may be {@code null} if a storage device is unavailable. + * + * @see Environment#getExternalStorageState(File) + */ + public abstract File[] getExternalMediaDirs(); + + /** * Returns an array of strings naming the private files associated with * this Context's application package. * diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index c66355b..dbf9122 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -237,6 +237,11 @@ public class ContextWrapper extends Context { } @Override + public File[] getExternalMediaDirs() { + return mBase.getExternalMediaDirs(); + } + + @Override public File getDir(String name, int mode) { return mBase.getDir(name, mode); } diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index e98a26b..e84b695 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -191,6 +191,10 @@ public class Environment { return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName); } + public File[] buildExternalStorageAppMediaDirsForVold(String packageName) { + return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_MEDIA, packageName); + } + public File[] buildExternalStorageAppObbDirs(String packageName) { return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName); } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index d5f045e..d31fb60 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2372,6 +2372,18 @@ class MountService extends IMountService.Stub } } + voldPath = maybeTranslatePathForVold(appPath, + userEnv.buildExternalStorageAppMediaDirs(callingPkg), + userEnv.buildExternalStorageAppMediaDirsForVold(callingPkg)); + if (voldPath != null) { + try { + mConnector.execute("volume", "mkdirs", voldPath); + return 0; + } catch (NativeDaemonConnectorException e) { + return e.getCode(); + } + } + throw new SecurityException("Invalid mkdirs path: " + appPath); } diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index c162bf2..a54936b 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -608,4 +608,9 @@ public class MockContext extends Context { public File[] getExternalCacheDirs() { throw new UnsupportedOperationException(); } + + @Override + public File[] getExternalMediaDirs() { + throw new UnsupportedOperationException(); + } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index d31239b..5c51c63 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1466,4 +1466,10 @@ public final class BridgeContext extends Context { // pass return new File[0]; } + + @Override + public File[] getExternalMediaDirs() { + // pass + return new File[0]; + } } |