Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -12466,6 +12466,7 @@ package android.content.pm { method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(int); method public boolean isRateLimitingActive(); method public boolean isRequestPinShortcutSupported(); method public void pushDynamicShortcut(@NonNull android.content.pm.ShortcutInfo); method public void removeAllDynamicShortcuts(); method public void removeDynamicShortcuts(@NonNull java.util.List<java.lang.String>); method public void removeLongLivedShortcuts(@NonNull java.util.List<java.lang.String>); core/java/android/content/pm/IShortcutService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -76,4 +76,6 @@ interface IShortcutService { void removeLongLivedShortcuts(String packageName, in List shortcutIds, int userId); ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId); void pushDynamicShortcut(String packageName, in ShortcutInfo shortcut, int userId); } No newline at end of file core/java/android/content/pm/ShortcutInfo.java +2 −2 Original line number Diff line number Diff line Loading @@ -1726,11 +1726,11 @@ public final class ShortcutInfo implements Parcelable { } /** * @return true if pinned but neither static nor dynamic. * @return true if pinned or cached, but neither static nor dynamic. * @hide */ public boolean isFloating() { return isPinned() && !(isDynamic() || isManifestShortcut()); return (isPinned() || isCached()) && !(isDynamic() || isManifestShortcut()); } /** @hide */ Loading core/java/android/content/pm/ShortcutManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.Notification; import android.app.usage.UsageStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; Loading Loading @@ -741,4 +742,33 @@ public class ShortcutManager { throw e.rethrowFromSystemServer(); } } /** * Publish a single dynamic shortcut. If there are already dynamic or pinned shortcuts with the * same ID, each mutable shortcut is updated. * * <p>This method is useful when posting notifications which are tagged with shortcut IDs; In * order to make sure shortcuts exist and are up-to-date, without the need to explicitly handle * the shortcut count limit. * @see android.app.NotificationManager#notify(int, Notification) * @see Notification.Builder#setShortcutId(String) * * <p>If {@link #getMaxShortcutCountPerActivity()} is already reached, an existing shortcut with * the lowest rank will be removed to add space for the new shortcut. * * <p>If the rank of the shortcut is not explicitly set, it will be set to zero, and shortcut * will be added to the top of the list. * * @throws IllegalArgumentException if trying to update an immutable shortcut. * * @throws IllegalStateException when the user is locked. */ public void pushDynamicShortcut(@NonNull ShortcutInfo shortcut) { try { mService.pushDynamicShortcut(mContext.getPackageName(), shortcut, injectMyUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } services/core/java/com/android/server/pm/ShortcutPackage.java +54 −0 Original line number Diff line number Diff line Loading @@ -309,6 +309,60 @@ class ShortcutPackage extends ShortcutPackageItem { forceReplaceShortcutInner(newShortcut); } /** * Push a shortcut. If the max number of dynamic shortcuts is already reached, remove the * shortcut with the lowest rank before adding the new shortcut. */ public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut) { Preconditions.checkArgument(newShortcut.isEnabled(), "pushDynamicShortcuts() cannot publish disabled shortcuts"); newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId()); boolean wasPinned = false; if (oldShortcut == null) { final ShortcutService service = mShortcutUser.mService; final int maxShortcuts = service.getMaxActivityShortcuts(); final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all = sortShortcutsToActivities(); final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity()); if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) { // Max has reached. Delete the shortcut with lowest rank. // Sort by isManifestShortcut() and getRank(). Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator); final ShortcutInfo shortcut = activityShortcuts.get(maxShortcuts - 1); if (shortcut.isManifestShortcut()) { // All shortcuts are manifest shortcuts and cannot be removed. Slog.e(TAG, "Failed to remove manifest shortcut while pushing dynamic shortcut " + newShortcut.getId()); return false; } deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true); } } else { // It's an update case. // Make sure the target is updatable. (i.e. should be mutable.) oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false); wasPinned = oldShortcut.isPinned(); } // If it was originally pinned, the new one should be pinned too. if (wasPinned) { newShortcut.addFlags(ShortcutInfo.FLAG_PINNED); } forceReplaceShortcutInner(newShortcut); return true; } /** * Remove all shortcuts that aren't pinned, cached nor dynamic. */ Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -12466,6 +12466,7 @@ package android.content.pm { method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(int); method public boolean isRateLimitingActive(); method public boolean isRequestPinShortcutSupported(); method public void pushDynamicShortcut(@NonNull android.content.pm.ShortcutInfo); method public void removeAllDynamicShortcuts(); method public void removeDynamicShortcuts(@NonNull java.util.List<java.lang.String>); method public void removeLongLivedShortcuts(@NonNull java.util.List<java.lang.String>);
core/java/android/content/pm/IShortcutService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -76,4 +76,6 @@ interface IShortcutService { void removeLongLivedShortcuts(String packageName, in List shortcutIds, int userId); ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId); void pushDynamicShortcut(String packageName, in ShortcutInfo shortcut, int userId); } No newline at end of file
core/java/android/content/pm/ShortcutInfo.java +2 −2 Original line number Diff line number Diff line Loading @@ -1726,11 +1726,11 @@ public final class ShortcutInfo implements Parcelable { } /** * @return true if pinned but neither static nor dynamic. * @return true if pinned or cached, but neither static nor dynamic. * @hide */ public boolean isFloating() { return isPinned() && !(isDynamic() || isManifestShortcut()); return (isPinned() || isCached()) && !(isDynamic() || isManifestShortcut()); } /** @hide */ Loading
core/java/android/content/pm/ShortcutManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.Notification; import android.app.usage.UsageStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; Loading Loading @@ -741,4 +742,33 @@ public class ShortcutManager { throw e.rethrowFromSystemServer(); } } /** * Publish a single dynamic shortcut. If there are already dynamic or pinned shortcuts with the * same ID, each mutable shortcut is updated. * * <p>This method is useful when posting notifications which are tagged with shortcut IDs; In * order to make sure shortcuts exist and are up-to-date, without the need to explicitly handle * the shortcut count limit. * @see android.app.NotificationManager#notify(int, Notification) * @see Notification.Builder#setShortcutId(String) * * <p>If {@link #getMaxShortcutCountPerActivity()} is already reached, an existing shortcut with * the lowest rank will be removed to add space for the new shortcut. * * <p>If the rank of the shortcut is not explicitly set, it will be set to zero, and shortcut * will be added to the top of the list. * * @throws IllegalArgumentException if trying to update an immutable shortcut. * * @throws IllegalStateException when the user is locked. */ public void pushDynamicShortcut(@NonNull ShortcutInfo shortcut) { try { mService.pushDynamicShortcut(mContext.getPackageName(), shortcut, injectMyUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
services/core/java/com/android/server/pm/ShortcutPackage.java +54 −0 Original line number Diff line number Diff line Loading @@ -309,6 +309,60 @@ class ShortcutPackage extends ShortcutPackageItem { forceReplaceShortcutInner(newShortcut); } /** * Push a shortcut. If the max number of dynamic shortcuts is already reached, remove the * shortcut with the lowest rank before adding the new shortcut. */ public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut) { Preconditions.checkArgument(newShortcut.isEnabled(), "pushDynamicShortcuts() cannot publish disabled shortcuts"); newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId()); boolean wasPinned = false; if (oldShortcut == null) { final ShortcutService service = mShortcutUser.mService; final int maxShortcuts = service.getMaxActivityShortcuts(); final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all = sortShortcutsToActivities(); final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity()); if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) { // Max has reached. Delete the shortcut with lowest rank. // Sort by isManifestShortcut() and getRank(). Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator); final ShortcutInfo shortcut = activityShortcuts.get(maxShortcuts - 1); if (shortcut.isManifestShortcut()) { // All shortcuts are manifest shortcuts and cannot be removed. Slog.e(TAG, "Failed to remove manifest shortcut while pushing dynamic shortcut " + newShortcut.getId()); return false; } deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true); } } else { // It's an update case. // Make sure the target is updatable. (i.e. should be mutable.) oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false); wasPinned = oldShortcut.isPinned(); } // If it was originally pinned, the new one should be pinned too. if (wasPinned) { newShortcut.addFlags(ShortcutInfo.FLAG_PINNED); } forceReplaceShortcutInner(newShortcut); return true; } /** * Remove all shortcuts that aren't pinned, cached nor dynamic. */ Loading