Merge "Improve performance of storage measurement." into jb-mr2-dev

This commit is contained in:
Jeff Sharkey
2013-03-02 06:14:51 +00:00
committed by Android (Google) Code Review
3 changed files with 70 additions and 11 deletions

View File

@@ -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.
@@ -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";
@@ -178,7 +183,7 @@ public class Environment {
* Gets the Android root directory.
*/
public static File getRootDirectory() {
return ROOT_DIRECTORY;
return DIR_ANDROID_ROOT;
}
/**
@@ -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());
@@ -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;
}
}

View File

@@ -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" />

View File

@@ -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;
@@ -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;
@@ -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;
}