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

Commit 1d4b9580 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 rvc-dev am: 15ae228d

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



Change-Id: I9e61356ca633c6800098a5511b7330db7a4503ae
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents b4f4ac8e 15ae228d
Loading
Loading
Loading
Loading
+76 −3
Original line number Original line Diff line number Diff line
@@ -68,6 +68,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;


/**
/**
 * Package information used by {@link ShortcutService}.
 * Package information used by {@link ShortcutService}.
@@ -350,6 +351,7 @@ class ShortcutPackage extends ShortcutPackageItem {
            @NonNull List<ShortcutInfo> changedShortcuts) {
            @NonNull List<ShortcutInfo> changedShortcuts) {
        Preconditions.checkArgument(newShortcut.isEnabled(),
        Preconditions.checkArgument(newShortcut.isEnabled(),
                "pushDynamicShortcuts() cannot publish disabled shortcuts");
                "pushDynamicShortcuts() cannot publish disabled shortcuts");
        ensureShortcutCountBeforePush();


        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);


@@ -357,7 +359,7 @@ class ShortcutPackage extends ShortcutPackageItem {
        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
        boolean deleted = false;
        boolean deleted = false;


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


@@ -367,7 +369,6 @@ class ShortcutPackage extends ShortcutPackageItem {


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

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


@@ -382,7 +383,8 @@ class ShortcutPackage extends ShortcutPackageItem {
                changedShortcuts.add(shortcut);
                changedShortcuts.add(shortcut);
                deleted = deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true) != null;
                deleted = deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true) != null;
            }
            }
        } else {
        }
        if (oldShortcut != null) {
            // It's an update case.
            // It's an update case.
            // Make sure the target is updatable. (i.e. should be mutable.)
            // Make sure the target is updatable. (i.e. should be mutable.)
            oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
            oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -396,6 +398,30 @@ class ShortcutPackage extends ShortcutPackageItem {
        return deleted;
        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();
        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.
     * Remove all shortcuts that aren't pinned, cached nor dynamic.
     *
     *
@@ -1222,6 +1248,53 @@ class ShortcutPackage extends ShortcutPackageItem {
        return Integer.compare(a.getRank(), b.getRank());
        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 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
     * 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.
     * contain "floating" shortcuts because they don't belong on any activities.
+24 −1
Original line number Original line Diff line number Diff line
@@ -171,6 +171,9 @@ public class ShortcutService extends IShortcutService.Stub {
    @VisibleForTesting
    @VisibleForTesting
    static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
    static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;


    @VisibleForTesting
    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;

    @VisibleForTesting
    @VisibleForTesting
    static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
    static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;


@@ -245,6 +248,11 @@ public class ShortcutService extends IShortcutService.Stub {
         */
         */
        String KEY_MAX_SHORTCUTS = "max_shortcuts";
        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.
         * Key name for icon compression quality, 0-100.
         */
         */
@@ -302,10 +310,15 @@ public class ShortcutService extends IShortcutService.Stub {
            new SparseArray<>();
            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;
    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.
     * Max number of updating API calls that each application can make during the interval.
     */
     */
@@ -732,6 +745,9 @@ public class ShortcutService extends IShortcutService.Stub {
        mMaxShortcuts = Math.max(0, (int) parser.getLong(
        mMaxShortcuts = Math.max(0, (int) parser.getLong(
                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
                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()
        final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
                ? (int) parser.getLong(
                ? (int) parser.getLong(
                ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
                ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1661,6 +1677,13 @@ public class ShortcutService extends IShortcutService.Stub {
        return mMaxShortcuts;
        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
     * - Sends a notification to LauncherApps
     * - Write to file
     * - Write to file