* commit '093be69c4168988938d276d31625515f641a170b': Kill MediaProvider during drastic changes. Use best volume description for MTP.
This commit is contained in:
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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 {
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -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();
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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. */
|
||||||
@@ -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);
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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();
|
||||||
|
|
||||||
@@ -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);
|
||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user