Fix a race condition in acquiring content provider

Client could be stuck at the lock before toggling the waiting flag,
meanwhile the publishing of the provider could been holding the lock
and check that flag, thus result in not notifying the client.

Now setting the flag with the global lock held.

Bug: 186228106
Bug: 190034355
Test: atest CtsContentTestCases:android.content.cts
Test: atest FrameworksCoreTests:android.content
Change-Id: I7c7a3326c302cc01e52a9a5d78ea9d089be0dcae
This commit is contained in:
Jing Ji
2021-06-03 12:29:31 -07:00
parent 327a271617
commit 42e44711fa

View File

@@ -501,37 +501,38 @@ public class ContentProviderHelper {
mService.grantImplicitAccess(userId, null, callingUid,
UserHandle.getAppId(cpi.applicationInfo.uid));
}
if (caller != null) {
// The client will be waiting, and we'll notify it when the provider is ready.
synchronized (cpr) {
if (cpr.provider == null) {
if (cpr.launchingApp == null) {
Slog.w(TAG, "Unable to launch app "
+ cpi.applicationInfo.packageName + "/"
+ cpi.applicationInfo.uid + " for provider "
+ name + ": launching app became null");
EventLogTags.writeAmProviderLostProcess(
UserHandle.getUserId(cpi.applicationInfo.uid),
cpi.applicationInfo.packageName,
cpi.applicationInfo.uid, name);
return null;
}
if (caller != null) {
// The client will be waiting, and we'll notify it when the provider is ready.
synchronized (cpr) {
if (cpr.provider == null) {
if (cpr.launchingApp == null) {
Slog.w(TAG, "Unable to launch app "
+ cpi.applicationInfo.packageName + "/"
+ cpi.applicationInfo.uid + " for provider "
+ name + ": launching app became null");
EventLogTags.writeAmProviderLostProcess(
UserHandle.getUserId(cpi.applicationInfo.uid),
cpi.applicationInfo.packageName,
cpi.applicationInfo.uid, name);
return null;
}
if (conn != null) {
conn.waiting = true;
if (conn != null) {
conn.waiting = true;
}
Message msg = mService.mHandler.obtainMessage(
ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG);
msg.obj = cpr;
mService.mHandler.sendMessageDelayed(msg,
ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
}
Message msg = mService.mHandler.obtainMessage(
ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG);
msg.obj = cpr;
mService.mHandler.sendMessageDelayed(msg,
ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
}
// Return a holder instance even if we are waiting for the publishing of the
// provider, client will check for the holder.provider to see if it needs to wait
// for it.
return cpr.newHolder(conn, false);
}
// Return a holder instance even if we are waiting for the publishing of the provider,
// client will check for the holder.provider to see if it needs to wait for it.
return cpr.newHolder(conn, false);
}
// Because of the provider's external client (i.e., SHELL), we'll have to wait right here.