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

Commit b2f366cb authored by Todd Kennedy's avatar Todd Kennedy
Browse files

Avoid taking a lock when we shouldn't

Pull out code that shouldn't be executed with the mPackages
lock held. Also changed the names of some methods [added a
'NotLocked' suffix] and added a WTF to be ensure that the
mPackages lock is not held when those methods are called.

Fixes: 129500384
Test: atest
Change-Id: I6853d4e6db92b962aa79e22470845296c2a77e58
parent 89082d70
Loading
Loading
Loading
Loading
+157 −109
Original line number Diff line number Diff line
@@ -1990,7 +1990,6 @@ public class PackageManagerService extends IPackageManager.Stub
            // Work that needs to happen on first install within each user
            if (firstUserIds != null && firstUserIds.length > 0) {
                synchronized (mPackages) {
                for (int userId : firstUserIds) {
                    // If this app is a browser and it's newly-installed for some
                    // users, clear any default-browser state in those users. The
@@ -1999,12 +1998,14 @@ public class PackageManagerService extends IPackageManager.Stub
                    if (packageIsBrowser(packageName, userId)) {
                        // If this browser is restored from user's backup, do not clear
                        // default-browser state for this user
                        synchronized (mPackages) {
                            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
                            if (pkgSetting.getInstallReason(userId)
                                    != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
                                setDefaultBrowserAsyncLPw(null, userId);
                            }
                        }
                    }
                    // We may also need to apply pending (restored) runtime permission grants
                    // within these users.
@@ -2013,8 +2014,7 @@ public class PackageManagerService extends IPackageManager.Stub
                    // Persistent preferred activity might have came into effect due to this
                    // install.
                        updateDefaultHomeLPw(userId);
                    }
                    updateDefaultHomeNotLocked(userId);
                }
            }
@@ -5158,7 +5158,7 @@ public class PackageManagerService extends IPackageManager.Stub
                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId),
                            (libInfo.getDependencies() == null
                                    ? null
                                    : new ArrayList(libInfo.getDependencies())));
                                    : new ArrayList<>(libInfo.getDependencies())));
                    if (result == null) {
                        result = new ArrayList<>();
@@ -6475,8 +6475,8 @@ public class PackageManagerService extends IPackageManager.Stub
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                userId);
        // Find any earlier preferred or last chosen entries and nuke them
        findPreferredActivity(intent, resolvedType,
                flags, query, 0, false, true, false, userId);
        findPreferredActivityNotLocked(
                intent, resolvedType, flags, query, 0, false, true, false, userId);
        // Add the new activity as the last chosen for this filter
        addPreferredActivityInternal(filter, match, null, activity, false, userId,
                "Setting last chosen");
@@ -6491,8 +6491,8 @@ public class PackageManagerService extends IPackageManager.Stub
        if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                userId);
        return findPreferredActivity(intent, resolvedType, flags, query, 0,
                false, false, false, userId);
        return findPreferredActivityNotLocked(
                intent, resolvedType, flags, query, 0, false, false, false, userId);
    }
    /**
@@ -6605,7 +6605,7 @@ public class PackageManagerService extends IPackageManager.Stub
                }
                // If we have saved a preference for a preferred activity for
                // this Intent, use that.
                ResolveInfo ri = findPreferredActivity(intent, resolvedType,
                ResolveInfo ri = findPreferredActivityNotLocked(intent, resolvedType,
                        flags, query, r0.priority, true, false, debug, userId);
                if (ri != null) {
                    return ri;
@@ -6744,9 +6744,14 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    // TODO: handle preferred activities missing while user has amnesia
    ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
    /** <b>must not hold {@link #mPackages}</b> */
    ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags,
            List<ResolveInfo> query, int priority, boolean always,
            boolean removeMatches, boolean debug, int userId) {
        if (Thread.holdsLock(mPackages)) {
            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
                    + " is holding mPackages", new Throwable());
        }
        if (!sUserManager.exists(userId)) return null;
        final int callingUid = Binder.getCallingUid();
        // Do NOT hold the packages lock; this calls up into the settings provider which
@@ -18599,10 +18604,10 @@ public class PackageManagerService extends IPackageManager.Stub
        int removedAppId = -1;
        // writer
        synchronized (mPackages) {
        boolean installedStateChanged = false;
        if (deletedPs != null) {
            if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
                synchronized (mPackages) {
                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                    clearDefaultBrowserIfNeeded(packageName);
                    mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
@@ -18633,7 +18638,14 @@ public class PackageManagerService extends IPackageManager.Stub
                            }
                        }
                    }
                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                }
                final SparseBooleanArray changedUsers = new SparseBooleanArray();
                clearPackagePreferredActivitiesLPw(
                        deletedPs.name, changedUsers, UserHandle.USER_ALL);
                if (changedUsers.size() > 0) {
                    updateDefaultHomeNotLocked(changedUsers);
                    postPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
                }
            }
            // make sure to preserve per-user disabled state if this removal was just
            // a downgrade of a system app to the factory package
