summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/SystemServiceRegistry.java8
-rw-r--r--core/java/android/net/TrafficStats.java2
-rw-r--r--core/java/android/os/Environment.java244
-rw-r--r--core/java/android/os/FileUtils.java17
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/os/storage/IMountService.java8
-rw-r--r--core/java/android/os/storage/StorageManager.java93
-rw-r--r--core/java/android/os/storage/StorageVolume.java64
-rw-r--r--core/java/android/util/DebugUtils.java57
-rw-r--r--core/java/com/android/internal/os/Zygote.java9
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java6
11 files changed, 223 insertions, 291 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 59fe490..a0f40f6 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -402,13 +402,7 @@ final class SystemServiceRegistry {
new CachedServiceFetcher<StorageManager>() {
@Override
public StorageManager createService(ContextImpl ctx) {
- try {
- return new StorageManager(
- ctx.getContentResolver(), ctx.mMainThread.getHandler().getLooper());
- } catch (RemoteException rex) {
- Log.e(TAG, "Failed to create StorageManager", rex);
- return null;
- }
+ return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper());
}});
registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 3f18519..ff3de2b 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -51,6 +51,8 @@ public class TrafficStats {
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
/** @hide */
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
+ /** @hide */
+ public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
/**
* Special UID value used when collecting {@link NetworkStatsHistory} for
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 975bfc2..2db976e 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -18,16 +18,11 @@ package android.os;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
-import android.text.TextUtils;
import android.util.Log;
-import com.google.android.collect.Lists;
-
import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
/**
* Provides access to environment variables.
@@ -36,11 +31,9 @@ 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_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_SECONDARY_STORAGE = "SECONDARY_STORAGE";
private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
+ private static final String ENV_ANDROID_DATA = "ANDROID_DATA";
+ private static final String ENV_ANDROID_STORAGE = "ANDROID_STORAGE";
private static final String ENV_OEM_ROOT = "OEM_ROOT";
private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
@@ -57,12 +50,10 @@ public class Environment {
public static final String DIRECTORY_ANDROID = DIR_ANDROID;
private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
+ private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
+ private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
- 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";
@@ -81,73 +72,24 @@ public class Environment {
/** {@hide} */
public static class UserEnvironment {
- // TODO: generalize further to create package-specific environment
-
- /** 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;
+ private final int mUserId;
public UserEnvironment(int userId) {
- // See storage config details at http://source.android.com/tech/storage/
- String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
- 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";
- }
-
- ArrayList<File> externalForVold = Lists.newArrayList();
- ArrayList<File> externalForApp = Lists.newArrayList();
-
- 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 emulatedSourceBase = new File(rawEmulatedSource);
- final File emulatedTargetBase = new File(rawEmulatedTarget);
- final File mediaBase = new File(rawMediaStorage);
-
- // /storage/emulated/0
- externalForVold.add(buildPath(emulatedSourceBase, rawUserId));
- externalForApp.add(buildPath(emulatedTargetBase, rawUserId));
- // /data/media/0
- mEmulatedDirForDirect = buildPath(mediaBase, rawUserId);
-
- } 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
- externalForVold.add(new File(rawExternalStorage));
- externalForApp.add(new File(rawExternalStorage));
- // /data/media
- mEmulatedDirForDirect = new File(rawMediaStorage);
- }
+ mUserId = userId;
+ }
- // Splice in any secondary storage paths, but only for owner
- final String rawSecondaryStorage = System.getenv(ENV_SECONDARY_STORAGE);
- if (!TextUtils.isEmpty(rawSecondaryStorage) && userId == UserHandle.USER_OWNER) {
- for (String secondaryPath : rawSecondaryStorage.split(":")) {
- externalForVold.add(new File(secondaryPath));
- externalForApp.add(new File(secondaryPath));
- }
+ public File[] getExternalDirs() {
+ final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId);
+ final File[] dirs = new File[volumes.length];
+ for (int i = 0; i < volumes.length; i++) {
+ dirs[i] = volumes[i].getPathFile();
}
-
- mExternalDirsForVold = externalForVold.toArray(new File[externalForVold.size()]);
- mExternalDirsForApp = externalForApp.toArray(new File[externalForApp.size()]);
+ return dirs;
}
@Deprecated
public File getExternalStorageDirectory() {
- return mExternalDirsForApp[0];
+ return getExternalDirs()[0];
}
@Deprecated
@@ -155,60 +97,36 @@ public class Environment {
return buildExternalStoragePublicDirs(type)[0];
}
- public File[] getExternalDirsForVold() {
- return mExternalDirsForVold;
- }
-
- public File[] getExternalDirsForApp() {
- return mExternalDirsForApp;
- }
-
- public File getMediaDir() {
- return mEmulatedDirForDirect;
- }
-
public File[] buildExternalStoragePublicDirs(String type) {
- return buildPaths(mExternalDirsForApp, type);
+ return buildPaths(getExternalDirs(), type);
}
public File[] buildExternalStorageAndroidDataDirs() {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA);
}
public File[] buildExternalStorageAndroidObbDirs() {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_OBB);
}
public File[] buildExternalStorageAppDataDirs(String packageName) {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName);
- }
-
- public File[] buildExternalStorageAppDataDirsForVold(String packageName) {
- return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_DATA, packageName);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName);
}
public File[] buildExternalStorageAppMediaDirs(String packageName) {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName);
- }
-
- public File[] buildExternalStorageAppMediaDirsForVold(String packageName) {
- return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_MEDIA, packageName);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_MEDIA, packageName);
}
public File[] buildExternalStorageAppObbDirs(String packageName) {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName);
- }
-
- public File[] buildExternalStorageAppObbDirsForVold(String packageName) {
- return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_OBB, packageName);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_OBB, packageName);
}
public File[] buildExternalStorageAppFilesDirs(String packageName) {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
}
public File[] buildExternalStorageAppCacheDirs(String packageName) {
- return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
+ return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
}
}
@@ -220,6 +138,11 @@ public class Environment {
return DIR_ANDROID_ROOT;
}
+ /** {@hide} */
+ public static File getStorageDirectory() {
+ return DIR_ANDROID_STORAGE;
+ }
+
/**
* Return root directory of the "oem" partition holding OEM customizations,
* if any. If present, the partition is mounted read-only.
@@ -270,17 +193,6 @@ public class Environment {
}
/**
- * Return directory used for internal media storage, which is protected by
- * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
- *
- * @hide
- */
- public static File getMediaStorageDirectory() {
- throwIfUserRequired();
- return sCurrentUser.getMediaDir();
- }
-
- /**
* Return the system directory for a user. This is for use by system services to store
* files relating to the user. This directory will be automatically deleted when the user
* is removed.
@@ -389,7 +301,7 @@ public class Environment {
*/
public static File getExternalStorageDirectory() {
throwIfUserRequired();
- return sCurrentUser.getExternalDirsForApp()[0];
+ return sCurrentUser.getExternalDirs()[0];
}
/** {@hide} */
@@ -402,18 +314,6 @@ public class Environment {
return buildPath(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB);
}
- /** {@hide} */
- public static File getEmulatedStorageSource(int userId) {
- // /mnt/shell/emulated/0
- return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId));
- }
-
- /** {@hide} */
- public static File getEmulatedStorageObbSource() {
- // /mnt/shell/emulated/obb
- return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), DIR_OBB);
- }
-
/**
* Standard directory in which to place any audio files that should be
* in the regular list of music for the user.
@@ -683,6 +583,13 @@ public class Environment {
public static final String MEDIA_UNMOUNTABLE = "unmountable";
/**
+ * Storage state if the media is in the process of being ejected.
+ *
+ * @see #getExternalStorageState(File)
+ */
+ public static final String MEDIA_EJECTING = "ejecting";
+
+ /**
* Returns the current state of the primary "external" storage device.
*
* @see #getExternalStorageDirectory()
@@ -693,7 +600,7 @@ public class Environment {
* {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
*/
public static String getExternalStorageState() {
- final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
return getExternalStorageState(externalDir);
}
@@ -716,17 +623,12 @@ public class Environment {
* {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
*/
public static String getExternalStorageState(File path) {
- final StorageVolume volume = getStorageVolume(path);
+ final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
- final IMountService mountService = IMountService.Stub.asInterface(
- ServiceManager.getService("mount"));
- try {
- return mountService.getVolumeState(volume.getPath());
- } catch (RemoteException e) {
- }
+ return volume.getState();
+ } else {
+ return MEDIA_UNKNOWN;
}
-
- return Environment.MEDIA_UNKNOWN;
}
/**
@@ -738,7 +640,7 @@ public class Environment {
*/
public static boolean isExternalStorageRemovable() {
if (isStorageDisabled()) return false;
- final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
return isExternalStorageRemovable(externalDir);
}
@@ -753,7 +655,7 @@ public class Environment {
* device.
*/
public static boolean isExternalStorageRemovable(File path) {
- final StorageVolume volume = getStorageVolume(path);
+ final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.isRemovable();
} else {
@@ -771,7 +673,7 @@ public class Environment {
*/
public static boolean isExternalStorageEmulated() {
if (isStorageDisabled()) return false;
- final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
return isExternalStorageEmulated(externalDir);
}
@@ -784,7 +686,7 @@ public class Environment {
* device.
*/
public static boolean isExternalStorageEmulated(File path) {
- final StorageVolume volume = getStorageVolume(path);
+ final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.isEmulated();
} else {
@@ -797,19 +699,6 @@ 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;
- }
- }
-
/** {@hide} */
public static void setUserRequired(boolean userRequired) {
sUserRequired = userRequired;
@@ -856,28 +745,6 @@ public class Environment {
return SystemProperties.getBoolean("config.disable_storage", false);
}
- private static StorageVolume getStorageVolume(File path) {
- try {
- path = path.getCanonicalFile();
- } catch (IOException e) {
- return null;
- }
-
- try {
- final IMountService mountService = IMountService.Stub.asInterface(
- ServiceManager.getService("mount"));
- final StorageVolume[] volumes = mountService.getVolumeList();
- for (StorageVolume volume : volumes) {
- if (FileUtils.contains(volume.getPathFile(), path)) {
- return volume;
- }
- }
- } catch (RemoteException e) {
- }
-
- return null;
- }
-
/**
* If the given path exists on emulated external storage, return the
* translated backing path hosted on internal storage. This bypasses any
@@ -891,26 +758,7 @@ public class Environment {
* @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
+ // TODO: bring back this optimization
return path;
}
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 0a724a1..b302f95 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -369,6 +369,23 @@ public class FileUtils {
* {@link File#getCanonicalFile()} to avoid symlink or path traversal
* attacks.
*/
+ public static boolean contains(File[] dirs, File file) {
+ for (File dir : dirs) {
+ if (contains(dir, file)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test if a file lives under the given directory, either as a direct child
+ * or a distant grandchild.
+ * <p>
+ * Both files <em>must</em> have been resolved using
+ * {@link File#getCanonicalFile()} to avoid symlink or path traversal
+ * attacks.
+ */
public static boolean contains(File dir, File file) {
if (file == null) return false;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 0de9c70..355ec8c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -637,10 +637,8 @@ public class Process {
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
- if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
- argsForZygote.add("--mount-external-multiuser");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
- argsForZygote.add("--mount-external-multiuser-all");
+ if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
+ argsForZygote.add("--mount-external-default");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 6209c2a..fef12d1 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -757,12 +757,13 @@ public interface IMountService extends IInterface {
return _result;
}
- public StorageVolume[] getVolumeList() throws RemoteException {
+ public StorageVolume[] getVolumeList(int userId) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
StorageVolume[] _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(userId);
mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArray(StorageVolume.CREATOR);
@@ -1308,7 +1309,8 @@ public interface IMountService extends IInterface {
}
case TRANSACTION_getVolumeList: {
data.enforceInterface(DESCRIPTOR);
- StorageVolume[] result = getVolumeList();
+ int userId = data.readInt();
+ StorageVolume[] result = getVolumeList(userId);
reply.writeNoException();
reply.writeTypedArray(result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
return true;
@@ -1630,7 +1632,7 @@ public interface IMountService extends IInterface {
/**
* Returns list of all mountable volumes.
*/
- public StorageVolume[] getVolumeList() throws RemoteException;
+ public StorageVolume[] getVolumeList(int userId) throws RemoteException;
/**
* Gets the path on the filesystem for the ASEC container itself.
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2785ee8..532bf2c 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -18,19 +18,23 @@ package android.os.storage;
import static android.net.TrafficStats.MB_IN_BYTES;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
+import libcore.util.EmptyArray;
+
import com.android.internal.util.Preconditions;
import java.io.File;
@@ -60,6 +64,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class StorageManager {
private static final String TAG = "StorageManager";
+ private final Context mContext;
private final ContentResolver mResolver;
/*
@@ -311,8 +316,9 @@ public class StorageManager {
*
* @hide
*/
- public StorageManager(ContentResolver resolver, Looper tgtLooper) throws RemoteException {
- mResolver = resolver;
+ public StorageManager(Context context, Looper tgtLooper) {
+ mContext = context;
+ mResolver = context.getContentResolver();
mTgtLooper = tgtLooper;
mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
if (mMountService == null) {
@@ -548,17 +554,46 @@ public class StorageManager {
return null;
}
+ /** {@hide} */
+ public @Nullable StorageVolume getStorageVolume(File file) {
+ return getStorageVolume(getVolumeList(), file);
+ }
+
+ /** {@hide} */
+ public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
+ return getStorageVolume(getVolumeList(userId), file);
+ }
+
+ /** {@hide} */
+ private static @Nullable StorageVolume getStorageVolume(StorageVolume[] volumes, File file) {
+ File canonicalFile = null;
+ try {
+ canonicalFile = file.getCanonicalFile();
+ } catch (IOException ignored) {
+ canonicalFile = null;
+ }
+ for (StorageVolume volume : volumes) {
+ if (volume.getPathFile().equals(file)) {
+ return volume;
+ }
+ if (FileUtils.contains(volume.getPathFile(), canonicalFile)) {
+ return volume;
+ }
+ }
+ return null;
+ }
+
/**
* Gets the state of a volume via its mountpoint.
* @hide
*/
- public String getVolumeState(String mountPoint) {
- if (mMountService == null) return Environment.MEDIA_REMOVED;
- try {
- return mMountService.getVolumeState(mountPoint);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get volume state", e);
- return null;
+ @Deprecated
+ public @NonNull String getVolumeState(String mountPoint) {
+ final StorageVolume vol = getStorageVolume(new File(mountPoint));
+ if (vol != null) {
+ return vol.getState();
+ } else {
+ return Environment.MEDIA_UNKNOWN;
}
}
@@ -566,20 +601,22 @@ public class StorageManager {
* Returns list of all mountable volumes.
* @hide
*/
- public StorageVolume[] getVolumeList() {
- if (mMountService == null) return new StorageVolume[0];
+ public @NonNull StorageVolume[] getVolumeList() {
try {
- Parcelable[] list = mMountService.getVolumeList();
- if (list == null) return new StorageVolume[0];
- int length = list.length;
- StorageVolume[] result = new StorageVolume[length];
- for (int i = 0; i < length; i++) {
- result[i] = (StorageVolume)list[i];
- }
- return result;
+ return mMountService.getVolumeList(mContext.getUserId());
} catch (RemoteException e) {
- Log.e(TAG, "Failed to get volume list", e);
- return null;
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** {@hide} */
+ public static @NonNull StorageVolume[] getVolumeList(int userId) {
+ final IMountService mountService = IMountService.Stub.asInterface(
+ ServiceManager.getService("mount"));
+ try {
+ return mountService.getVolumeList(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
}
}
@@ -587,9 +624,9 @@ public class StorageManager {
* Returns list of paths for all mountable volumes.
* @hide
*/
- public String[] getVolumePaths() {
+ @Deprecated
+ public @NonNull String[] getVolumePaths() {
StorageVolume[] volumes = getVolumeList();
- if (volumes == null) return null;
int count = volumes.length;
String[] paths = new String[count];
for (int i = 0; i < count; i++) {
@@ -599,21 +636,21 @@ public class StorageManager {
}
/** {@hide} */
- public StorageVolume getPrimaryVolume() {
+ public @NonNull StorageVolume getPrimaryVolume() {
return getPrimaryVolume(getVolumeList());
}
/** {@hide} */
- public static StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
+ public static @NonNull StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
for (StorageVolume volume : volumes) {
if (volume.isPrimary()) {
return volume;
}
}
- Log.w(TAG, "No primary storage defined");
- return null;
+ throw new IllegalStateException("Missing primary storage");
}
+ /** {@hide} */
private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 06565f1..0c391ca 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -17,6 +17,7 @@
package android.os.storage;
import android.content.Context;
+import android.net.TrafficStats;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
@@ -34,52 +35,58 @@ import java.io.File;
*/
public class StorageVolume implements Parcelable {
- // TODO: switch to more durable token
- private int mStorageId;
+ private final String mId;
+ private final int mStorageId;
private final File mPath;
private final int mDescriptionId;
private final boolean mPrimary;
private final boolean mRemovable;
private final boolean mEmulated;
- private final int mMtpReserveSpace;
+ private final long mMtpReserveSize;
private final boolean mAllowMassStorage;
/** Maximum file size for the storage, or zero for no limit */
private final long mMaxFileSize;
/** When set, indicates exclusive ownership of this volume */
private final UserHandle mOwner;
- private String mUuid;
- private String mUserLabel;
- private String mState;
+ private final String mUuid;
+ private final String mUserLabel;
+ private final String mState;
// StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
// ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
// ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
- public StorageVolume(File path, int descriptionId, boolean primary, boolean removable,
- boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize,
- UserHandle owner) {
+ public StorageVolume(String id, int storageId, File path, int descriptionId, boolean primary,
+ boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage,
+ long maxFileSize, UserHandle owner, String uuid, String userLabel, String state) {
+ mId = id;
+ mStorageId = storageId;
mPath = path;
mDescriptionId = descriptionId;
mPrimary = primary;
mRemovable = removable;
mEmulated = emulated;
- mMtpReserveSpace = mtpReserveSpace;
+ mMtpReserveSize = mtpReserveSize;
mAllowMassStorage = allowMassStorage;
mMaxFileSize = maxFileSize;
mOwner = owner;
+ mUuid = uuid;
+ mUserLabel = userLabel;
+ mState = state;
}
private StorageVolume(Parcel in) {
+ mId = in.readString();
mStorageId = in.readInt();
mPath = new File(in.readString());
mDescriptionId = in.readInt();
mPrimary = in.readInt() != 0;
mRemovable = in.readInt() != 0;
mEmulated = in.readInt() != 0;
- mMtpReserveSpace = in.readInt();
+ mMtpReserveSize = in.readLong();
mAllowMassStorage = in.readInt() != 0;
mMaxFileSize = in.readLong();
mOwner = in.readParcelable(null);
@@ -88,10 +95,8 @@ public class StorageVolume implements Parcelable {
mState = in.readString();
}
- public static StorageVolume fromTemplate(StorageVolume template, File path, UserHandle owner) {
- return new StorageVolume(path, template.mDescriptionId, template.mPrimary,
- template.mRemovable, template.mEmulated, template.mMtpReserveSpace,
- template.mAllowMassStorage, template.mMaxFileSize, owner);
+ public String getId() {
+ return mId;
}
/**
@@ -153,15 +158,6 @@ public class StorageVolume implements Parcelable {
}
/**
- * Do not call this unless you are MountService
- */
- public void setStorageId(int index) {
- // storage ID is 0x00010001 for primary storage,
- // then 0x00020001, 0x00030001, etc. for secondary storages
- mStorageId = ((index + 1) << 16) + 1;
- }
-
- /**
* Number of megabytes of space to leave unallocated by MTP.
* MTP will subtract this value from the free space it reports back
* to the host via GetStorageInfo, and will not allow new files to
@@ -174,7 +170,7 @@ public class StorageVolume implements Parcelable {
* @return MTP reserve space
*/
public int getMtpReserveSpace() {
- return mMtpReserveSpace;
+ return (int) (mMtpReserveSize / TrafficStats.MB_IN_BYTES);
}
/**
@@ -199,10 +195,6 @@ public class StorageVolume implements Parcelable {
return mOwner;
}
- public void setUuid(String uuid) {
- mUuid = uuid;
- }
-
public String getUuid() {
return mUuid;
}
@@ -222,18 +214,10 @@ public class StorageVolume implements Parcelable {
}
}
- public void setUserLabel(String userLabel) {
- mUserLabel = userLabel;
- }
-
public String getUserLabel() {
return mUserLabel;
}
- public void setState(String state) {
- mState = state;
- }
-
public String getState() {
return mState;
}
@@ -262,13 +246,14 @@ public class StorageVolume implements Parcelable {
public void dump(IndentingPrintWriter pw) {
pw.println("StorageVolume:");
pw.increaseIndent();
+ pw.printPair("mId", mId);
pw.printPair("mStorageId", mStorageId);
pw.printPair("mPath", mPath);
pw.printPair("mDescriptionId", mDescriptionId);
pw.printPair("mPrimary", mPrimary);
pw.printPair("mRemovable", mRemovable);
pw.printPair("mEmulated", mEmulated);
- pw.printPair("mMtpReserveSpace", mMtpReserveSpace);
+ pw.printPair("mMtpReserveSize", mMtpReserveSize);
pw.printPair("mAllowMassStorage", mAllowMassStorage);
pw.printPair("mMaxFileSize", mMaxFileSize);
pw.printPair("mOwner", mOwner);
@@ -297,13 +282,14 @@ public class StorageVolume implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(mId);
parcel.writeInt(mStorageId);
parcel.writeString(mPath.toString());
parcel.writeInt(mDescriptionId);
parcel.writeInt(mPrimary ? 1 : 0);
parcel.writeInt(mRemovable ? 1 : 0);
parcel.writeInt(mEmulated ? 1 : 0);
- parcel.writeInt(mMtpReserveSpace);
+ parcel.writeLong(mMtpReserveSize);
parcel.writeInt(mAllowMassStorage ? 1 : 0);
parcel.writeLong(mMaxFileSize);
parcel.writeParcelable(mOwner, flags);
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 84d9ce8..c44f42b 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -17,8 +17,10 @@
package android.util;
import java.io.PrintWriter;
-import java.lang.reflect.Method;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.Locale;
/**
@@ -203,4 +205,57 @@ public class DebugUtils {
outBuilder.append(suffix);
return outBuilder.toString();
}
+
+ /**
+ * Use prefixed constants (static final values) on given class to turn value
+ * into human-readable string.
+ *
+ * @hide
+ */
+ public static String valueToString(Class<?> clazz, String prefix, int value) {
+ for (Field field : clazz.getDeclaredFields()) {
+ final int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
+ && field.getType().equals(int.class) && field.getName().startsWith(prefix)) {
+ try {
+ if (value == field.getInt(null)) {
+ return field.getName().substring(prefix.length());
+ }
+ } catch (IllegalAccessException ignored) {
+ }
+ }
+ }
+ return Integer.toString(value);
+ }
+
+ /**
+ * Use prefixed constants (static final values) on given class to turn flags
+ * into human-readable string.
+ *
+ * @hide
+ */
+ public static String flagsToString(Class<?> clazz, String prefix, int flags) {
+ final StringBuilder res = new StringBuilder();
+
+ for (Field field : clazz.getDeclaredFields()) {
+ final int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
+ && field.getType().equals(int.class) && field.getName().startsWith(prefix)) {
+ try {
+ final int value = field.getInt(null);
+ if ((flags & value) != 0) {
+ flags &= ~value;
+ res.append(field.getName().substring(prefix.length())).append('|');
+ }
+ } catch (IllegalAccessException ignored) {
+ }
+ }
+ }
+ if (flags != 0 || res.length() == 0) {
+ res.append(Integer.toHexString(flags));
+ } else {
+ res.deleteCharAt(res.length() - 1);
+ }
+ return res.toString();
+ }
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 8674a21..75b6446 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -41,15 +41,10 @@ public final class Zygote {
/** enable the JIT compiler */
public static final int DEBUG_ENABLE_JIT = 1 << 5;
-
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = 0;
- /** Single-user external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
- /** Multi-user external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
- /** All multi-user external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+ /** Default user-specific external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_DEFAULT = 1;
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4d405b2..9106ccd 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -514,10 +514,8 @@ class ZygoteConnection {
"Duplicate arg specified");
}
niceName = arg.substring(arg.indexOf('=') + 1);
- } else if (arg.equals("--mount-external-multiuser")) {
- mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
- } else if (arg.equals("--mount-external-multiuser-all")) {
- mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
+ } else if (arg.equals("--mount-external-default")) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT;
} else if (arg.equals("--query-abi-list")) {
abiListQuery = true;
} else if (arg.startsWith("--instruction-set=")) {