Loading core/java/android/os/Environment.java +57 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.io.File; import java.io.IOException; /** * Provides access to environment variables. Loading @@ -36,12 +37,16 @@ public class Environment { private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE"; private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"; private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; /** {@hide} */ public static String DIRECTORY_ANDROID = "Android"; private static final File ROOT_DIRECTORY = getDirectory("ANDROID_ROOT", "/system"); private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system"); private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media"); private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull( ENV_EMULATED_STORAGE_TARGET); private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; Loading Loading @@ -178,7 +183,7 @@ public class Environment { * Gets the Android root directory. */ public static File getRootDirectory() { return ROOT_DIRECTORY; return DIR_ANDROID_ROOT; } /** Loading Loading @@ -632,6 +637,19 @@ public class Environment { return path == null ? new File(defaultPath) : new File(path); } private static String getCanonicalPathOrNull(String variableName) { String path = System.getenv(variableName); if (path == null) { return null; } try { return new File(path).getCanonicalPath(); } catch (IOException e) { Log.w(TAG, "Unable to resolve canonical path for " + path); return null; } } private static void throwIfSystem() { if (Process.myUid() == Process.SYSTEM_UID) { Log.wtf(TAG, "Static storage paths aren't available from AID_SYSTEM", new Throwable()); Loading @@ -649,4 +667,40 @@ public class Environment { } return cur; } /** * If the given path exists on emulated external storage, return the * translated backing path hosted on internal storage. This bypasses any * emulation later, improving performance. This is <em>only</em> suitable * for read-only access. * <p> * Returns original path if given path doesn't meet these criteria. Callers * must hold {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} * permission. * * @hide */ public static File maybeTranslateEmulatedPathToInternal(File path) { // Fast return if not emulated, or missing variables if (!Environment.isExternalStorageEmulated() || CANONCIAL_EMULATED_STORAGE_TARGET == null) { return path; } try { final String rawPath = path.getCanonicalPath(); if (rawPath.startsWith(CANONCIAL_EMULATED_STORAGE_TARGET)) { final File internalPath = new File(DIR_MEDIA_STORAGE, rawPath.substring(CANONCIAL_EMULATED_STORAGE_TARGET.length())); if (internalPath.exists()) { return internalPath; } } } catch (IOException e) { Log.w(TAG, "Failed to resolve canonical path for " + path); } // Unable to translate to internal path; use original return path; } } packages/DefaultContainerService/AndroidManifest.xml +2 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ <uses-permission android:name="android.permission.ASEC_DESTROY"/> <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Used to improve MeasureUtils performance on emulated storage --> <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" /> <uses-permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" /> Loading packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +11 −8 Original line number Diff line number Diff line Loading @@ -16,16 +16,12 @@ package com.android.defcontainer; import com.android.internal.app.IMediaContainerService; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import android.app.IntentService; import android.content.Intent; import android.content.pm.MacAuthenticatedInputStream; import android.content.pm.ContainerEncryptionParams; import android.content.pm.IPackageManager; import android.content.pm.LimitedLengthInputStream; import android.content.pm.MacAuthenticatedInputStream; import android.content.pm.PackageCleanItem; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; Loading @@ -43,10 +39,16 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StatFs; import android.os.SystemClock; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Log; import android.util.Slog; import com.android.internal.app.IMediaContainerService; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; Loading Loading @@ -228,9 +230,10 @@ public class DefaultContainerService extends IntentService { public long calculateDirectorySize(String path) throws RemoteException { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); final File directory = new File(path); if (directory.exists() && directory.isDirectory()) { return MeasurementUtils.measureDirectory(path); final File dir = Environment.maybeTranslateEmulatedPathToInternal(new File(path)); if (dir.exists() && dir.isDirectory()) { final String targetPath = dir.getAbsolutePath(); return MeasurementUtils.measureDirectory(targetPath); } else { return 0L; } Loading Loading
core/java/android/os/Environment.java +57 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.io.File; import java.io.IOException; /** * Provides access to environment variables. Loading @@ -36,12 +37,16 @@ public class Environment { private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE"; private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"; private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; /** {@hide} */ public static String DIRECTORY_ANDROID = "Android"; private static final File ROOT_DIRECTORY = getDirectory("ANDROID_ROOT", "/system"); private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system"); private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media"); private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull( ENV_EMULATED_STORAGE_TARGET); private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; Loading Loading @@ -178,7 +183,7 @@ public class Environment { * Gets the Android root directory. */ public static File getRootDirectory() { return ROOT_DIRECTORY; return DIR_ANDROID_ROOT; } /** Loading Loading @@ -632,6 +637,19 @@ public class Environment { return path == null ? new File(defaultPath) : new File(path); } private static String getCanonicalPathOrNull(String variableName) { String path = System.getenv(variableName); if (path == null) { return null; } try { return new File(path).getCanonicalPath(); } catch (IOException e) { Log.w(TAG, "Unable to resolve canonical path for " + path); return null; } } private static void throwIfSystem() { if (Process.myUid() == Process.SYSTEM_UID) { Log.wtf(TAG, "Static storage paths aren't available from AID_SYSTEM", new Throwable()); Loading @@ -649,4 +667,40 @@ public class Environment { } return cur; } /** * If the given path exists on emulated external storage, return the * translated backing path hosted on internal storage. This bypasses any * emulation later, improving performance. This is <em>only</em> suitable * for read-only access. * <p> * Returns original path if given path doesn't meet these criteria. Callers * must hold {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} * permission. * * @hide */ public static File maybeTranslateEmulatedPathToInternal(File path) { // Fast return if not emulated, or missing variables if (!Environment.isExternalStorageEmulated() || CANONCIAL_EMULATED_STORAGE_TARGET == null) { return path; } try { final String rawPath = path.getCanonicalPath(); if (rawPath.startsWith(CANONCIAL_EMULATED_STORAGE_TARGET)) { final File internalPath = new File(DIR_MEDIA_STORAGE, rawPath.substring(CANONCIAL_EMULATED_STORAGE_TARGET.length())); if (internalPath.exists()) { return internalPath; } } } catch (IOException e) { Log.w(TAG, "Failed to resolve canonical path for " + path); } // Unable to translate to internal path; use original return path; } }
packages/DefaultContainerService/AndroidManifest.xml +2 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ <uses-permission android:name="android.permission.ASEC_DESTROY"/> <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Used to improve MeasureUtils performance on emulated storage --> <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" /> <uses-permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" /> Loading
packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +11 −8 Original line number Diff line number Diff line Loading @@ -16,16 +16,12 @@ package com.android.defcontainer; import com.android.internal.app.IMediaContainerService; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import android.app.IntentService; import android.content.Intent; import android.content.pm.MacAuthenticatedInputStream; import android.content.pm.ContainerEncryptionParams; import android.content.pm.IPackageManager; import android.content.pm.LimitedLengthInputStream; import android.content.pm.MacAuthenticatedInputStream; import android.content.pm.PackageCleanItem; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; Loading @@ -43,10 +39,16 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StatFs; import android.os.SystemClock; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Log; import android.util.Slog; import com.android.internal.app.IMediaContainerService; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; Loading Loading @@ -228,9 +230,10 @@ public class DefaultContainerService extends IntentService { public long calculateDirectorySize(String path) throws RemoteException { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); final File directory = new File(path); if (directory.exists() && directory.isDirectory()) { return MeasurementUtils.measureDirectory(path); final File dir = Environment.maybeTranslateEmulatedPathToInternal(new File(path)); if (dir.exists() && dir.isDirectory()) { final String targetPath = dir.getAbsolutePath(); return MeasurementUtils.measureDirectory(targetPath); } else { return 0L; } Loading