diff options
author | Wale Ogunwale <ogunwale@google.com> | 2015-04-09 15:42:12 -0700 |
---|---|---|
committer | Wale Ogunwale <ogunwale@google.com> | 2015-04-10 09:32:26 -0700 |
commit | 73e239bdc9493d81215d5afe739b3ed095686ba2 (patch) | |
tree | 82d7b7e42f5e1ec1561e524b456a53ffb78b5c3b | |
parent | 1d3c77a21e9c8fc59200b42503d9f0effd3f1551 (diff) | |
download | frameworks_base-73e239bdc9493d81215d5afe739b3ed095686ba2.zip frameworks_base-73e239bdc9493d81215d5afe739b3ed095686ba2.tar.gz frameworks_base-73e239bdc9493d81215d5afe739b3ed095686ba2.tar.bz2 |
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
-rw-r--r-- | core/java/android/app/ActivityThread.java | 66 |
1 files changed, 42 insertions, 24 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9269f60..b063209 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -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,39 +4672,55 @@ public final class ActivityThread { } IActivityManager.ContentProviderHolder holder = null; - 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. - // Other threads just wait for its result. - // 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 { + 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. + // Other threads just wait for its result. + // 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. holder = ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable); - } catch (RemoteException ex) { + } else { + synchronized (r) { + while (r.acquiring) { + try { + r.wait(); + } catch (InterruptedException e) { + } + } + holder = r.holder; + } } + } catch (RemoteException ex) { + } catch (RuntimeException e) { synchronized (r) { - r.holder = holder; - r.acquiring = false; - r.notifyAll(); + r.runtimeException = e; } - } else { - synchronized (r) { - while (r.acquiring) { - try { - r.wait(); - } catch (InterruptedException e) { - } + } finally { + if (first) { + synchronized (r) { + r.holder = holder; + r.acquiring = false; + r.notifyAll(); } - holder = r.holder; } - } - synchronized (mAcquiringProviderMap) { - if (--r.requests == 0) { - mAcquiringProviderMap.remove(key); + + 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; |