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

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

Merge "Include user identifier in external storage paths." into jb-mr1-dev

parents 8a0e1fef b049e212
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -4877,6 +4878,8 @@ public final class ActivityThread {
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        Security.addProvider(new AndroidKeyStoreProvider());

        Process.setArgV0("<pre-initialized>");
+5 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package android.content.pm;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.os.UserHandle;

/**
 * Per-user information.
@@ -92,6 +92,10 @@ public class UserInfo implements Parcelable {
        serialNumber = orig.serialNumber;
    }

    public UserHandle getUserHandle() {
        return new UserHandle(id);
    }

    @Override
    public String toString() {
        return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}";
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ public final class Debug
     * Default trace file path and file
     */
    private static final String DEFAULT_TRACE_PATH_PREFIX =
        Environment.getExternalStorageDirectory().getPath() + "/";
        Environment.getLegacyExternalStorageDirectory().getPath() + "/";
    private static final String DEFAULT_TRACE_BODY = "dmtrace";
    private static final String DEFAULT_TRACE_EXTENSION = ".trace";
    private static final String DEFAULT_TRACE_FILE_PATH =
+153 −41
Original line number Diff line number Diff line
@@ -16,9 +16,10 @@

package android.os;

import android.content.res.Resources;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
@@ -29,31 +30,125 @@ import java.io.File;
public class Environment {
    private static final String TAG = "Environment";

    private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
    private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";

    private static final File ROOT_DIRECTORY
            = getDirectory("ANDROID_ROOT", "/system");

    private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";

    private static final Object mLock = new Object();
    private static UserEnvironment sCurrentUser;

    private static final Object sLock = new Object();

    private volatile static StorageVolume mPrimaryVolume = null;
    // @GuardedBy("sLock")
    private static volatile StorageVolume sPrimaryVolume;

    private static StorageVolume getPrimaryVolume() {
        if (mPrimaryVolume == null) {
            synchronized (mLock) {
                if (mPrimaryVolume == null) {
        if (sPrimaryVolume == null) {
            synchronized (sLock) {
                if (sPrimaryVolume == null) {
                    try {
                        IMountService mountService = IMountService.Stub.asInterface(ServiceManager
                                .getService("mount"));
                        Parcelable[] volumes = mountService.getVolumeList();
                        mPrimaryVolume = (StorageVolume)volumes[0];
                        final StorageVolume[] volumes = mountService.getVolumeList();
                        sPrimaryVolume = StorageManager.getPrimaryVolume(volumes);
                    } catch (Exception e) {
                        Log.e(TAG, "couldn't talk to MountService", e);
                    }
                }
            }
        }
        return mPrimaryVolume;
        return sPrimaryVolume;
    }

    static {
        initForCurrentUser();
    }

    /** {@hide} */
    public static void initForCurrentUser() {
        final int userId = UserHandle.myUserId();
        sCurrentUser = new UserEnvironment(userId);

        synchronized (sLock) {
            sPrimaryVolume = null;
        }
    }

    /** {@hide} */
    public static class UserEnvironment {
        // TODO: generalize further to create package-specific environment

        private final File mExternalStorage;
        private final File mExternalStorageAndroidData;
        private final File mExternalStorageAndroidMedia;
        private final File mExternalStorageAndroidObb;

        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);

            if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
                // Device has emulated storage; external storage paths should have
                // userId burned into them.
                final File emulatedBase = new File(rawEmulatedStorageTarget);

                // /storage/emulated/0
                mExternalStorage = buildPath(emulatedBase, Integer.toString(userId));
                // /storage/emulated/obb
                mExternalStorageAndroidObb = buildPath(emulatedBase, "obb");

            } else {
                // Device has physical external storage; use plain paths.
                if (TextUtils.isEmpty(rawExternalStorage)) {
                    Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default");
                    rawExternalStorage = "/storage/sdcard0";
                }

                // /storage/sdcard0
                mExternalStorage = new File(rawExternalStorage);
                // /storage/sdcard0/Android/obb
                mExternalStorageAndroidObb = buildPath(mExternalStorage, "Android", "obb");
            }

            mExternalStorageAndroidData = buildPath(mExternalStorage, "Android", "data");
            mExternalStorageAndroidMedia = buildPath(mExternalStorage, "Android", "media");
        }

        public File getExternalStorageDirectory() {
            return mExternalStorage;
        }

        public File getExternalStoragePublicDirectory(String type) {
            return new File(mExternalStorage, type);
        }

        public File getExternalStorageAndroidDataDir() {
            return mExternalStorageAndroidData;
        }

        public File getExternalStorageAppDataDirectory(String packageName) {
            return new File(mExternalStorageAndroidData, packageName);
        }

        public File getExternalStorageAppMediaDirectory(String packageName) {
            return new File(mExternalStorageAndroidMedia, packageName);
        }

        public File getExternalStorageAppObbDirectory(String packageName) {
            return new File(mExternalStorageAndroidObb, packageName);
        }

        public File getExternalStorageAppFilesDirectory(String packageName) {
            return new File(new File(mExternalStorageAndroidData, packageName), "files");
        }

        public File getExternalStorageAppCacheDirectory(String packageName) {
            return new File(new File(mExternalStorageAndroidData, packageName), "cache");
        }
    }

    /**
@@ -137,20 +232,7 @@ public class Environment {
    private static final File MEDIA_STORAGE_DIRECTORY
            = getDirectory("MEDIA_STORAGE", "/data/media");

    private static final File EXTERNAL_STORAGE_DIRECTORY
            = getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0");

    private static final File EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY = new File(new File(
            getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0"), "Android"), "data");

    private static final File EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY = new File(new File(
            getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0"), "Android"), "media");

    private static final File EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY = new File(new File(
            getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0"), "Android"), "obb");

    private static final File DOWNLOAD_CACHE_DIRECTORY
            = getDirectory("DOWNLOAD_CACHE", "/cache");
    private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache");

    /**
     * Gets the Android data directory.
@@ -198,7 +280,13 @@ public class Environment {
     * @see #isExternalStorageRemovable()
     */
    public static File getExternalStorageDirectory() {
        return EXTERNAL_STORAGE_DIRECTORY;
        throwIfSystem();
        return sCurrentUser.getExternalStorageDirectory();
    }

    /** {@hide} */
    public static File getLegacyExternalStorageDirectory() {
        return new File(System.getenv(ENV_EXTERNAL_STORAGE));
    }

    /**
@@ -318,7 +406,8 @@ public class Environment {
     * using it such as with {@link File#mkdirs File.mkdirs()}.
     */
    public static File getExternalStoragePublicDirectory(String type) {
        return new File(getExternalStorageDirectory(), type);
        throwIfSystem();
        return sCurrentUser.getExternalStoragePublicDirectory(type);
    }

    /**
@@ -326,7 +415,8 @@ public class Environment {
     * @hide
     */
    public static File getExternalStorageAndroidDataDir() {
        return EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY;
        throwIfSystem();
        return sCurrentUser.getExternalStorageAndroidDataDir();
    }
    
    /**
@@ -334,7 +424,8 @@ public class Environment {
     * @hide
     */
    public static File getExternalStorageAppDataDirectory(String packageName) {
        return new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, packageName);
        throwIfSystem();
        return sCurrentUser.getExternalStorageAppDataDirectory(packageName);
    }
    
    /**
@@ -342,7 +433,8 @@ public class Environment {
     * @hide
     */
    public static File getExternalStorageAppMediaDirectory(String packageName) {
        return new File(EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY, packageName);
        throwIfSystem();
        return sCurrentUser.getExternalStorageAppMediaDirectory(packageName);
    }
    
    /**
@@ -350,7 +442,8 @@ public class Environment {
     * @hide
     */
    public static File getExternalStorageAppObbDirectory(String packageName) {
        return new File(EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY, packageName);
        throwIfSystem();
        return sCurrentUser.getExternalStorageAppObbDirectory(packageName);
    }
    
    /**
@@ -358,8 +451,8 @@ public class Environment {
     * @hide
     */
    public static File getExternalStorageAppFilesDirectory(String packageName) {
        return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY,
                packageName), "files");
        throwIfSystem();
        return sCurrentUser.getExternalStorageAppFilesDirectory(packageName);
    }

    /**
@@ -367,8 +460,8 @@ public class Environment {
     * @hide
     */
    public static File getExternalStorageAppCacheDirectory(String packageName) {
        return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY,
                packageName), "cache");
        throwIfSystem();
        return sCurrentUser.getExternalStorageAppCacheDirectory(packageName);
    }
    
    /**
@@ -441,9 +534,10 @@ public class Environment {
        try {
            IMountService mountService = IMountService.Stub.asInterface(ServiceManager
                    .getService("mount"));
            return mountService.getVolumeState(getExternalStorageDirectory()
                    .toString());
        } catch (Exception rex) {
            final StorageVolume primary = getPrimaryVolume();
            return mountService.getVolumeState(primary.getPath());
        } catch (RemoteException rex) {
            Log.w(TAG, "Failed to read external storage state; assuming REMOVED: " + rex);
            return Environment.MEDIA_REMOVED;
        }
    }
@@ -457,8 +551,8 @@ public class Environment {
     * <p>See {@link #getExternalStorageDirectory()} for more information.
     */
    public static boolean isExternalStorageRemovable() {
        StorageVolume volume = getPrimaryVolume();
        return (volume != null && volume.isRemovable());
        final StorageVolume primary = getPrimaryVolume();
        return (primary != null && primary.isRemovable());
    }

    /**
@@ -475,12 +569,30 @@ public class Environment {
     * android.content.ComponentName, boolean)} for additional details.
     */
    public static boolean isExternalStorageEmulated() {
        StorageVolume volume = getPrimaryVolume();
        return (volume != null && volume.isEmulated());
        final StorageVolume primary = getPrimaryVolume();
        return (primary != null && primary.isEmulated());
    }

    static File getDirectory(String variableName, String defaultPath) {
        String path = System.getenv(variableName);
        return path == null ? new File(defaultPath) : new File(path);
    }

    private static void throwIfSystem() {
        if (Process.myUid() == Process.SYSTEM_UID) {
            Log.wtf(TAG, "Static storage paths aren't available from AID_SYSTEM", new Throwable());
        }
    }

    private static File buildPath(File base, String... segments) {
        File cur = base;
        for (String segment : segments) {
            if (cur == null) {
                cur = new File(segment);
            } else {
                cur = new File(cur, segment);
            }
        }
        return cur;
    }
}
+6 −6
Original line number Diff line number Diff line
@@ -677,15 +677,15 @@ public interface IMountService extends IInterface {
                return _result;
            }

            public Parcelable[] getVolumeList() throws RemoteException {
            public StorageVolume[] getVolumeList() throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                Parcelable[] _result;
                StorageVolume[] _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readParcelableArray(StorageVolume.class.getClassLoader());
                    _result = _reply.createTypedArray(StorageVolume.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
@@ -1119,9 +1119,9 @@ public interface IMountService extends IInterface {
                }
                case TRANSACTION_getVolumeList: {
                    data.enforceInterface(DESCRIPTOR);
                    Parcelable[] result = getVolumeList();
                    StorageVolume[] result = getVolumeList();
                    reply.writeNoException();
                    reply.writeParcelableArray(result, 0);
                    reply.writeTypedArray(result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    return true;
                }
                case TRANSACTION_getSecureContainerFilesystemPath: {
@@ -1358,7 +1358,7 @@ public interface IMountService extends IInterface {
    /**
     * Returns list of all mountable volumes.
     */
    public Parcelable[] getVolumeList() throws RemoteException;
    public StorageVolume[] getVolumeList() throws RemoteException;

    /**
     * Gets the path on the filesystem for the ASEC container itself.
Loading