@@ -18653,6 +18665,7 @@ public class PackageManagerService extends IPackageManager.Stub
                }
            }
        }
        synchronized (mPackages) {
            // can downgrade to reader
            if (writeSettings) {
                // Save settings now
@@ -19330,10 +19343,17 @@ public class PackageManagerService extends IPackageManager.Stub
            destroyAppDataLIF(pkg, nextUserId,
                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
            clearDefaultBrowserIfNeededForUser(ps.name, nextUserId);
            removeKeystoreDataIfNeeded(nextUserId, ps.appId);
            final SparseBooleanArray changedUsers = new SparseBooleanArray();
            clearPackagePreferredActivitiesLPw(ps.name, changedUsers, nextUserId);
            if (changedUsers.size() > 0) {
                updateDefaultHomeNotLocked(changedUsers);
                postPreferredActivityChangedBroadcast(nextUserId);
                synchronized (mPackages) {
                if (clearPackagePreferredActivitiesLPw(ps.name, nextUserId)) {
                    scheduleWritePackageRestrictionsLocked(nextUserId);
                }
            }
            synchronized (mPackages) {
                resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, nextUserId);
            }
            // Also delete contributed media, when requested
@@ -19796,11 +19816,6 @@ public class PackageManagerService extends IPackageManager.Stub
        int callingUid = Binder.getCallingUid();
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, false /* checkShell */, "add preferred activity");
        if (filter.countActions() == 0) {
            Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
            return;
        }
        synchronized (mPackages) {
        if (mContext.checkCallingOrSelfPermission(
                android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                != PackageManager.PERMISSION_GRANTED) {
@@ -19813,16 +19828,22 @@ public class PackageManagerService extends IPackageManager.Stub
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
        }
            PreferredIntentResolver pir = mSettings.editPreferredActivitiesLPw(userId);
        if (filter.countActions() == 0) {
            Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
            return;
        }
        if (DEBUG_PREFERRED) {
            Slog.i(TAG, opname + " activity " + activity.flattenToShortString() + " for user "
                    + userId + ":");
            filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
            pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
            scheduleWritePackageRestrictionsLocked(userId);
            if (!updateDefaultHomeLPw(userId)) {
        }
        if (!updateDefaultHomeNotLocked(userId)) {
            postPreferredActivityChangedBroadcast(userId);
        }
        synchronized (mPackages) {
            final PreferredIntentResolver pir = mSettings.editPreferredActivitiesLPw(userId);
            pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
            scheduleWritePackageRestrictionsLocked(userId);
        }
    }
@@ -19963,25 +19984,24 @@ public class PackageManagerService extends IPackageManager.Stub
                    && filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
                return;
            }
            int user = UserHandle.getCallingUserId();
            if (clearPackagePreferredActivitiesLPw(packageName, user)) {
                scheduleWritePackageRestrictionsLocked(user);
        }
        int callingUserId = UserHandle.getCallingUserId();
        final SparseBooleanArray changedUsers = new SparseBooleanArray();
        clearPackagePreferredActivitiesLPw(packageName, changedUsers, callingUserId);
        if (changedUsers.size() > 0) {
            updateDefaultHomeNotLocked(changedUsers);
            postPreferredActivityChangedBroadcast(callingUserId);
            synchronized (mPackages) {
                scheduleWritePackageRestrictionsLocked(callingUserId);
            }
        }
    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
    @GuardedBy("mPackages")
    boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
        return clearPackagePreferredActivitiesLPw(packageName, false, userId);
    }
    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
    @GuardedBy("mPackages")
    private boolean clearPackagePreferredActivitiesLPw(String packageName,
            boolean skipUpdateDefaultHome, int userId) {
    private void clearPackagePreferredActivitiesLPw(String packageName,
            @NonNull SparseBooleanArray outUserChanged, int userId) {
        ArrayList<PreferredActivity> removed = null;
        boolean changed = false;
        for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
            final int thisUserId = mSettings.mPreferredActivities.keyAt(i);
            PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
@@ -20007,16 +20027,9 @@ public class PackageManagerService extends IPackageManager.Stub
                    PreferredActivity pa = removed.get(j);
                    pir.removeFilter(pa);
                }
                changed = true;
                if (!skipUpdateDefaultHome) {
                    updateDefaultHomeLPw(thisUserId);
                }
                outUserChanged.setValueAt(thisUserId, true);
            }
        }
        if (changed) {
            postPreferredActivityChangedBroadcast(userId);
        }
        return changed;
    }
    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
