diff options
| author | Jing Ji <jji@google.com> | 2020-08-06 18:39:30 -0700 |
|---|---|---|
| committer | Jing Ji <jji@google.com> | 2020-08-06 18:39:30 -0700 |
| commit | adda50006d1a4401d72f4df7664e8904aff5e43b (patch) | |
| tree | dafbbec0e1d2c53a563a0dcbcacfd900c1729c3f /core/java | |
| parent | 5605ab66d7cfe44a6779a113fc2914dd2be22d64 (diff) | |
Move the waiting for the publishing of content provider to client side
...except the external provider client.
Previously the waiting is within the system_server and holds a binder
thread of the system_server. Now the waiting will be in client side
and the system_server will notify the client when the provider is
ready.
Bug: 149935749
Bug: 162450085
Test: atest CtsContentTestCases:android.content.cts
Test: atest FrameworksCoreTests:android.content
Test: atest ActivityManagerPerfTests:ContentProviderPerfTest
Change-Id: I0c8ef1c397103ac38f2fb7da79e647c0b8cd63cc
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 60 | ||||
| -rw-r--r-- | core/java/android/app/ContentProviderHolder.java | 9 | ||||
| -rw-r--r-- | core/java/android/app/IApplicationThread.aidl | 3 |
3 files changed, 60 insertions, 12 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9b13d256aea6..dde0be57c6f3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -421,9 +421,14 @@ public final class ActivityThread extends ClientTransactionHandler { final String authority; final int userId; + @GuardedBy("mLock") + ContentProviderHolder mHolder; // Temp holder to be used between notifier and waiter + Object mLock; // The lock to be used to get notified when the provider is ready + public ProviderKey(String authority, int userId) { this.authority = authority; this.userId = userId; + this.mLock = new Object(); } @Override @@ -437,7 +442,11 @@ public final class ActivityThread extends ClientTransactionHandler { @Override public int hashCode() { - return ((authority != null) ? authority.hashCode() : 0) ^ userId; + return hashCode(authority, userId); + } + + public static int hashCode(final String auth, final int userIdent) { + return ((auth != null) ? auth.hashCode() : 0) ^ userIdent; } } @@ -458,9 +467,8 @@ public final class ActivityThread extends ClientTransactionHandler { // Mitigation for b/74523247: Used to serialize calls to AM.getContentProvider(). // Note we never removes items from this map but that's okay because there are only so many // users and so many authorities. - // TODO Remove it once we move CPR.wait() from AMS to the client side. - @GuardedBy("mGetProviderLocks") - final ArrayMap<ProviderKey, Object> mGetProviderLocks = new ArrayMap<>(); + @GuardedBy("mGetProviderKeys") + final SparseArray<ProviderKey> mGetProviderKeys = new SparseArray<>(); final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>(); @@ -1751,6 +1759,16 @@ public final class ActivityThread extends ClientTransactionHandler { ActivityThread.this, activityToken, actionId, arguments, cancellationSignal, resultCallback)); } + + @Override + public void notifyContentProviderPublishStatus(@NonNull ContentProviderHolder holder, + @NonNull String auth, int userId, boolean published) { + final ProviderKey key = getGetProviderKey(auth, userId); + synchronized (key.mLock) { + key.mHolder = holder; + key.mLock.notifyAll(); + } + } } private @NonNull SafeCancellationTransport createSafeCancellationTransport( @@ -6796,13 +6814,33 @@ public final class ActivityThread extends ClientTransactionHandler { // 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. ContentProviderHolder holder = null; + final ProviderKey key = getGetProviderKey(auth, userId); try { - synchronized (getGetProviderLock(auth, userId)) { + synchronized (key) { holder = ActivityManager.getService().getContentProvider( getApplicationThread(), c.getOpPackageName(), auth, userId, stable); + // If the returned holder is non-null but its provider is null and it's not + // local, we'll need to wait for the publishing of the provider. + if (holder != null && holder.provider == null && !holder.mLocal) { + synchronized (key.mLock) { + key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS); + holder = key.mHolder; + } + if (holder != null && holder.provider == null) { + // probably timed out + holder = null; + } + } } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); + } catch (InterruptedException e) { + holder = null; + } finally { + // Clear the holder from the key since the key itself is never cleared. + synchronized (key.mLock) { + key.mHolder = null; + } } if (holder == null) { if (UserManager.get(c).isUserUnlocked(userId)) { @@ -6820,13 +6858,13 @@ public final class ActivityThread extends ClientTransactionHandler { return holder.provider; } - private Object getGetProviderLock(String auth, int userId) { - final ProviderKey key = new ProviderKey(auth, userId); - synchronized (mGetProviderLocks) { - Object lock = mGetProviderLocks.get(key); + private ProviderKey getGetProviderKey(String auth, int userId) { + final int key = ProviderKey.hashCode(auth, userId); + synchronized (mGetProviderKeys) { + ProviderKey lock = mGetProviderKeys.get(key); if (lock == null) { - lock = key; - mGetProviderLocks.put(key, lock); + lock = new ProviderKey(auth, userId); + mGetProviderKeys.put(key, lock); } return lock; } diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java index 3d745831ce1c..e330a30de7b0 100644 --- a/core/java/android/app/ContentProviderHolder.java +++ b/core/java/android/app/ContentProviderHolder.java @@ -39,6 +39,11 @@ public class ContentProviderHolder implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public boolean noReleaseNeeded; + /** + * Whether the provider here is a local provider or not. + */ + public boolean mLocal; + @UnsupportedAppUsage public ContentProviderHolder(ProviderInfo _info) { info = _info; @@ -59,6 +64,7 @@ public class ContentProviderHolder implements Parcelable { } dest.writeStrongBinder(connection); dest.writeInt(noReleaseNeeded ? 1 : 0); + dest.writeInt(mLocal ? 1 : 0); } public static final @android.annotation.NonNull Parcelable.Creator<ContentProviderHolder> CREATOR @@ -81,5 +87,6 @@ public class ContentProviderHolder implements Parcelable { source.readStrongBinder()); connection = source.readStrongBinder(); noReleaseNeeded = source.readInt() != 0; + mLocal = source.readInt() != 0; } -}
\ No newline at end of file +} diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 6e9157e2a8c3..e5d4a766a89d 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -16,6 +16,7 @@ package android.app; +import android.app.ContentProviderHolder; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; @@ -147,4 +148,6 @@ oneway interface IApplicationThread { void performDirectAction(IBinder activityToken, String actionId, in Bundle arguments, in RemoteCallback cancellationCallback, in RemoteCallback resultCallback); + void notifyContentProviderPublishStatus(in ContentProviderHolder holder, String auth, + int userId, boolean published); } |
