Loading core/java/android/os/storage/VolumeInfo.java +15 −10 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.res.Resources; import android.content.res.Resources; import android.mtp.MtpStorage; import android.net.Uri; import android.net.Uri; import android.os.Environment; import android.os.Environment; import android.os.Parcel; import android.os.Parcel; Loading Loading @@ -300,6 +299,8 @@ public class VolumeInfo implements Parcelable { } } public StorageVolume buildStorageVolume(Context context, int userId) { public StorageVolume buildStorageVolume(Context context, int userId) { final StorageManager storage = context.getSystemService(StorageManager.class); final boolean removable; final boolean removable; final boolean emulated; final boolean emulated; final boolean allowMassStorage = false; final boolean allowMassStorage = false; Loading @@ -310,14 +311,7 @@ public class VolumeInfo implements Parcelable { userPath = new File("/dev/null"); userPath = new File("/dev/null"); } } String description = getDescription(); String description = null; if (description == null) { description = getFsUuid(); } if (description == null) { description = context.getString(android.R.string.unknownName); } long mtpReserveSize = 0; long mtpReserveSize = 0; long maxFileSize = 0; long maxFileSize = 0; int mtpStorageId = StorageVolume.STORAGE_ID_INVALID; int mtpStorageId = StorageVolume.STORAGE_ID_INVALID; Loading @@ -325,11 +319,16 @@ public class VolumeInfo implements Parcelable { if (type == TYPE_EMULATED) { if (type == TYPE_EMULATED) { emulated = true; emulated = true; final VolumeInfo privateVol = storage.findPrivateForEmulated(this); if (privateVol != null) { description = storage.getBestVolumeDescription(privateVol); } if (isPrimary()) { if (isPrimary()) { mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; } } mtpReserveSize = StorageManager.from(context).getStorageLowBytes(userPath); mtpReserveSize = storage.getStorageLowBytes(userPath); if (ID_EMULATED_INTERNAL.equals(id)) { if (ID_EMULATED_INTERNAL.equals(id)) { removable = false; removable = false; Loading @@ -341,6 +340,8 @@ public class VolumeInfo implements Parcelable { emulated = false; emulated = false; removable = true; removable = true; description = storage.getBestVolumeDescription(this); if (isPrimary()) { if (isPrimary()) { mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; } else { } else { Loading @@ -357,6 +358,10 @@ public class VolumeInfo implements Parcelable { throw new IllegalStateException("Unexpected volume type " + type); throw new IllegalStateException("Unexpected volume type " + type); } } if (description == null) { description = context.getString(android.R.string.unknownName); } return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable, return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable, emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId), emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId), fsUuid, envState); fsUuid, envState); Loading services/core/java/com/android/server/MountService.java +26 −4 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.Manifest; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManagerNative; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.IActivityManager; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; Loading @@ -39,10 +40,10 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.ServiceConnection; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.ObbInfo; import android.content.res.ObbInfo; import android.mtp.MtpStorage; import android.net.Uri; import android.net.Uri; import android.os.Binder; import android.os.Binder; import android.os.DropBoxManager; import android.os.DropBoxManager; Loading @@ -53,7 +54,6 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.os.IBinder; import android.os.IBinder; import android.os.Looper; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; import android.os.Process; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteCallbackList; Loading @@ -73,6 +73,7 @@ import android.os.storage.StorageResultCode; import android.os.storage.StorageVolume; import android.os.storage.StorageVolume; import android.os.storage.VolumeInfo; import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; import android.os.storage.VolumeRecord; import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.DateUtils; Loading Loading @@ -176,7 +177,6 @@ class MountService extends IMountService.Stub } } } } private static final boolean LOCAL_LOGD = false; private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_OBB = false; private static final boolean DEBUG_OBB = false; Loading Loading @@ -723,10 +723,30 @@ class MountService extends IMountService.Stub MountServiceIdler.scheduleIdlePass(mContext); MountServiceIdler.scheduleIdlePass(mContext); } } /** * MediaProvider has a ton of code that makes assumptions about storage * paths never changing, so we outright kill them to pick up new state. */ @Deprecated private void killMediaProvider() { final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY, 0, UserHandle.USER_OWNER); if (provider != null) { final IActivityManager am = ActivityManagerNative.getDefault(); try { am.killApplicationWithAppId(provider.applicationInfo.packageName, UserHandle.getAppId(provider.applicationInfo.uid), "vold reset"); } catch (RemoteException e) { } } } private void resetIfReadyAndConnectedLocked() { private void resetIfReadyAndConnectedLocked() { Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady + ", mDaemonConnected=" + mDaemonConnected); + ", mDaemonConnected=" + mDaemonConnected); if (mSystemReady && mDaemonConnected) { if (mSystemReady && mDaemonConnected) { killMediaProvider(); mDisks.clear(); mDisks.clear(); mVolumes.clear(); mVolumes.clear(); Loading Loading @@ -1606,7 +1626,9 @@ class MountService extends IMountService.Stub waitForReady(); waitForReady(); try { try { final NativeDaemonEvent res = mConnector.execute("volume", "benchmark", volId); // TODO: make benchmark async so we don't block other commands final NativeDaemonEvent res = mConnector.execute(3 * DateUtils.MINUTE_IN_MILLIS, "volume", "benchmark", volId); return Long.parseLong(res.getMessage()); return Long.parseLong(res.getMessage()); } catch (NativeDaemonTimeoutException e) { } catch (NativeDaemonTimeoutException e) { return Long.MAX_VALUE; return Long.MAX_VALUE; Loading services/core/java/com/android/server/NativeDaemonConnector.java +11 −6 Original line number Original line Diff line number Diff line Loading @@ -69,7 +69,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo private AtomicInteger mSequenceNumber; private AtomicInteger mSequenceNumber; private static final int DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */ private static final long DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */ private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */ private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */ /** Lock held whenever communicating with native daemon. */ /** Lock held whenever communicating with native daemon. */ Loading Loading @@ -337,7 +337,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ */ public NativeDaemonEvent execute(String cmd, Object... args) public NativeDaemonEvent execute(String cmd, Object... args) throws NativeDaemonConnectorException { throws NativeDaemonConnectorException { final NativeDaemonEvent[] events = executeForList(cmd, args); return execute(DEFAULT_TIMEOUT, cmd, args); } public NativeDaemonEvent execute(long timeoutMs, String cmd, Object... args) throws NativeDaemonConnectorException { final NativeDaemonEvent[] events = executeForList(timeoutMs, cmd, args); if (events.length != 1) { if (events.length != 1) { throw new NativeDaemonConnectorException( throw new NativeDaemonConnectorException( "Expected exactly one response, but received " + events.length); "Expected exactly one response, but received " + events.length); Loading Loading @@ -372,7 +377,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ */ public NativeDaemonEvent[] executeForList(String cmd, Object... args) public NativeDaemonEvent[] executeForList(String cmd, Object... args) throws NativeDaemonConnectorException { throws NativeDaemonConnectorException { return execute(DEFAULT_TIMEOUT, cmd, args); return executeForList(DEFAULT_TIMEOUT, cmd, args); } } /** /** Loading @@ -387,7 +392,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo * {@link NativeDaemonEvent#isClassClientError()} or * {@link NativeDaemonEvent#isClassClientError()} or * {@link NativeDaemonEvent#isClassServerError()}. * {@link NativeDaemonEvent#isClassServerError()}. */ */ public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args) public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args) throws NativeDaemonConnectorException { throws NativeDaemonConnectorException { final long startTime = SystemClock.elapsedRealtime(); final long startTime = SystemClock.elapsedRealtime(); Loading Loading @@ -418,7 +423,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo NativeDaemonEvent event = null; NativeDaemonEvent event = null; do { do { event = mResponseQueue.remove(sequenceNumber, timeout, logCmd); event = mResponseQueue.remove(sequenceNumber, timeoutMs, logCmd); if (event == null) { if (event == null) { loge("timed-out waiting for response to " + logCmd); loge("timed-out waiting for response to " + logCmd); throw new NativeDaemonTimeoutException(logCmd, event); throw new NativeDaemonTimeoutException(logCmd, event); Loading Loading @@ -606,7 +611,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo // note that the timeout does not count time in deep sleep. If you don't want // note that the timeout does not count time in deep sleep. If you don't want // the device to sleep, hold a wakelock // the device to sleep, hold a wakelock public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String logCmd) { public NativeDaemonEvent remove(int cmdNum, long timeoutMs, String logCmd) { PendingCmd found = null; PendingCmd found = null; synchronized (mPendingCmds) { synchronized (mPendingCmds) { for (PendingCmd pendingCmd : mPendingCmds) { for (PendingCmd pendingCmd : mPendingCmds) { Loading Loading
core/java/android/os/storage/VolumeInfo.java +15 −10 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.res.Resources; import android.content.res.Resources; import android.mtp.MtpStorage; import android.net.Uri; import android.net.Uri; import android.os.Environment; import android.os.Environment; import android.os.Parcel; import android.os.Parcel; Loading Loading @@ -300,6 +299,8 @@ public class VolumeInfo implements Parcelable { } } public StorageVolume buildStorageVolume(Context context, int userId) { public StorageVolume buildStorageVolume(Context context, int userId) { final StorageManager storage = context.getSystemService(StorageManager.class); final boolean removable; final boolean removable; final boolean emulated; final boolean emulated; final boolean allowMassStorage = false; final boolean allowMassStorage = false; Loading @@ -310,14 +311,7 @@ public class VolumeInfo implements Parcelable { userPath = new File("/dev/null"); userPath = new File("/dev/null"); } } String description = getDescription(); String description = null; if (description == null) { description = getFsUuid(); } if (description == null) { description = context.getString(android.R.string.unknownName); } long mtpReserveSize = 0; long mtpReserveSize = 0; long maxFileSize = 0; long maxFileSize = 0; int mtpStorageId = StorageVolume.STORAGE_ID_INVALID; int mtpStorageId = StorageVolume.STORAGE_ID_INVALID; Loading @@ -325,11 +319,16 @@ public class VolumeInfo implements Parcelable { if (type == TYPE_EMULATED) { if (type == TYPE_EMULATED) { emulated = true; emulated = true; final VolumeInfo privateVol = storage.findPrivateForEmulated(this); if (privateVol != null) { description = storage.getBestVolumeDescription(privateVol); } if (isPrimary()) { if (isPrimary()) { mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; } } mtpReserveSize = StorageManager.from(context).getStorageLowBytes(userPath); mtpReserveSize = storage.getStorageLowBytes(userPath); if (ID_EMULATED_INTERNAL.equals(id)) { if (ID_EMULATED_INTERNAL.equals(id)) { removable = false; removable = false; Loading @@ -341,6 +340,8 @@ public class VolumeInfo implements Parcelable { emulated = false; emulated = false; removable = true; removable = true; description = storage.getBestVolumeDescription(this); if (isPrimary()) { if (isPrimary()) { mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; mtpStorageId = StorageVolume.STORAGE_ID_PRIMARY; } else { } else { Loading @@ -357,6 +358,10 @@ public class VolumeInfo implements Parcelable { throw new IllegalStateException("Unexpected volume type " + type); throw new IllegalStateException("Unexpected volume type " + type); } } if (description == null) { description = context.getString(android.R.string.unknownName); } return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable, return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable, emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId), emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId), fsUuid, envState); fsUuid, envState); Loading
services/core/java/com/android/server/MountService.java +26 −4 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.Manifest; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManagerNative; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.IActivityManager; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; Loading @@ -39,10 +40,10 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.ServiceConnection; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.ObbInfo; import android.content.res.ObbInfo; import android.mtp.MtpStorage; import android.net.Uri; import android.net.Uri; import android.os.Binder; import android.os.Binder; import android.os.DropBoxManager; import android.os.DropBoxManager; Loading @@ -53,7 +54,6 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.os.IBinder; import android.os.IBinder; import android.os.Looper; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; import android.os.Process; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteCallbackList; Loading @@ -73,6 +73,7 @@ import android.os.storage.StorageResultCode; import android.os.storage.StorageVolume; import android.os.storage.StorageVolume; import android.os.storage.VolumeInfo; import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; import android.os.storage.VolumeRecord; import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.DateUtils; Loading Loading @@ -176,7 +177,6 @@ class MountService extends IMountService.Stub } } } } private static final boolean LOCAL_LOGD = false; private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_OBB = false; private static final boolean DEBUG_OBB = false; Loading Loading @@ -723,10 +723,30 @@ class MountService extends IMountService.Stub MountServiceIdler.scheduleIdlePass(mContext); MountServiceIdler.scheduleIdlePass(mContext); } } /** * MediaProvider has a ton of code that makes assumptions about storage * paths never changing, so we outright kill them to pick up new state. */ @Deprecated private void killMediaProvider() { final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY, 0, UserHandle.USER_OWNER); if (provider != null) { final IActivityManager am = ActivityManagerNative.getDefault(); try { am.killApplicationWithAppId(provider.applicationInfo.packageName, UserHandle.getAppId(provider.applicationInfo.uid), "vold reset"); } catch (RemoteException e) { } } } private void resetIfReadyAndConnectedLocked() { private void resetIfReadyAndConnectedLocked() { Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady + ", mDaemonConnected=" + mDaemonConnected); + ", mDaemonConnected=" + mDaemonConnected); if (mSystemReady && mDaemonConnected) { if (mSystemReady && mDaemonConnected) { killMediaProvider(); mDisks.clear(); mDisks.clear(); mVolumes.clear(); mVolumes.clear(); Loading Loading @@ -1606,7 +1626,9 @@ class MountService extends IMountService.Stub waitForReady(); waitForReady(); try { try { final NativeDaemonEvent res = mConnector.execute("volume", "benchmark", volId); // TODO: make benchmark async so we don't block other commands final NativeDaemonEvent res = mConnector.execute(3 * DateUtils.MINUTE_IN_MILLIS, "volume", "benchmark", volId); return Long.parseLong(res.getMessage()); return Long.parseLong(res.getMessage()); } catch (NativeDaemonTimeoutException e) { } catch (NativeDaemonTimeoutException e) { return Long.MAX_VALUE; return Long.MAX_VALUE; Loading
services/core/java/com/android/server/NativeDaemonConnector.java +11 −6 Original line number Original line Diff line number Diff line Loading @@ -69,7 +69,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo private AtomicInteger mSequenceNumber; private AtomicInteger mSequenceNumber; private static final int DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */ private static final long DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */ private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */ private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */ /** Lock held whenever communicating with native daemon. */ /** Lock held whenever communicating with native daemon. */ Loading Loading @@ -337,7 +337,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ */ public NativeDaemonEvent execute(String cmd, Object... args) public NativeDaemonEvent execute(String cmd, Object... args) throws NativeDaemonConnectorException { throws NativeDaemonConnectorException { final NativeDaemonEvent[] events = executeForList(cmd, args); return execute(DEFAULT_TIMEOUT, cmd, args); } public NativeDaemonEvent execute(long timeoutMs, String cmd, Object... args) throws NativeDaemonConnectorException { final NativeDaemonEvent[] events = executeForList(timeoutMs, cmd, args); if (events.length != 1) { if (events.length != 1) { throw new NativeDaemonConnectorException( throw new NativeDaemonConnectorException( "Expected exactly one response, but received " + events.length); "Expected exactly one response, but received " + events.length); Loading Loading @@ -372,7 +377,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ */ public NativeDaemonEvent[] executeForList(String cmd, Object... args) public NativeDaemonEvent[] executeForList(String cmd, Object... args) throws NativeDaemonConnectorException { throws NativeDaemonConnectorException { return execute(DEFAULT_TIMEOUT, cmd, args); return executeForList(DEFAULT_TIMEOUT, cmd, args); } } /** /** Loading @@ -387,7 +392,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo * {@link NativeDaemonEvent#isClassClientError()} or * {@link NativeDaemonEvent#isClassClientError()} or * {@link NativeDaemonEvent#isClassServerError()}. * {@link NativeDaemonEvent#isClassServerError()}. */ */ public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args) public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args) throws NativeDaemonConnectorException { throws NativeDaemonConnectorException { final long startTime = SystemClock.elapsedRealtime(); final long startTime = SystemClock.elapsedRealtime(); Loading Loading @@ -418,7 +423,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo NativeDaemonEvent event = null; NativeDaemonEvent event = null; do { do { event = mResponseQueue.remove(sequenceNumber, timeout, logCmd); event = mResponseQueue.remove(sequenceNumber, timeoutMs, logCmd); if (event == null) { if (event == null) { loge("timed-out waiting for response to " + logCmd); loge("timed-out waiting for response to " + logCmd); throw new NativeDaemonTimeoutException(logCmd, event); throw new NativeDaemonTimeoutException(logCmd, event); Loading Loading @@ -606,7 +611,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo // note that the timeout does not count time in deep sleep. If you don't want // note that the timeout does not count time in deep sleep. If you don't want // the device to sleep, hold a wakelock // the device to sleep, hold a wakelock public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String logCmd) { public NativeDaemonEvent remove(int cmdNum, long timeoutMs, String logCmd) { PendingCmd found = null; PendingCmd found = null; synchronized (mPendingCmds) { synchronized (mPendingCmds) { for (PendingCmd pendingCmd : mPendingCmds) { for (PendingCmd pendingCmd : mPendingCmds) { Loading