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

Commit 2e79de04 authored by Pinyao Ting's avatar Pinyao Ting Committed by Automerger Merge Worker
Browse files

Merge "Limit the number of shortcuts per app that can be retained by system"...

Merge "Limit the number of shortcuts per app that can be retained by system" into sc-dev am: d8bf6af4

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21574889



Change-Id: I5b56983c96c7c34292baa58e02a5da63fd3de53d
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1b3b97d9 d8bf6af4
Loading
Loading
Loading
Loading
+85 −3
Original line number Diff line number Diff line
@@ -405,6 +405,7 @@ class ShortcutPackage extends ShortcutPackageItem {
            @NonNull List<ShortcutInfo> changedShortcuts) {
        Preconditions.checkArgument(newShortcut.isEnabled(),
                "pushDynamicShortcuts() cannot publish disabled shortcuts");
        ensureShortcutCountBeforePush();

        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);

@@ -412,7 +413,7 @@ class ShortcutPackage extends ShortcutPackageItem {
        final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
        boolean deleted = false;

        if (oldShortcut == null) {
        if (oldShortcut == null || !oldShortcut.isDynamic()) {
            final ShortcutService service = mShortcutUser.mService;
            final int maxShortcuts = service.getMaxActivityShortcuts();

@@ -422,7 +423,6 @@ class ShortcutPackage extends ShortcutPackageItem {

            if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
                // Max has reached. Delete the shortcut with lowest rank.

                // Sort by isManifestShortcut() and getRank().
                Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);

@@ -437,7 +437,8 @@ class ShortcutPackage extends ShortcutPackageItem {
                changedShortcuts.add(shortcut);
                deleted = deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true) != null;
            }
        } else {
        }
        if (oldShortcut != null) {
            // It's an update case.
            // Make sure the target is updatable. (i.e. should be mutable.)
            oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -463,6 +464,32 @@ class ShortcutPackage extends ShortcutPackageItem {
        return deleted;
    }

    private void ensureShortcutCountBeforePush() {
        final ShortcutService service = mShortcutUser.mService;
        // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
        final int maxShortcutPerApp = service.getMaxAppShortcuts();
        synchronized (mLock) {
            final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
                    !si.isPinned()).collect(Collectors.toList());
            if (appShortcuts.size() >= maxShortcutPerApp) {
                // Max has reached. Removes shortcuts until they fall within the hard cap.
                // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
                Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);

                while (appShortcuts.size() >= maxShortcutPerApp) {
                    final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
                    if (shortcut.isDeclaredInManifest()) {
                        // All shortcuts are manifest shortcuts and cannot be removed.
                        throw new IllegalArgumentException(getPackageName() + " has published "
                                + appShortcuts.size() + " manifest shortcuts across different"
                                + " activities.");
                    }
                    forceDeleteShortcutInner(shortcut.getId());
                }
            }
        }
    }

    /**
     * Remove all shortcuts that aren't pinned, cached nor dynamic.
     *
@@ -1368,6 +1395,61 @@ class ShortcutPackage extends ShortcutPackageItem {
        return Integer.compare(a.getRank(), b.getRank());
    };

    /**
     * To sort by isManifestShortcut(), isDynamic(), getRank() and
     * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
     * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
     *
     * This is used to decide which shortcuts to remove when the total number of shortcuts retained
     * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
     *
     * (Note the number of manifest shortcuts is always <= the max number, because if there are
     * more, ShortcutParser would ignore the rest.)
     */
    final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
            ShortcutInfo b) -> {
        if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
            return -1;
        }
        if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
            return 1;
        }
        if (a.isDynamic() && b.isDynamic()) {
            return Integer.compare(a.getRank(), b.getRank());
        }
        if (a.isDynamic()) {
            return -1;
        }
        if (b.isDynamic()) {
            return 1;
        }
        if (a.isCached() && b.isCached()) {
            // if both shortcuts are cached, prioritize shortcuts cached by people tile,
            if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
                    && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
                return -1;
            } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
                    && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
                return 1;
            }
            // followed by bubbles.
            if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
                    && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
                return -1;
            } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
                    && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
                return 1;
            }
        }
        if (a.isCached()) {
            return -1;
        }
        if (b.isCached()) {
            return 1;
        }
        return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
    };

    /**
     * Build a list of shortcuts for each target activity and return as a map. The result won't
     * contain "floating" shortcuts because they don't belong on any activities.
+24 −1
Original line number Diff line number Diff line
@@ -179,6 +179,9 @@ public class ShortcutService extends IShortcutService.Stub {
    @VisibleForTesting
    static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;

    @VisibleForTesting
    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;

    @VisibleForTesting
    static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;

@@ -253,6 +256,11 @@ public class ShortcutService extends IShortcutService.Stub {
         */
        String KEY_MAX_SHORTCUTS = "max_shortcuts";

        /**
         * Key name for the max shortcuts can be retained in system ram per app. (int)
         */
        String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";

        /**
         * Key name for icon compression quality, 0-100.
         */
@@ -325,10 +333,15 @@ public class ShortcutService extends IShortcutService.Stub {
            new SparseArray<>();

    /**
     * Max number of dynamic + manifest shortcuts that each application can have at a time.
     * Max number of dynamic + manifest shortcuts that each activity can have at a time.
     */
    private int mMaxShortcuts;

    /**
     * Max number of shortcuts that can exists in system ram for each application.
     */
    private int mMaxShortcutsPerApp;

    /**
     * Max number of updating API calls that each application can make during the interval.
     */
@@ -790,6 +803,9 @@ public class ShortcutService extends IShortcutService.Stub {
        mMaxShortcuts = Math.max(0, (int) parser.getLong(
                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));

        mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
                ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));

        final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
                ? (int) parser.getLong(
                ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1757,6 +1773,13 @@ public class ShortcutService extends IShortcutService.Stub {
        return mMaxShortcuts;
    }

    /**
     * Return the max number of shortcuts can be retaiend in system ram for each application.
     */
    int getMaxAppShortcuts() {
        return mMaxShortcutsPerApp;
    }

    /**
     * - Sends a notification to LauncherApps
     * - Write to file