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

Commit 14cbe521 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Kill MediaProvider during drastic changes.

Sadly MediaProvider makes a ton of assumptions about storage paths
not changing.  To ensure that it picks up radical storage changes,
kill it and let it restart to pick up new paths.

Also give ourselves a longer timeout when benchmarking.

Bug: 20275423
Change-Id: I9971c4667dabdc685cb23528443f085f152c461d
parent a83bf196
Loading
Loading
Loading
Loading
+26 −4
Original line number Original line Diff line number Diff line
@@ -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;
+11 −6
Original line number Original line Diff line number Diff line
@@ -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) {