@@ -20069,21 +20082,27 @@ public class PackageManagerService extends IPackageManager.Stub
        final long identity = Binder.clearCallingIdentity();
        // writer
        try {
            final SparseBooleanArray changedUsers = new SparseBooleanArray();
            clearPackagePreferredActivitiesLPw(null, changedUsers, userId);
            if (changedUsers.size() > 0) {
                postPreferredActivityChangedBroadcast(userId);
            }
            synchronized (mPackages) {
                clearPackagePreferredActivitiesLPw(null, true, userId);
                mSettings.applyDefaultPreferredAppsLPw(userId);
                updateDefaultHomeLPw(userId);
                clearIntentFilterVerificationsLPw(userId);
                primeDomainVerificationsLPw(userId);
                resetUserChangesToRuntimePermissionsAndFlagsLPw(userId);
            }
            updateDefaultHomeNotLocked(userId);
            // TODO: We have to reset the default SMS and Phone. This requires
            // significant refactoring to keep all default apps in the package
            // manager (cleaner but more work) or have the services provide
            // callbacks to the package manager to request a default app reset.
            setDefaultBrowserPackageName(null, userId);
                clearIntentFilterVerificationsLPw(userId);
                primeDomainVerificationsLPw(userId);
                resetUserChangesToRuntimePermissionsAndFlagsLPw(userId);
            resetNetworkPolicies(userId);
            synchronized (mPackages) {
                scheduleWritePackageRestrictionsLocked(userId);
            }
            resetNetworkPolicies(userId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -20133,15 +20152,17 @@ public class PackageManagerService extends IPackageManager.Stub
            Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
            return;
        }
        synchronized (mPackages) {
            Slog.i(TAG, "Adding persistent preferred activity " + activity + " for user " + userId +
                    ":");
        if (DEBUG_PREFERRED) {
            Slog.i(TAG, "Adding persistent preferred activity " + activity
                    + " for user " + userId + ":");
            filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
        }
        updateDefaultHomeNotLocked(userId);
        postPreferredActivityChangedBroadcast(userId);
        synchronized (mPackages) {
            mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
                    new PersistentPreferredActivity(filter, activity));
            scheduleWritePackageRestrictionsLocked(userId);
            postPreferredActivityChangedBroadcast(userId);
            updateDefaultHomeLPw(userId);
        }
    }
@@ -20181,11 +20202,12 @@ public class PackageManagerService extends IPackageManager.Stub
                    changed = true;
                }
            }
        }
        if (changed) {
                scheduleWritePackageRestrictionsLocked(userId);
            updateDefaultHomeNotLocked(userId);
            postPreferredActivityChangedBroadcast(userId);
                updateDefaultHomeLPw(userId);
            synchronized (mPackages) {
                scheduleWritePackageRestrictionsLocked(userId);
            }
        }
    }
@@ -20273,8 +20295,8 @@ public class PackageManagerService extends IPackageManager.Stub
                    (readParser, readUserId) -> {
                        synchronized (mPackages) {
                            mSettings.readPreferredActivitiesLPw(readParser, readUserId);
                            updateDefaultHomeLPw(readUserId);
                        }
                        updateDefaultHomeNotLocked(readUserId);
                    });
        } catch (Exception e) {
            if (DEBUG_BACKUP) {
@@ -20601,29 +20623,55 @@ public class PackageManagerService extends IPackageManager.Stub
        return null;
    }
    /** <b>must not hold {@link #mPackages}</b> */
    private void updateDefaultHomeNotLocked(SparseBooleanArray userIds) {
        if (Thread.holdsLock(mPackages)) {
            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
                    + " is holding mPackages", new Throwable());
        }
        for (int i = userIds.size() - 1; i >= 0; --i) {
            final int userId = userIds.keyAt(i);
            updateDefaultHomeNotLocked(userId);
        }
    }
    /**
     * <b>must not hold {@link #mPackages}</b>
     *
     * @return Whether the ACTION_PREFERRED_ACTIVITY_CHANGED broadcast has been scheduled.
     */
    private boolean updateDefaultHomeLPw(int userId) {
        Intent intent = getHomeIntent();
        List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
    private boolean updateDefaultHomeNotLocked(int userId) {
        if (Thread.holdsLock(mPackages)) {
            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
                    + " is holding mPackages", new Throwable());
        }
        final Intent intent = getHomeIntent();
        final List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
                PackageManager.GET_META_DATA, userId);
        ResolveInfo preferredResolveInfo = findPreferredActivity(intent, null, 0, resolveInfos,
                0, true, false, false, userId);
        String packageName = preferredResolveInfo != null
        final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked(
                intent, null, 0, resolveInfos, 0, true, false, false, userId);
        final String packageName = preferredResolveInfo != null
                && preferredResolveInfo.activityInfo != null
                ? preferredResolveInfo.activityInfo.packageName : null;
        String currentPackageName = mDefaultHomeProvider.getDefaultHome(userId);
        final PackageManagerInternal.DefaultHomeProvider provider;
        synchronized (mPackages) {
            provider = mDefaultHomeProvider;
        }
        if (provider == null) {
            Slog.e(TAG, "Default home provider has not been set");
            return false;
        }
        final String currentPackageName = provider.getDefaultHome(userId);
        if (TextUtils.equals(currentPackageName, packageName)) {
            return false;
        }
        String[] callingPackages = getPackagesForUid(Binder.getCallingUid());
        final String[] callingPackages = getPackagesForUid(Binder.getCallingUid());
        if (callingPackages != null && ArrayUtils.contains(callingPackages,
                mRequiredPermissionControllerPackage)) {
            // PermissionController manages default home directly.
            return false;
        }
        mDefaultHomeProvider.setDefaultHomeAsync(packageName, userId, (successful) -> {
        provider.setDefaultHomeAsync(packageName, userId, (successful) -> {
            if (successful) {
                postPreferredActivityChangedBroadcast(userId);
            }