Loading core/java/android/app/ActivityThread.java +49 −11 Original line number Diff line number Diff line Loading @@ -424,9 +424,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 Loading @@ -440,7 +445,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; } } Loading @@ -461,9 +470,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>>(); Loading Loading @@ -1756,6 +1764,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( Loading Loading @@ -6807,13 +6825,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)) { Loading @@ -6831,13 +6869,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; } Loading core/java/android/app/ContentProviderHolder.java +8 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -81,5 +87,6 @@ public class ContentProviderHolder implements Parcelable { source.readStrongBinder()); connection = source.readStrongBinder(); noReleaseNeeded = source.readInt() != 0; mLocal = source.readInt() != 0; } } core/java/android/app/IApplicationThread.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.app; import android.app.ContentProviderHolder; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; Loading Loading @@ -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); } core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +6 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.app.servertransaction.TestUtils.resultInfoList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.app.ContentProviderHolder; import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; Loading Loading @@ -665,5 +666,10 @@ public class TransactionParcelTests { public void performDirectAction(IBinder activityToken, String actionId, Bundle arguments, RemoteCallback cancellationCallback, RemoteCallback resultCallback) { } @Override public void notifyContentProviderPublishStatus(ContentProviderHolder holder, String auth, int userId, boolean published) { } } } services/core/java/com/android/server/am/ActivityManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -1581,6 +1581,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70; static final int KILL_APP_ZYGOTE_MSG = 71; static final int BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG = 72; static final int WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG = 73; static final int FIRST_BROADCAST_QUEUE_MSG = 200; Loading Loading @@ -1917,6 +1918,11 @@ public class ActivityManagerService extends IActivityManager.Stub case BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG: { handleBinderHeavyHitterAutoSamplerTimeOut(); } break; case WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG: { synchronized (ActivityManagerService.this) { ((ContentProviderRecord) msg.obj).onProviderPublishStatusLocked(false); } } break; } } } Loading Loading
core/java/android/app/ActivityThread.java +49 −11 Original line number Diff line number Diff line Loading @@ -424,9 +424,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 Loading @@ -440,7 +445,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; } } Loading @@ -461,9 +470,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>>(); Loading Loading @@ -1756,6 +1764,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( Loading Loading @@ -6807,13 +6825,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)) { Loading @@ -6831,13 +6869,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; } Loading
core/java/android/app/ContentProviderHolder.java +8 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -81,5 +87,6 @@ public class ContentProviderHolder implements Parcelable { source.readStrongBinder()); connection = source.readStrongBinder(); noReleaseNeeded = source.readInt() != 0; mLocal = source.readInt() != 0; } }
core/java/android/app/IApplicationThread.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.app; import android.app.ContentProviderHolder; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; Loading Loading @@ -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); }
core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +6 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.app.servertransaction.TestUtils.resultInfoList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.app.ContentProviderHolder; import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; Loading Loading @@ -665,5 +666,10 @@ public class TransactionParcelTests { public void performDirectAction(IBinder activityToken, String actionId, Bundle arguments, RemoteCallback cancellationCallback, RemoteCallback resultCallback) { } @Override public void notifyContentProviderPublishStatus(ContentProviderHolder holder, String auth, int userId, boolean published) { } } }
services/core/java/com/android/server/am/ActivityManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -1581,6 +1581,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70; static final int KILL_APP_ZYGOTE_MSG = 71; static final int BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG = 72; static final int WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG = 73; static final int FIRST_BROADCAST_QUEUE_MSG = 200; Loading Loading @@ -1917,6 +1918,11 @@ public class ActivityManagerService extends IActivityManager.Stub case BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG: { handleBinderHeavyHitterAutoSamplerTimeOut(); } break; case WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG: { synchronized (ActivityManagerService.this) { ((ContentProviderRecord) msg.obj).onProviderPublishStatusLocked(false); } } break; } } } Loading