diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/SystemServiceRegistry.java | 8 | ||||
-rw-r--r-- | core/java/android/net/TrafficStats.java | 2 | ||||
-rw-r--r-- | core/java/android/os/Environment.java | 244 | ||||
-rw-r--r-- | core/java/android/os/FileUtils.java | 17 | ||||
-rw-r--r-- | core/java/android/os/Process.java | 6 | ||||
-rw-r--r-- | core/java/android/os/storage/IMountService.java | 8 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageManager.java | 93 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageVolume.java | 64 | ||||
-rw-r--r-- | core/java/android/util/DebugUtils.java | 57 | ||||
-rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 9 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 6 |
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=")) { |