Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 123fc306 authored by Gabriele M's avatar Gabriele M
Browse files

AppOps: Prevent deadlock when making note of applications

If noteOperation() is called with ActivityManagerService locked,
AppOpsService won't be able to show the PermissionDialog, causing
noteOperation() to wait indefinitely. Keep a reference to the
current ActivityManagerService instance so that we can check
whether showing the PermissionDialog is safe or not.

Even though there's currently no code path that causes startOperation()
to be called with ActivityManagerService locked, add the same check
there to prevent the same from happening in future.

BUGBASH-17

Change-Id: I118aac6ddf91774a038d73047162cfdb8395e58d
parent 013b62c4
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.am.ActivityManagerService;
import com.android.server.PermissionDialogReqQueue.PermissionDialogReq;

import libcore.util.EmptyArray;
@@ -104,6 +105,7 @@ public class AppOpsService extends IAppOpsService.Stub {
    final boolean mStrictEnable;
    AppOpsPolicy mPolicy;
    private PowerManager mPowerManager;
    private final ActivityManagerService mActivityManagerService;

    private static final int[] PRIVACY_GUARD_OP_STATES = new int[] {
        AppOpsManager.OP_COARSE_LOCATION,
@@ -286,11 +288,12 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    public AppOpsService(File storagePath, Handler handler) {
    public AppOpsService(File storagePath, Handler handler, ActivityManagerService service) {
        mFile = new AtomicFile(storagePath);
        mHandler = handler;
        mLooper = Looper.myLooper();
        mStrictEnable = AppOpsManager.isStrictEnable();
        mActivityManagerService = service;
        readState();
    }

@@ -1159,7 +1162,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                    op.ignoredCount++;
                    return switchOp.mode;
                } else if (switchOp.mode == AppOpsManager.MODE_ASK) {
                    if (Looper.myLooper() == mLooper) {
                    if (Looper.myLooper() == mLooper || Thread.holdsLock(mActivityManagerService)) {
                        Log.e(TAG,
                                "noteOperation: This method will deadlock if called from the main thread. (Code: "
                                        + code
@@ -1295,7 +1298,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                broadcastOpIfNeeded(code);
                return AppOpsManager.MODE_ALLOWED;
            } else {
                if (Looper.myLooper() == mLooper) {
                if (Looper.myLooper() == mLooper || Thread.holdsLock(mActivityManagerService)) {
                    Log.e(TAG,
                            "startOperation: This method will deadlock if called from the main thread. (Code: "
                                    + code
+1 −1
Original line number Diff line number Diff line
@@ -2843,7 +2843,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
        mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
        mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler, this);
        mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null,
                new IAppOpsCallback.Stub() {
                    @Override public void opChanged(int op, int uid, String packageName) {