diff options
4 files changed, 90 insertions, 4 deletions
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index 2b76ae20b80b..d0c63979d833 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -23,7 +23,6 @@ import android.app.TaskStackBuilder; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; @@ -96,6 +95,9 @@ public final class ShortcutInfo implements Parcelable { public static final int FLAG_ADAPTIVE_BITMAP = 1 << 9; /** @hide */ + public static final int FLAG_RETURNED_BY_SERVICE = 1 << 10; + + /** @hide */ @IntDef(flag = true, value = { FLAG_DYNAMIC, @@ -108,6 +110,7 @@ public final class ShortcutInfo implements Parcelable { FLAG_STRINGS_RESOLVED, FLAG_IMMUTABLE, FLAG_ADAPTIVE_BITMAP, + FLAG_RETURNED_BY_SERVICE }) @Retention(RetentionPolicy.SOURCE) public @interface ShortcutFlags {} @@ -1343,6 +1346,16 @@ public final class ShortcutInfo implements Parcelable { return (mFlags & flags) == flags; } + /** @hide */ + public boolean isReturnedByServer() { + return hasFlags(FLAG_RETURNED_BY_SERVICE); + } + + /** @hide */ + public void setReturnedByServer() { + addFlags(FLAG_RETURNED_BY_SERVICE); + } + /** Return whether a shortcut is dynamic. */ public boolean isDynamic() { return hasFlags(FLAG_DYNAMIC); @@ -1450,7 +1463,7 @@ public final class ShortcutInfo implements Parcelable { /** * Return whether a shortcut's icon is adaptive bitmap following design guideline - * defined in {@link AdaptiveIconDrawable}. + * defined in {@link android.graphics.drawable.AdaptiveIconDrawable}. * * @hide internal/unit tests only */ @@ -1776,6 +1789,9 @@ public final class ShortcutInfo implements Parcelable { if (hasStringResourcesResolved()) { sb.append("Sr"); } + if (isReturnedByServer()) { + sb.append("V"); + } sb.append("]"); sb.append(", packageName="); diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index a7c09b50ffa9..e3e0cc560d1f 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -618,6 +618,10 @@ public class ShortcutManager { /** * Return all dynamic shortcuts from the caller app. * + * <p>This API is intended to be used for examining what shortcuts are currently published. + * Re-publishing returned {@link ShortcutInfo}s via APIs such as + * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons. + * * @throws IllegalStateException when the user is locked. */ @NonNull @@ -633,6 +637,10 @@ public class ShortcutManager { /** * Return all static (manifest) shortcuts from the caller app. * + * <p>This API is intended to be used for examining what shortcuts are currently published. + * Re-publishing returned {@link ShortcutInfo}s via APIs such as + * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons. + * * @throws IllegalStateException when the user is locked. */ @NonNull @@ -697,6 +705,10 @@ public class ShortcutManager { /** * Return all pinned shortcuts from the caller app. * + * <p>This API is intended to be used for examining what shortcuts are currently published. + * Re-publishing returned {@link ShortcutInfo}s via APIs such as + * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons. + * * @throws IllegalStateException when the user is locked. */ @NonNull diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index bed8f1a78649..7f0528a49098 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -1611,6 +1611,11 @@ public class ShortcutService extends IShortcutService.Stub { */ private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate, boolean forPinRequest) { + if (shortcut.isReturnedByServer()) { + Log.w(TAG, + "Re-publishing ShortcutInfo returned by server is not supported." + + " Some information such as icon may lost from shortcut."); + } Preconditions.checkNotNull(shortcut, "Null shortcut detected"); if (shortcut.getActivity() != null) { Preconditions.checkState( @@ -1670,6 +1675,13 @@ public class ShortcutService extends IShortcutService.Stub { } } + private List<ShortcutInfo> setReturnedByServer(List<ShortcutInfo> shortcuts) { + for (int i = shortcuts.size() - 1; i >= 0; i--) { + shortcuts.get(i).setReturnedByServer(); + } + return shortcuts; + } + // === APIs === @Override @@ -2049,7 +2061,7 @@ public class ShortcutService extends IShortcutService.Stub { final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); ps.findAll(ret, query, cloneFlags); - return new ParceledListSlice<>(ret); + return new ParceledListSlice<>(setReturnedByServer(ret)); } @Override @@ -2406,7 +2418,7 @@ public class ShortcutService extends IShortcutService.Stub { }); } } - return ret; + return setReturnedByServer(ret); } private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage, diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index 4c7bf4df0143..f4944f9ee83d 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -7399,4 +7399,50 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { "s21", "s22"); }); } + + public void testReturnedByServer() { + // Package 1 updated, with manifest shortcuts. + addManifestShortcutResource( + new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()), + R.xml.shortcut_1); + updatePackageVersion(CALLING_PACKAGE_1, 1); + mService.mPackageMonitor.onReceive(getTestContext(), + genPackageAddIntent(CALLING_PACKAGE_1, USER_0)); + + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertWith(mManager.getManifestShortcuts()) + .haveIds("ms1") + .forAllShortcuts(si -> assertTrue(si.isReturnedByServer())); + + assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1")))); + + assertWith(mManager.getDynamicShortcuts()) + .haveIds("s1") + .forAllShortcuts(si -> assertTrue(si.isReturnedByServer())); + }); + + // Pin them. + runWithCaller(LAUNCHER_1, USER_0, () -> { + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, + list("ms1", "s1"), getCallingUser()); + assertWith(getShortcutAsLauncher(USER_0)) + .haveIds("ms1", "s1") + .forAllShortcuts(si -> assertTrue(si.isReturnedByServer())); + }); + + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertWith(mManager.getPinnedShortcuts()) + .haveIds("ms1", "s1") + .forAllShortcuts(si -> assertTrue(si.isReturnedByServer())); + }); + + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + // This shows a warning log, but should still work. + assertTrue(mManager.setDynamicShortcuts(mManager.getDynamicShortcuts())); + + assertWith(mManager.getDynamicShortcuts()) + .haveIds("s1") + .forAllShortcuts(si -> assertTrue(si.isReturnedByServer())); + }); + } } |