Loading core/java/android/app/ContextImpl.java +18 −4 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.SystemVibrator; import android.os.UserManager; import android.os.storage.IMountService; import android.os.storage.StorageManager; import android.print.IPrintManager; import android.print.PrintManager; Loading Loading @@ -864,7 +865,9 @@ class ContextImpl extends Context { if (mExternalObbDirs == null) { mExternalObbDirs = Environment.buildExternalStorageAppObbDirs(getPackageName()); } return mExternalObbDirs; // Create dirs if needed return ensureDirsExistOrFilter(mExternalObbDirs); } } Loading Loading @@ -2127,16 +2130,27 @@ class ContextImpl extends Context { * Ensure that given directories exist, trying to create them if missing. If * unable to create, they are filtered by replacing with {@code null}. */ private static File[] ensureDirsExistOrFilter(File[] dirs) { private File[] ensureDirsExistOrFilter(File[] dirs) { File[] result = new File[dirs.length]; for (int i = 0; i < dirs.length; i++) { File dir = dirs[i]; if (!dir.exists()) { if (!dir.mkdirs()) { // Failing to mkdir() may be okay, since we might not have // enough permissions; ask vold to create on our behalf. final IMountService mount = IMountService.Stub.asInterface( ServiceManager.getService("mount")); int res = -1; try { res = mount.mkdirs(getPackageName(), dir.getAbsolutePath()); } catch (RemoteException e) { } if (res != 0) { Log.w(TAG, "Failed to ensure directory: " + dir); dir = null; } } } result[i] = dir; } return result; Loading core/java/android/os/Environment.java +42 −22 Original line number Diff line number Diff line Loading @@ -109,29 +109,36 @@ public class Environment { // TODO: generalize further to create package-specific environment // TODO: add support for secondary external storage private final File[] mExternalDirs; private final File mMediaDir; /** External storage dirs, as visible to vold */ private final File[] mExternalDirsForVold; /** External storage dirs, as visible to apps */ private final File[] mExternalDirsForApp; /** Primary emulated storage dir for direct access */ private final File mEmulatedDirForDirect; public UserEnvironment(int userId) { // See storage config details at http://source.android.com/tech/storage/ String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE); String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE); String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE); if (TextUtils.isEmpty(rawMediaStorage)) { rawMediaStorage = "/data/media"; } if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) { if (!TextUtils.isEmpty(rawEmulatedTarget)) { // Device has emulated storage; external storage paths should have // userId burned into them. final String rawUserId = Integer.toString(userId); final File emulatedBase = new File(rawEmulatedStorageTarget); final File emulatedSourceBase = new File(rawEmulatedSource); final File emulatedTargetBase = new File(rawEmulatedTarget); final File mediaBase = new File(rawMediaStorage); // /storage/emulated/0 mExternalDirs = new File[] { buildPath(emulatedBase, rawUserId) }; mExternalDirsForVold = new File[] { buildPath(emulatedSourceBase, rawUserId) }; mExternalDirsForApp = new File[] { buildPath(emulatedTargetBase, rawUserId) }; // /data/media/0 mMediaDir = buildPath(mediaBase, rawUserId); mEmulatedDirForDirect = buildPath(mediaBase, rawUserId); } else { // Device has physical external storage; use plain paths. Loading @@ -141,15 +148,16 @@ public class Environment { } // /storage/sdcard0 mExternalDirs = new File[] { new File(rawExternalStorage) }; mExternalDirsForVold = new File[] { new File(rawExternalStorage) }; mExternalDirsForApp = new File[] { new File(rawExternalStorage) }; // /data/media mMediaDir = new File(rawMediaStorage); mEmulatedDirForDirect = new File(rawMediaStorage); } } @Deprecated public File getExternalStorageDirectory() { return mExternalDirs[0]; return mExternalDirsForApp[0]; } @Deprecated Loading @@ -157,44 +165,56 @@ public class Environment { return buildExternalStoragePublicDirs(type)[0]; } public File[] getExternalDirs() { return mExternalDirs; public File[] getExternalDirsForVold() { return mExternalDirsForVold; } public File[] getExternalDirsForApp() { return mExternalDirsForApp; } public File getMediaDir() { return mMediaDir; return mEmulatedDirForDirect; } public File[] buildExternalStoragePublicDirs(String type) { return buildPaths(mExternalDirs, type); return buildPaths(mExternalDirsForApp, type); } public File[] buildExternalStorageAndroidDataDirs() { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA); } public File[] buildExternalStorageAndroidObbDirs() { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_OBB); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB); } public File[] buildExternalStorageAppDataDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName); } public File[] buildExternalStorageAppDataDirsForVold(String packageName) { return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_DATA, packageName); } public File[] buildExternalStorageAppMediaDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_MEDIA, packageName); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName); } public File[] buildExternalStorageAppObbDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_OBB, packageName); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName); } public File[] buildExternalStorageAppObbDirsForVold(String packageName) { return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_OBB, packageName); } public File[] buildExternalStorageAppFilesDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES); } public File[] buildExternalStorageAppCacheDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE); } } Loading Loading @@ -344,7 +364,7 @@ public class Environment { */ public static File getExternalStorageDirectory() { throwIfUserRequired(); return sCurrentUser.getExternalDirs()[0]; return sCurrentUser.getExternalDirsForApp()[0]; } /** {@hide} */ Loading core/java/android/os/storage/IMountService.java +38 −2 Original line number Diff line number Diff line Loading @@ -20,9 +20,7 @@ import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.storage.StorageVolume; /** * WARNING! Update IMountService.h and IMountService.cpp if you change this Loading Loading @@ -737,7 +735,25 @@ public interface IMountService extends IInterface { _data.recycle(); } return _result; } @Override public int mkdirs(String callingPkg, String path) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(callingPkg); _data.writeString(path); mRemote.transact(Stub.TRANSACTION_mkdirs, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } Loading Loading @@ -811,6 +827,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33; static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34; /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. Loading Loading @@ -1154,6 +1172,15 @@ public interface IMountService extends IInterface { reply.writeInt(resultCode); return true; } case TRANSACTION_mkdirs: { data.enforceInterface(DESCRIPTOR); String callingPkg = data.readString(); String path = data.readString(); int result = mkdirs(callingPkg, path); reply.writeNoException(); reply.writeInt(result); return true; } } return super.onTransact(code, data, reply, flags); } Loading Loading @@ -1376,4 +1403,13 @@ public interface IMountService extends IInterface { */ public int fixPermissionsSecureContainer(String id, int gid, String filename) throws RemoteException; /** * Ensure that all directories along given path exist, creating parent * directories as needed. Validates that given path is absolute and that it * contains no relative "." or ".." paths or symlinks. Also ensures that * path belongs to a volume managed by vold, and that path is either * external storage data or OBB directory belonging to calling app. */ public int mkdirs(String callingPkg, String path) throws RemoteException; } services/java/com/android/server/MountService.java +81 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.Manifest; import android.app.AppOpsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -2127,6 +2128,85 @@ class MountService extends IMountService.Stub } } @Override public int mkdirs(String callingPkg, String appPath) { final int userId = UserHandle.getUserId(Binder.getCallingUid()); final UserEnvironment userEnv = new UserEnvironment(userId); // Validate that reported package name belongs to caller final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService( Context.APP_OPS_SERVICE); appOps.checkPackage(Binder.getCallingUid(), callingPkg); try { appPath = new File(appPath).getCanonicalPath(); } catch (IOException e) { Slog.e(TAG, "Failed to resolve " + appPath + ": " + e); return -1; } // Try translating the app path into a vold path, but require that it // belong to the calling package. String voldPath = maybeTranslatePathForVold(appPath, userEnv.buildExternalStorageAppDataDirs(callingPkg), userEnv.buildExternalStorageAppDataDirsForVold(callingPkg)); if (voldPath != null) { try { mConnector.execute("volume", "mkdirs", voldPath); return 0; } catch (NativeDaemonConnectorException e) { return e.getCode(); } } voldPath = maybeTranslatePathForVold(appPath, userEnv.buildExternalStorageAppObbDirs(callingPkg), userEnv.buildExternalStorageAppObbDirsForVold(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); } /** * Translate the given path from an app-visible path to a vold-visible path, * but only if it's under the given whitelisted paths. * * @param path a canonicalized app-visible path. * @param appPaths list of app-visible paths that are allowed. * @param voldPaths list of vold-visible paths directly corresponding to the * allowed app-visible paths argument. * @return a vold-visible path representing the original path, or * {@code null} if the given path didn't have an app-to-vold * mapping. */ @VisibleForTesting public static String maybeTranslatePathForVold( String path, File[] appPaths, File[] voldPaths) { if (appPaths.length != voldPaths.length) { throw new IllegalStateException("Paths must be 1:1 mapping"); } for (int i = 0; i < appPaths.length; i++) { final String appPath = appPaths[i].getAbsolutePath(); if (path.startsWith(appPath)) { path = new File(voldPaths[i], path.substring(appPath.length() + 1)) .getAbsolutePath(); if (!path.endsWith("/")) { path = path + "/"; } return path; } } return null; } @Override public StorageVolume[] getVolumeList() { final int callingUserId = UserHandle.getCallingUserId(); Loading Loading @@ -2651,7 +2731,7 @@ class MountService extends IMountService.Stub if (forVold) { return new File(Environment.getEmulatedStorageSource(userId), path).getAbsolutePath(); } else { return new File(userEnv.getExternalDirs()[0], path).getAbsolutePath(); return new File(userEnv.getExternalDirsForApp()[0], path).getAbsolutePath(); } } Loading Loading
core/java/android/app/ContextImpl.java +18 −4 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.SystemVibrator; import android.os.UserManager; import android.os.storage.IMountService; import android.os.storage.StorageManager; import android.print.IPrintManager; import android.print.PrintManager; Loading Loading @@ -864,7 +865,9 @@ class ContextImpl extends Context { if (mExternalObbDirs == null) { mExternalObbDirs = Environment.buildExternalStorageAppObbDirs(getPackageName()); } return mExternalObbDirs; // Create dirs if needed return ensureDirsExistOrFilter(mExternalObbDirs); } } Loading Loading @@ -2127,16 +2130,27 @@ class ContextImpl extends Context { * Ensure that given directories exist, trying to create them if missing. If * unable to create, they are filtered by replacing with {@code null}. */ private static File[] ensureDirsExistOrFilter(File[] dirs) { private File[] ensureDirsExistOrFilter(File[] dirs) { File[] result = new File[dirs.length]; for (int i = 0; i < dirs.length; i++) { File dir = dirs[i]; if (!dir.exists()) { if (!dir.mkdirs()) { // Failing to mkdir() may be okay, since we might not have // enough permissions; ask vold to create on our behalf. final IMountService mount = IMountService.Stub.asInterface( ServiceManager.getService("mount")); int res = -1; try { res = mount.mkdirs(getPackageName(), dir.getAbsolutePath()); } catch (RemoteException e) { } if (res != 0) { Log.w(TAG, "Failed to ensure directory: " + dir); dir = null; } } } result[i] = dir; } return result; Loading
core/java/android/os/Environment.java +42 −22 Original line number Diff line number Diff line Loading @@ -109,29 +109,36 @@ public class Environment { // TODO: generalize further to create package-specific environment // TODO: add support for secondary external storage private final File[] mExternalDirs; private final File mMediaDir; /** External storage dirs, as visible to vold */ private final File[] mExternalDirsForVold; /** External storage dirs, as visible to apps */ private final File[] mExternalDirsForApp; /** Primary emulated storage dir for direct access */ private final File mEmulatedDirForDirect; public UserEnvironment(int userId) { // See storage config details at http://source.android.com/tech/storage/ String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE); String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE); String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE); if (TextUtils.isEmpty(rawMediaStorage)) { rawMediaStorage = "/data/media"; } if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) { if (!TextUtils.isEmpty(rawEmulatedTarget)) { // Device has emulated storage; external storage paths should have // userId burned into them. final String rawUserId = Integer.toString(userId); final File emulatedBase = new File(rawEmulatedStorageTarget); final File emulatedSourceBase = new File(rawEmulatedSource); final File emulatedTargetBase = new File(rawEmulatedTarget); final File mediaBase = new File(rawMediaStorage); // /storage/emulated/0 mExternalDirs = new File[] { buildPath(emulatedBase, rawUserId) }; mExternalDirsForVold = new File[] { buildPath(emulatedSourceBase, rawUserId) }; mExternalDirsForApp = new File[] { buildPath(emulatedTargetBase, rawUserId) }; // /data/media/0 mMediaDir = buildPath(mediaBase, rawUserId); mEmulatedDirForDirect = buildPath(mediaBase, rawUserId); } else { // Device has physical external storage; use plain paths. Loading @@ -141,15 +148,16 @@ public class Environment { } // /storage/sdcard0 mExternalDirs = new File[] { new File(rawExternalStorage) }; mExternalDirsForVold = new File[] { new File(rawExternalStorage) }; mExternalDirsForApp = new File[] { new File(rawExternalStorage) }; // /data/media mMediaDir = new File(rawMediaStorage); mEmulatedDirForDirect = new File(rawMediaStorage); } } @Deprecated public File getExternalStorageDirectory() { return mExternalDirs[0]; return mExternalDirsForApp[0]; } @Deprecated Loading @@ -157,44 +165,56 @@ public class Environment { return buildExternalStoragePublicDirs(type)[0]; } public File[] getExternalDirs() { return mExternalDirs; public File[] getExternalDirsForVold() { return mExternalDirsForVold; } public File[] getExternalDirsForApp() { return mExternalDirsForApp; } public File getMediaDir() { return mMediaDir; return mEmulatedDirForDirect; } public File[] buildExternalStoragePublicDirs(String type) { return buildPaths(mExternalDirs, type); return buildPaths(mExternalDirsForApp, type); } public File[] buildExternalStorageAndroidDataDirs() { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA); } public File[] buildExternalStorageAndroidObbDirs() { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_OBB); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB); } public File[] buildExternalStorageAppDataDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName); } public File[] buildExternalStorageAppDataDirsForVold(String packageName) { return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_DATA, packageName); } public File[] buildExternalStorageAppMediaDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_MEDIA, packageName); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName); } public File[] buildExternalStorageAppObbDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_OBB, packageName); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName); } public File[] buildExternalStorageAppObbDirsForVold(String packageName) { return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_OBB, packageName); } public File[] buildExternalStorageAppFilesDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES); } public File[] buildExternalStorageAppCacheDirs(String packageName) { return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE); return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE); } } Loading Loading @@ -344,7 +364,7 @@ public class Environment { */ public static File getExternalStorageDirectory() { throwIfUserRequired(); return sCurrentUser.getExternalDirs()[0]; return sCurrentUser.getExternalDirsForApp()[0]; } /** {@hide} */ Loading
core/java/android/os/storage/IMountService.java +38 −2 Original line number Diff line number Diff line Loading @@ -20,9 +20,7 @@ import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.storage.StorageVolume; /** * WARNING! Update IMountService.h and IMountService.cpp if you change this Loading Loading @@ -737,7 +735,25 @@ public interface IMountService extends IInterface { _data.recycle(); } return _result; } @Override public int mkdirs(String callingPkg, String path) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(callingPkg); _data.writeString(path); mRemote.transact(Stub.TRANSACTION_mkdirs, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } Loading Loading @@ -811,6 +827,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33; static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34; /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. Loading Loading @@ -1154,6 +1172,15 @@ public interface IMountService extends IInterface { reply.writeInt(resultCode); return true; } case TRANSACTION_mkdirs: { data.enforceInterface(DESCRIPTOR); String callingPkg = data.readString(); String path = data.readString(); int result = mkdirs(callingPkg, path); reply.writeNoException(); reply.writeInt(result); return true; } } return super.onTransact(code, data, reply, flags); } Loading Loading @@ -1376,4 +1403,13 @@ public interface IMountService extends IInterface { */ public int fixPermissionsSecureContainer(String id, int gid, String filename) throws RemoteException; /** * Ensure that all directories along given path exist, creating parent * directories as needed. Validates that given path is absolute and that it * contains no relative "." or ".." paths or symlinks. Also ensures that * path belongs to a volume managed by vold, and that path is either * external storage data or OBB directory belonging to calling app. */ public int mkdirs(String callingPkg, String path) throws RemoteException; }
services/java/com/android/server/MountService.java +81 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.Manifest; import android.app.AppOpsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -2127,6 +2128,85 @@ class MountService extends IMountService.Stub } } @Override public int mkdirs(String callingPkg, String appPath) { final int userId = UserHandle.getUserId(Binder.getCallingUid()); final UserEnvironment userEnv = new UserEnvironment(userId); // Validate that reported package name belongs to caller final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService( Context.APP_OPS_SERVICE); appOps.checkPackage(Binder.getCallingUid(), callingPkg); try { appPath = new File(appPath).getCanonicalPath(); } catch (IOException e) { Slog.e(TAG, "Failed to resolve " + appPath + ": " + e); return -1; } // Try translating the app path into a vold path, but require that it // belong to the calling package. String voldPath = maybeTranslatePathForVold(appPath, userEnv.buildExternalStorageAppDataDirs(callingPkg), userEnv.buildExternalStorageAppDataDirsForVold(callingPkg)); if (voldPath != null) { try { mConnector.execute("volume", "mkdirs", voldPath); return 0; } catch (NativeDaemonConnectorException e) { return e.getCode(); } } voldPath = maybeTranslatePathForVold(appPath, userEnv.buildExternalStorageAppObbDirs(callingPkg), userEnv.buildExternalStorageAppObbDirsForVold(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); } /** * Translate the given path from an app-visible path to a vold-visible path, * but only if it's under the given whitelisted paths. * * @param path a canonicalized app-visible path. * @param appPaths list of app-visible paths that are allowed. * @param voldPaths list of vold-visible paths directly corresponding to the * allowed app-visible paths argument. * @return a vold-visible path representing the original path, or * {@code null} if the given path didn't have an app-to-vold * mapping. */ @VisibleForTesting public static String maybeTranslatePathForVold( String path, File[] appPaths, File[] voldPaths) { if (appPaths.length != voldPaths.length) { throw new IllegalStateException("Paths must be 1:1 mapping"); } for (int i = 0; i < appPaths.length; i++) { final String appPath = appPaths[i].getAbsolutePath(); if (path.startsWith(appPath)) { path = new File(voldPaths[i], path.substring(appPath.length() + 1)) .getAbsolutePath(); if (!path.endsWith("/")) { path = path + "/"; } return path; } } return null; } @Override public StorageVolume[] getVolumeList() { final int callingUserId = UserHandle.getCallingUserId(); Loading Loading @@ -2651,7 +2731,7 @@ class MountService extends IMountService.Stub if (forVold) { return new File(Environment.getEmulatedStorageSource(userId), path).getAbsolutePath(); } else { return new File(userEnv.getExternalDirs()[0], path).getAbsolutePath(); return new File(userEnv.getExternalDirsForApp()[0], path).getAbsolutePath(); } } Loading