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

Commit 950d96b2 authored by Songchun Fan's avatar Songchun Fan
Browse files

[AppsFilter] make mShouldFilterCache non null

To prepare adding a snapshot cache for it. Instead of copy+modify+swap,
we now modify the content of it in place.

BUG: 218411030
Test: atest AppsFilterTest
Test: m RUN_ERROR_PRONE=true framework services.core |& grep AppsFilter
Change-Id: Ief23ef7ce2272057ebccca4f552687b21ae55c1a
parent 3057f825
Loading
Loading
Loading
Loading
+168 −170
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.QuadFunction;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -171,10 +170,13 @@ public class AppsFilter implements Watchable, Snappable {
     * filtered to the second. It's essentially a cache of the
     * {@link #shouldFilterApplicationInternal(int, Object, PackageStateInternal, int)} call.
     * NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on
     * initial scam and is null until {@link #onSystemReady()} is called.
     * initial scam and is empty until {@link #mSystemReady} is true.
     */
    @GuardedBy("mCacheLock")
    private volatile WatchedSparseBooleanMatrix mShouldFilterCache;
    @NonNull
    private final WatchedSparseBooleanMatrix mShouldFilterCache;

    private volatile boolean mSystemReady = false;

    /**
     * A cached snapshot.
@@ -187,7 +189,8 @@ public class AppsFilter implements Watchable, Snappable {
            public AppsFilter createSnapshot() {
                AppsFilter s = new AppsFilter(mSource);
                return s;
            }};
            }
        };
    }

    /**
@@ -219,6 +222,7 @@ public class AppsFilter implements Watchable, Snappable {

    /**
     * Return true if the {@link Watcher) is a registered observer.
     *
     * @param observer A {@link Watcher} that might be registered
     * @return true if the observer is registered with this {@link Watchable}.
     */
@@ -262,6 +266,7 @@ public class AppsFilter implements Watchable, Snappable {
        mStateProvider = stateProvider;
        mPmInternal = pmInternal;
        mBackgroundExecutor = backgroundExecutor;
        mShouldFilterCache = new WatchedSparseBooleanMatrix();
        mSnapshot = makeCache();
    }

@@ -285,16 +290,14 @@ public class AppsFilter implements Watchable, Snappable {
        mStateProvider = orig.mStateProvider;
        mSystemSigningDetails = orig.mSystemSigningDetails;
        mProtectedBroadcasts = orig.mProtectedBroadcasts;
        mShouldFilterCache = orig.mShouldFilterCache;
        if (mShouldFilterCache != null) {
        synchronized (orig.mCacheLock) {
                mShouldFilterCache = mShouldFilterCache.snapshot();
            }
            mShouldFilterCache = orig.mShouldFilterCache.snapshot();
        }

        mBackgroundExecutor = null;
        mPmInternal = null;
        mSnapshot = new SnapshotCache.Sealed<>();
        mSystemReady = true;
    }

    /**
@@ -669,8 +672,9 @@ public class AppsFilter implements Watchable, Snappable {
            Slog.i(TAG, (retainOnUpdate ? "retained " : "") + "implicit access granted: "
                    + recipientUid + " -> " + visibleUid);
        }

        if (mSystemReady) {
            synchronized (mCacheLock) {
            if (mShouldFilterCache != null) {
                // update the cache in a one-off manner since we've got all the information we
                // need.
                mShouldFilterCache.put(recipientUid, visibleUid, false);
@@ -688,6 +692,7 @@ public class AppsFilter implements Watchable, Snappable {

        updateEntireShouldFilterCacheAsync();
        onChanged();
        mSystemReady = true;
    }

    /**
@@ -708,9 +713,8 @@ public class AppsFilter implements Watchable, Snappable {
            mStateProvider.runWithState((settings, users) -> {
                ArraySet<String> additionalChangedPackages =
                        addPackageInternal(newPkgSetting, settings);
                synchronized (mCacheLock) {
                    if (mShouldFilterCache != null) {
                        updateShouldFilterCacheForPackage(mShouldFilterCache, null, newPkgSetting,
                if (mSystemReady) {
                    updateShouldFilterCacheForPackage(null, newPkgSetting,
                            settings, users, USER_ALL, settings.size());
                    if (additionalChangedPackages != null) {
                        for (int index = 0; index < additionalChangedPackages.size(); index++) {
@@ -724,13 +728,12 @@ public class AppsFilter implements Watchable, Snappable {
                                continue;
                            }

                                updateShouldFilterCacheForPackage(mShouldFilterCache, null,
                            updateShouldFilterCacheForPackage(null,
                                    changedPkgSetting, settings, users, USER_ALL,
                                    settings.size());
                        }
                    }
                } // else, rebuild entire cache when system is ready
                }
            });
        } finally {
            onChanged();
@@ -845,11 +848,11 @@ public class AppsFilter implements Watchable, Snappable {
        return changedPackages;
    }

    @GuardedBy("mCacheLock")
    private void removeAppIdFromVisibilityCache(int appId) {
        if (mShouldFilterCache == null) {
        if (!mSystemReady) {
            return;
        }
        synchronized (mCacheLock) {
            for (int i = 0; i < mShouldFilterCache.size(); i++) {
                if (UserHandle.getAppId(mShouldFilterCache.keyAt(i)) == appId) {
                    mShouldFilterCache.removeAt(i);
@@ -861,6 +864,7 @@ public class AppsFilter implements Watchable, Snappable {
                }
            }
        }
    }

    private void updateEntireShouldFilterCache() {
        updateEntireShouldFilterCache(USER_ALL);
@@ -880,31 +884,23 @@ public class AppsFilter implements Watchable, Snappable {
                        + "updating the whole cache");
                userId = USER_ALL;
            }
            WatchedSparseBooleanMatrix cache =
            updateEntireShouldFilterCacheInner(settings, users, userId);
            synchronized (mCacheLock) {
                mShouldFilterCache = cache;
            }
        });
    }

    private WatchedSparseBooleanMatrix updateEntireShouldFilterCacheInner(
    private void updateEntireShouldFilterCacheInner(
            ArrayMap<String, ? extends PackageStateInternal> settings, UserInfo[] users,
            int subjectUserId) {
        final WatchedSparseBooleanMatrix cache;
        if (subjectUserId == USER_ALL) {
            cache = new WatchedSparseBooleanMatrix(users.length * settings.size());
        } else {
        synchronized (mCacheLock) {
                cache = mShouldFilterCache.snapshot();
            if (subjectUserId == USER_ALL) {
                mShouldFilterCache.clear();
            }
            cache.setCapacity(users.length * settings.size());
            mShouldFilterCache.setCapacity(users.length * settings.size());
        }
        for (int i = settings.size() - 1; i >= 0; i--) {
            updateShouldFilterCacheForPackage(cache,
            updateShouldFilterCacheForPackage(
                    null /*skipPackage*/, settings.valueAt(i), settings, users, subjectUserId, i);
        }
        return cache;
    }

    private void updateEntireShouldFilterCacheAsync() {
@@ -923,8 +919,7 @@ public class AppsFilter implements Watchable, Snappable {
                    packagesCache.put(settings.keyAt(i), pkg);
                }
            });
            WatchedSparseBooleanMatrix cache = updateEntireShouldFilterCacheInner(
                    settingsCopy, usersRef[0], USER_ALL);

            boolean[] changed = new boolean[1];
            // We have a cache, let's make sure the world hasn't changed out from under us.
            mStateProvider.runWithState((settings, users) -> {
@@ -947,45 +942,39 @@ public class AppsFilter implements Watchable, Snappable {
                    Slog.i(TAG, "Rebuilding cache with lock due to package change.");
                }
            } else {
                synchronized (mCacheLock) {
                    mShouldFilterCache = cache;
                }
                updateEntireShouldFilterCacheInner(settingsCopy, usersRef[0], USER_ALL);
            }
        });
    }

    public void onUserCreated(int newUserId) {
        synchronized (mCacheLock) {
            if (mShouldFilterCache != null) {
        if (!mSystemReady) {
            return;
        }
        updateEntireShouldFilterCache(newUserId);
        onChanged();
    }
        }
    }

    public void onUserDeleted(@UserIdInt int userId) {
        synchronized (mCacheLock) {
            if (mShouldFilterCache != null) {
        if (!mSystemReady) {
            return;
        }
        removeShouldFilterCacheForUser(userId);
        onChanged();
    }
        }
    }

    private void updateShouldFilterCacheForPackage(String packageName) {
        mStateProvider.runWithState((settings, users) -> {
            synchronized (mCacheLock) {
                if (mShouldFilterCache == null) {
            if (!mSystemReady) {
                return;
            }
                updateShouldFilterCacheForPackage(mShouldFilterCache, null /* skipPackage */,
            updateShouldFilterCacheForPackage(null /* skipPackage */,
                    settings.get(packageName), settings, users, USER_ALL,
                    settings.size() /*maxIndex*/);
            }
        });
    }

    private void updateShouldFilterCacheForPackage(WatchedSparseBooleanMatrix cache,
    private void updateShouldFilterCacheForPackage(
            @Nullable String skipPackageName, PackageStateInternal subjectSetting, ArrayMap<String,
            ? extends PackageStateInternal> allSettings, UserInfo[] allUsers, int subjectUserId,
            int maxIndex) {
@@ -1001,34 +990,36 @@ public class AppsFilter implements Watchable, Snappable {
            }
            if (subjectUserId == USER_ALL) {
                for (int su = 0; su < allUsers.length; su++) {
                    updateShouldFilterCacheForUser(cache, subjectSetting, allUsers, otherSetting,
                    updateShouldFilterCacheForUser(subjectSetting, allUsers, otherSetting,
                            allUsers[su].id);
                }
            } else {
                updateShouldFilterCacheForUser(cache, subjectSetting, allUsers, otherSetting,
                updateShouldFilterCacheForUser(subjectSetting, allUsers, otherSetting,
                        subjectUserId);
            }
        }
    }

    private void updateShouldFilterCacheForUser(WatchedSparseBooleanMatrix cache,
    private void updateShouldFilterCacheForUser(
            PackageStateInternal subjectSetting, UserInfo[] allUsers,
            PackageStateInternal otherSetting, int subjectUserId) {
        for (int ou = 0; ou < allUsers.length; ou++) {
            int otherUser = allUsers[ou].id;
            int subjectUid = UserHandle.getUid(subjectUserId, subjectSetting.getAppId());
            int otherUid = UserHandle.getUid(otherUser, otherSetting.getAppId());
            cache.put(subjectUid, otherUid,
                    shouldFilterApplicationInternal(
                            subjectUid, subjectSetting, otherSetting, otherUser));
            cache.put(otherUid, subjectUid,
                    shouldFilterApplicationInternal(
                            otherUid, otherSetting, subjectSetting, subjectUserId));
            final boolean shouldFilterSubjectToOther = shouldFilterApplicationInternal(
                    subjectUid, subjectSetting, otherSetting, otherUser);
            final boolean shouldFilterOtherToSubject = shouldFilterApplicationInternal(
                    otherUid, otherSetting, subjectSetting, subjectUserId);
            synchronized (mCacheLock) {
                mShouldFilterCache.put(subjectUid, otherUid, shouldFilterSubjectToOther);
                mShouldFilterCache.put(otherUid, subjectUid, shouldFilterOtherToSubject);
            }
        }
    }

    @GuardedBy("mCacheLock")
    private void removeShouldFilterCacheForUser(int userId) {
        synchronized (mCacheLock) {
            // Sorted uids with the ascending order
            final int[] cacheUids = mShouldFilterCache.keys();
            final int size = cacheUids.length;
@@ -1049,6 +1040,7 @@ public class AppsFilter implements Watchable, Snappable {
            mShouldFilterCache.removeRange(fromIndex, toIndex);
            mShouldFilterCache.compact();
        }
    }

    private static boolean isSystemSigned(@NonNull SigningDetails sysSigningDetails,
            PackageStateInternal pkgSetting) {
@@ -1171,6 +1163,7 @@ public class AppsFilter implements Watchable, Snappable {
    /**
     * Equivalent to calling {@link #addPackage(PackageStateInternal, boolean)} with
     * {@code isReplace} equal to {@code false}.
     *
     * @see AppsFilter#addPackage(PackageStateInternal, boolean)
     */
    public void addPackage(PackageStateInternal newPkgSetting) {
@@ -1253,9 +1246,8 @@ public class AppsFilter implements Watchable, Snappable {
                }
            }

            synchronized (mCacheLock) {
            removeAppIdFromVisibilityCache(setting.getAppId());
                if (mShouldFilterCache != null && setting.hasSharedUser()) {
            if (mSystemReady && setting.hasSharedUser()) {
                final ArraySet<PackageStateInternal> sharedUserPackages =
                        mPmInternal.getSharedUserPackages(setting.getSharedUserAppId());
                for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
@@ -1264,13 +1256,13 @@ public class AppsFilter implements Watchable, Snappable {
                    if (siblingSetting == setting) {
                        continue;
                    }
                        updateShouldFilterCacheForPackage(mShouldFilterCache,
                    updateShouldFilterCacheForPackage(
                            setting.getPackageName(), siblingSetting, settings, users,
                            USER_ALL, settings.size());
                }
            }

                if (mShouldFilterCache != null) {
            if (mSystemReady) {
                if (additionalChangedPackages != null) {
                    for (int index = 0; index < additionalChangedPackages.size(); index++) {
                        String changedPackage = additionalChangedPackages.valueAt(index);
@@ -1282,14 +1274,13 @@ public class AppsFilter implements Watchable, Snappable {
                            continue;
                        }

                            updateShouldFilterCacheForPackage(mShouldFilterCache, null,
                        updateShouldFilterCacheForPackage(null,
                                changedPkgSetting, settings, users, USER_ALL, settings.size());
                    }
                }
            }

            onChanged();
            }
        });
    }

@@ -1315,22 +1306,10 @@ public class AppsFilter implements Watchable, Snappable {
                    || callingAppId == targetPkgSetting.getAppId()) {
                return false;
            }
            synchronized (mCacheLock) {
                if (mShouldFilterCache != null) { // use cache
                    final int callingIndex = mShouldFilterCache.indexOfKey(callingUid);
                    if (callingIndex < 0) {
                        Slog.wtf(TAG, "Encountered calling uid with no cached rules: "
                                + callingUid);
                        return true;
                    }
                    final int targetUid = UserHandle.getUid(userId, targetPkgSetting.getAppId());
                    final int targetIndex = mShouldFilterCache.indexOfKey(targetUid);
                    if (targetIndex < 0) {
                        Slog.w(TAG, "Encountered calling -> target with no cached rules: "
                                + callingUid + " -> " + targetUid);
                        return true;
                    }
                    if (!mShouldFilterCache.valueAt(callingIndex, targetIndex)) {
            if (mSystemReady) { // use cache
                if (!shouldFilterApplicationUsingCache(callingUid,
                        targetPkgSetting.getAppId(),
                        userId)) {
                    return false;
                }
            } else {
@@ -1339,7 +1318,6 @@ public class AppsFilter implements Watchable, Snappable {
                    return false;
                }
            }
            }
            if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(callingAppId)) {
                log(callingSetting, targetPkgSetting, "BLOCKED");
            }
@@ -1351,6 +1329,25 @@ public class AppsFilter implements Watchable, Snappable {
        }
    }

    private boolean shouldFilterApplicationUsingCache(int callingUid, int appId, int userId) {
        synchronized (mCacheLock) {
            final int callingIndex = mShouldFilterCache.indexOfKey(callingUid);
            if (callingIndex < 0) {
                Slog.wtf(TAG, "Encountered calling uid with no cached rules: "
                        + callingUid);
                return true;
            }
            final int targetUid = UserHandle.getUid(userId, appId);
            final int targetIndex = mShouldFilterCache.indexOfKey(targetUid);
            if (targetIndex < 0) {
                Slog.w(TAG, "Encountered calling -> target with no cached rules: "
                        + callingUid + " -> " + targetUid);
                return true;
            }
            return mShouldFilterCache.valueAt(callingIndex, targetIndex);
        }
    }

    private boolean shouldFilterApplicationInternal(int callingUid, Object callingSetting,
            PackageStateInternal targetPkgSetting, int targetUserId) {
        if (DEBUG_TRACING) {
@@ -1747,6 +1744,7 @@ public class AppsFilter implements Watchable, Snappable {

    private interface ToString<T> {
        String toString(T input);

    }

    private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId,