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

Commit cd9f253c authored by Hai Zhang's avatar Hai Zhang
Browse files

Fix deadlock in getOneTimePermissionUserManager().

The OneTimePermissionUserManager constructor may acquire the package
manager lock inside, so we cannot call it while holding our permission
lock.

Fixes: 173097873
Test: presubmit
Change-Id: I7178bc0a642d6c42dfc9edf855dce72deaa1e699
parent a5a96475
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -3369,16 +3369,28 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                SystemConfig.getInstance().getSplitPermissions());
    }

    @NonNull
    private OneTimePermissionUserManager getOneTimePermissionUserManager(@UserIdInt int userId) {
        OneTimePermissionUserManager oneTimePermissionUserManager;
        synchronized (mLock) {
            oneTimePermissionUserManager =
                    mOneTimePermissionUserManagers.get(userId);
            oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId);
            if (oneTimePermissionUserManager != null) {
                return oneTimePermissionUserManager;
            }
        }
        // We cannot create a new instance of OneTimePermissionUserManager while holding our own
        // lock, which may lead to a deadlock with the package manager lock. So we do it in a
        // retry-like way, and just discard the newly created instance if someone else managed to be
        // a little bit faster than us when we dropped our own lock.
        final OneTimePermissionUserManager newOneTimePermissionUserManager =
                new OneTimePermissionUserManager(mContext.createContextAsUser(UserHandle.of(userId),
                        /*flags*/ 0));
        synchronized (mLock) {
            oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId);
            if (oneTimePermissionUserManager != null) {
                return oneTimePermissionUserManager;
            }
            oneTimePermissionUserManager = new OneTimePermissionUserManager(
                    mContext.createContextAsUser(UserHandle.of(userId), /*flags*/ 0));
            oneTimePermissionUserManager = newOneTimePermissionUserManager;
            mOneTimePermissionUserManagers.put(userId, oneTimePermissionUserManager);
        }
        oneTimePermissionUserManager.registerUninstallListener();