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

Commit 666b998b authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

am 364fc14f: Merge "Detect wedged ContentProviders, treat as ANR." into klp-dev

* commit '364fc14f':
  Detect wedged ContentProviders, treat as ANR.
parents 990615e3 364fc14f
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -758,6 +758,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            appNotRespondingViaProvider(b);
            reply.writeNoException();
            return true;
        }

        case REMOVE_CONTENT_PROVIDER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
@@ -2891,6 +2899,7 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
        return res;
    }

    public void unstableProviderDied(IBinder connection) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
@@ -2902,6 +2911,18 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }

    @Override
    public void appNotRespondingViaProvider(IBinder connection) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(connection);
        mRemote.transact(APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

    public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
+13 −0
Original line number Diff line number Diff line
@@ -4653,6 +4653,19 @@ public final class ActivityThread {
        }
    }

    final void appNotRespondingViaProvider(IBinder provider) {
        synchronized (mProviderMap) {
            ProviderRefCount prc = mProviderRefCountMap.get(provider);
            if (prc != null) {
                try {
                    ActivityManagerNative.getDefault()
                            .appNotRespondingViaProvider(prc.holder.connection);
                } catch (RemoteException e) {
                }
            }
        }
    }

    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
            ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
        final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);
+5 −0
Original line number Diff line number Diff line
@@ -2200,5 +2200,10 @@ class ContextImpl extends Context {
        public void unstableProviderDied(IContentProvider icp) {
            mMainThread.handleUnstableProviderDied(icp.asBinder(), true);
        }

        @Override
        public void appNotRespondingViaProvider(IContentProvider icp) {
            mMainThread.appNotRespondingViaProvider(icp.asBinder());
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ public interface IActivityManager extends IInterface {
    public boolean refContentProvider(IBinder connection, int stableDelta, int unstableDelta)
            throws RemoteException;
    public void unstableProviderDied(IBinder connection) throws RemoteException;
    public void appNotRespondingViaProvider(IBinder connection) throws RemoteException;
    public PendingIntent getRunningServiceControlPanel(ComponentName service)
            throws RemoteException;
    public ComponentName startService(IApplicationThread caller, Intent service,
@@ -691,4 +692,5 @@ public interface IActivityManager extends IInterface {
    int TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+179;
    int RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+180;
    int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181;
    int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
}
+133 −43
Original line number Diff line number Diff line
@@ -16,15 +16,20 @@

package android.content;

import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.ICancellationSignal;
import android.os.RemoteException;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.content.res.AssetFileDescriptor;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import dalvik.system.CloseGuard;

@@ -45,26 +50,64 @@ import java.util.ArrayList;
 * until you are finished with the data they have returned.
 */
public class ContentProviderClient {
    private final IContentProvider mContentProvider;
    private static final String TAG = "ContentProviderClient";

    @GuardedBy("ContentProviderClient.class")
    private static Handler sAnrHandler;

    private final ContentResolver mContentResolver;
    private final IContentProvider mContentProvider;
    private final String mPackageName;
    private final boolean mStable;
    private boolean mReleased;

    private final CloseGuard mGuard = CloseGuard.get();

    /**
     * @hide
     */
    ContentProviderClient(ContentResolver contentResolver,
            IContentProvider contentProvider, boolean stable) {
        mContentProvider = contentProvider;
    private long mAnrTimeout;
    private NotRespondingRunnable mAnrRunnable;

    private boolean mReleased;

    /** {@hide} */
    ContentProviderClient(
            ContentResolver contentResolver, IContentProvider contentProvider, boolean stable) {
        mContentResolver = contentResolver;
        mContentProvider = contentProvider;
        mPackageName = contentResolver.mPackageName;
        mStable = stable;

        mGuard.open("release");
    }

    /** {@hide} */
    public void setDetectNotResponding(long timeoutMillis) {
        synchronized (ContentProviderClient.class) {
            mAnrTimeout = timeoutMillis;

            if (timeoutMillis > 0) {
                if (mAnrRunnable == null) {
                    mAnrRunnable = new NotRespondingRunnable();
                }
                if (sAnrHandler == null) {
                    sAnrHandler = new Handler(Looper.getMainLooper(), null, true /* async */);
                }
            } else {
                mAnrRunnable = null;
            }
        }
    }

    private void beforeRemote() {
        if (mAnrRunnable != null) {
            sAnrHandler.postDelayed(mAnrRunnable, mAnrTimeout);
        }
    }

    private void afterRemote() {
        if (mAnrRunnable != null) {
            sAnrHandler.removeCallbacks(mAnrRunnable);
        }
    }

    /** See {@link ContentProvider#query ContentProvider.query} */
    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) throws RemoteException {
@@ -72,16 +115,16 @@ public class ContentProviderClient {
    }

    /** See {@link ContentProvider#query ContentProvider.query} */
    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)
                    throws RemoteException {
    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
            String sortOrder, CancellationSignal cancellationSignal) throws RemoteException {
        beforeRemote();
        try {
            ICancellationSignal remoteCancellationSignal = null;
            if (cancellationSignal != null) {
                cancellationSignal.throwIfCanceled();
                remoteCancellationSignal = mContentProvider.createCancellationSignal();
                cancellationSignal.setRemote(remoteCancellationSignal);
            }
        try {
            return mContentProvider.query(mPackageName, url, projection, selection, selectionArgs,
                    sortOrder, remoteCancellationSignal);
        } catch (DeadObjectException e) {
@@ -89,11 +132,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#getType ContentProvider.getType} */
    public String getType(Uri url) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.getType(url);
        } catch (DeadObjectException e) {
@@ -101,11 +147,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
    public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.getStreamTypes(url, mimeTypeFilter);
        } catch (DeadObjectException e) {
@@ -113,11 +162,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#canonicalize} */
    public final Uri canonicalize(Uri url) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.canonicalize(mPackageName, url);
        } catch (DeadObjectException e) {
@@ -125,11 +177,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#uncanonicalize} */
    public final Uri uncanonicalize(Uri url) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.uncanonicalize(mPackageName, url);
        } catch (DeadObjectException e) {
@@ -137,12 +192,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#insert ContentProvider.insert} */
    public Uri insert(Uri url, ContentValues initialValues)
            throws RemoteException {
    public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.insert(mPackageName, url, initialValues);
        } catch (DeadObjectException e) {
@@ -150,11 +207,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
    public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.bulkInsert(mPackageName, url, initialValues);
        } catch (DeadObjectException e) {
@@ -162,12 +222,15 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#delete ContentProvider.delete} */
    public int delete(Uri url, String selection, String[] selectionArgs)
            throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.delete(mPackageName, url, selection, selectionArgs);
        } catch (DeadObjectException e) {
@@ -175,12 +238,15 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#update ContentProvider.update} */
    public int update(Uri url, ContentValues values, String selection,
            String[] selectionArgs) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.update(mPackageName, url, values, selection, selectionArgs);
        } catch (DeadObjectException e) {
@@ -188,6 +254,8 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

@@ -212,19 +280,22 @@ public class ContentProviderClient {
     */
    public ParcelFileDescriptor openFile(Uri url, String mode, CancellationSignal signal)
            throws RemoteException, FileNotFoundException {
        beforeRemote();
        try {
            ICancellationSignal remoteSignal = null;
            if (signal != null) {
                signal.throwIfCanceled();
                remoteSignal = mContentProvider.createCancellationSignal();
                signal.setRemote(remoteSignal);
            }
        try {
            return mContentProvider.openFile(mPackageName, url, mode, remoteSignal);
        } catch (DeadObjectException e) {
            if (!mStable) {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

@@ -249,19 +320,22 @@ public class ContentProviderClient {
     */
    public AssetFileDescriptor openAssetFile(Uri url, String mode, CancellationSignal signal)
            throws RemoteException, FileNotFoundException {
        beforeRemote();
        try {
            ICancellationSignal remoteSignal = null;
            if (signal != null) {
                signal.throwIfCanceled();
                remoteSignal = mContentProvider.createCancellationSignal();
                signal.setRemote(remoteSignal);
            }
        try {
            return mContentProvider.openAssetFile(mPackageName, url, mode, remoteSignal);
        } catch (DeadObjectException e) {
            if (!mStable) {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

@@ -275,13 +349,14 @@ public class ContentProviderClient {
    public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
            String mimeType, Bundle opts, CancellationSignal signal)
            throws RemoteException, FileNotFoundException {
        beforeRemote();
        try {
            ICancellationSignal remoteSignal = null;
            if (signal != null) {
                signal.throwIfCanceled();
                remoteSignal = mContentProvider.createCancellationSignal();
                signal.setRemote(remoteSignal);
            }
        try {
            return mContentProvider.openTypedAssetFile(
                    mPackageName, uri, mimeType, opts, remoteSignal);
        } catch (DeadObjectException e) {
@@ -289,12 +364,15 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
            throws RemoteException, OperationApplicationException {
        beforeRemote();
        try {
            return mContentProvider.applyBatch(mPackageName, operations);
        } catch (DeadObjectException e) {
@@ -302,12 +380,14 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

    /** See {@link ContentProvider#call(String, String, Bundle)} */
    public Bundle call(String method, String arg, Bundle extras)
            throws RemoteException {
    public Bundle call(String method, String arg, Bundle extras) throws RemoteException {
        beforeRemote();
        try {
            return mContentProvider.call(mPackageName, method, arg, extras);
        } catch (DeadObjectException e) {
@@ -315,6 +395,8 @@ public class ContentProviderClient {
                mContentResolver.unstableProviderDied(mContentProvider);
            }
            throw e;
        } finally {
            afterRemote();
        }
    }

@@ -359,7 +441,7 @@ public class ContentProviderClient {
    }

    /** {@hide} */
    public static void closeQuietly(ContentProviderClient client) {
    public static void releaseQuietly(ContentProviderClient client) {
        if (client != null) {
            try {
                client.release();
@@ -367,4 +449,12 @@ public class ContentProviderClient {
            }
        }
    }

    private class NotRespondingRunnable implements Runnable {
        @Override
        public void run() {
            Log.w(TAG, "Detected provider not responding: " + mContentProvider);
            mContentResolver.appNotRespondingViaProvider(mContentProvider);
        }
    }
}
Loading