Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e0da1ea authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

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

parents 151b71cb 63d0a067
Loading
Loading
Loading
Loading
+57 −3
Original line number Diff line number Diff line
@@ -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;
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -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" />

+11 −8
Original line number Diff line number Diff line
@@ -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;
            }