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

Commit 73e239bd authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Clean-up state if we have an exception when acquiring provider

We can get a number of exceptions (e.g. SecurityException) when
a process is acquiring a provider. We need to clean-up correctly
so that other threads that try to acquire the provider the progress.

Bug: 20122809
Change-Id: Icac1d391df7e8c24198be89035b1c5a23da834cf
parent 1d3c77a2
Loading
Loading
Loading
Loading
+42 −24
Original line number Diff line number Diff line
@@ -261,6 +261,8 @@ public final class ActivityThread {
        IActivityManager.ContentProviderHolder holder;
        boolean acquiring = true;
        int requests = 1;
        // Set if there was a runtime exception when trying to acquire the provider.
        RuntimeException runtimeException = null;
    }

    // The lock of mProviderMap protects the following variables.
@@ -4670,6 +4672,7 @@ public final class ActivityThread {
        }

        IActivityManager.ContentProviderHolder holder = null;
        try {
            if (first) {
                // Multiple threads may try to acquire the same provider at the same time.
                // When this happens, we only let the first one really gets provider.
@@ -4677,16 +4680,8 @@ public final class ActivityThread {
                // Note that we cannot hold the lock while acquiring and installing the
                // provider since it might take a long time to run and it could also potentially
                // be re-entrant in the case where the provider is in the same process.
            try {
                holder = ActivityManagerNative.getDefault().getContentProvider(
                        getApplicationThread(), auth, userId, stable);
            } catch (RemoteException ex) {
            }
            synchronized (r) {
                r.holder = holder;
                r.acquiring = false;
                r.notifyAll();
            }
            } else {
                synchronized (r) {
                    while (r.acquiring) {
@@ -4698,11 +4693,34 @@ public final class ActivityThread {
                    holder = r.holder;
                }
            }
        } catch (RemoteException ex) {
        } catch (RuntimeException e) {
            synchronized (r) {
                r.runtimeException = e;
            }
        } finally {
            if (first) {
                synchronized (r) {
                    r.holder = holder;
                    r.acquiring = false;
                    r.notifyAll();
                }
            }

            synchronized (mAcquiringProviderMap) {
                if (--r.requests == 0) {
                    mAcquiringProviderMap.remove(key);
                }
            }

            if (r.runtimeException != null) {
                // Was set when the first thread tried to acquire the provider,
                // but we should make sure it is thrown for all threads trying to
                // acquire the provider.
                throw r.runtimeException;
            }
        }

        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + auth);
            return null;