Merge "Avoid wm<->am deadlock when checking uri permission" into rvc-dev am: 02c67b119e

Change-Id: Ie768349ab4ad5c67f471642151f5f66101e4ebea
This commit is contained in:
Wale Ogunwale
2020-05-19 15:20:18 +00:00
committed by Automerger Merge Worker

View File

@@ -337,6 +337,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.TriFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AlarmManagerInternal; import com.android.server.AlarmManagerInternal;
import com.android.server.AttributeCache; import com.android.server.AttributeCache;
import com.android.server.DeviceIdleInternal; import com.android.server.DeviceIdleInternal;
@@ -18831,28 +18832,39 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override @Override
public int checkContentProviderUriPermission(Uri uri, int userId, public int checkContentProviderUriPermission(Uri uri, int userId,
int callingUid, int modeFlags) { int callingUid, int modeFlags) {
// We can find ourselves needing to check Uri permissions while final Object wmLock = mActivityTaskManager.getGlobalLock();
// already holding the WM lock, which means reaching back here for if (Thread.currentThread().holdsLock(wmLock)
// the AM lock would cause an inversion. The WM team has requested && !Thread.currentThread().holdsLock(ActivityManagerService.this)) {
// that we use the strategy below instead of shifting where Uri // We can find ourselves needing to check Uri permissions while already holding the
// grants are calculated. // WM lock, which means reaching back here for the AM lock would cause an inversion.
// The WM team has requested that we use the strategy below instead of shifting
// where Uri grants are calculated.
synchronized (wmLock) {
final int[] result = new int[1];
final Message msg = PooledLambda.obtainMessage(
LocalService::checkContentProviderUriPermission,
this, uri, userId, callingUid, modeFlags, wmLock, result);
mHandler.sendMessage(msg);
try {
wmLock.wait();
} catch (InterruptedException ignore) {
// Since we could also arrive here while holding the AM lock, we }
// can't always delegate the call through the handler, and we need return result[0];
// to delicately dance between the deadlocks. }
if (Thread.currentThread().holdsLock(ActivityManagerService.this)) { } else {
return ActivityManagerService.this.checkContentProviderUriPermission(uri, return ActivityManagerService.this.checkContentProviderUriPermission(uri,
userId, callingUid, modeFlags); userId, callingUid, modeFlags);
} else { }
final CompletableFuture<Integer> res = new CompletableFuture<>(); }
mHandler.post(() -> {
res.complete(ActivityManagerService.this.checkContentProviderUriPermission(uri, void checkContentProviderUriPermission(
userId, callingUid, modeFlags)); Uri uri, int userId, int callingUid, int modeFlags, Object wmLock, int[] result) {
}); synchronized (ActivityManagerService.this) {
try { synchronized (wmLock) {
return res.get(); result[0] = ActivityManagerService.this.checkContentProviderUriPermission(
} catch (InterruptedException | ExecutionException e) { uri, userId, callingUid, modeFlags);
throw new RuntimeException(e); wmLock.notify();
} }
} }
} }