Merge "Avoid wm<->am deadlock when checking uri permission" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
02c67b119e
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user