Loading core/api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -13385,6 +13385,7 @@ package android.content.pm { method public boolean isDynamic(); method public boolean isEnabled(); method public boolean isImmutable(); method public boolean isIncludedIn(int); method public boolean isPinned(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR; Loading @@ -13397,6 +13398,7 @@ package android.content.pm { field public static final int DISABLED_REASON_UNKNOWN = 3; // 0x3 field public static final int DISABLED_REASON_VERSION_LOWER = 100; // 0x64 field public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation"; field public static final int SURFACE_LAUNCHER = 1; // 0x1 } public static class ShortcutInfo.Builder { Loading @@ -13405,6 +13407,7 @@ package android.content.pm { method @NonNull public android.content.pm.ShortcutInfo.Builder setActivity(@NonNull android.content.ComponentName); method @NonNull public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>); method @NonNull public android.content.pm.ShortcutInfo.Builder setDisabledMessage(@NonNull CharSequence); method @NonNull public android.content.pm.ShortcutInfo.Builder setExcludedFromSurfaces(int); method @NonNull public android.content.pm.ShortcutInfo.Builder setExtras(@NonNull android.os.PersistableBundle); method @NonNull public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); method @NonNull public android.content.pm.ShortcutInfo.Builder setIntent(@NonNull android.content.Intent); core/java/android/content/pm/ShortcutInfo.java +44 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,16 @@ public final class ShortcutInfo implements Parcelable { return disabledReason >= DISABLED_REASON_RESTORE_ISSUE_START; } /** @hide */ @IntDef(flag = true, value = {SURFACE_LAUNCHER}) @Retention(RetentionPolicy.SOURCE) public @interface Surface {} /** * Indicates system surfaces managed by a launcher app. e.g. Long-Press Menu. */ public static final int SURFACE_LAUNCHER = 1 << 0; /** * Shortcut category for messaging related actions, such as chat. */ Loading Loading @@ -451,6 +461,8 @@ public final class ShortcutInfo implements Parcelable { @Nullable private String mStartingThemeResName; private int mExcludedSurfaces; private ShortcutInfo(Builder b) { mUserId = b.mContext.getUserId(); Loading @@ -474,6 +486,7 @@ public final class ShortcutInfo implements Parcelable { if (b.mIsLongLived) { setLongLived(); } mExcludedSurfaces = b.mExcludedSurfaces; mRank = b.mRank; mExtras = b.mExtras; mLocusId = b.mLocusId; Loading Loading @@ -587,6 +600,7 @@ public final class ShortcutInfo implements Parcelable { mLastChangedTimestamp = source.mLastChangedTimestamp; mDisabledReason = source.mDisabledReason; mLocusId = source.mLocusId; mExcludedSurfaces = source.mExcludedSurfaces; // Just always keep it since it's cheep. mIconResId = source.mIconResId; Loading Loading @@ -1025,6 +1039,8 @@ public final class ShortcutInfo implements Parcelable { private int mStartingThemeResId; private int mExcludedSurfaces; /** * Old style constructor. * @hide Loading Loading @@ -1384,6 +1400,22 @@ public final class ShortcutInfo implements Parcelable { return this; } /** * Sets which surfaces a shortcut will be excluded from. * * If the shortcut is set to be excluded from {@link #SURFACE_LAUNCHER}, shortcuts will be * excluded from the search result of {@link android.content.pm.LauncherApps#getShortcuts( * android.content.pm.LauncherApps.ShortcutQuery, UserHandle)} nor * {@link android.content.pm.ShortcutManager#getShortcuts(int)}. This generally means the * shortcut would not be displayed by a launcher app (e.g. in Long-Press menu), while * remain visible in other surfaces such as assistant or on-device-intelligence. */ @NonNull public Builder setExcludedFromSurfaces(final int surfaces) { mExcludedSurfaces = surfaces; return this; } /** * Creates a {@link ShortcutInfo} instance. */ Loading Loading @@ -2137,6 +2169,13 @@ public final class ShortcutInfo implements Parcelable { mCategories = cloneCategories(categories); } /** * Return true if the shortcut is included in specified surface. */ public boolean isIncludedIn(@Surface int surface) { return (mExcludedSurfaces & surface) == 0; } private ShortcutInfo(Parcel source) { final ClassLoader cl = getClass().getClassLoader(); Loading Loading @@ -2185,6 +2224,7 @@ public final class ShortcutInfo implements Parcelable { mLocusId = source.readParcelable(cl); mIconUri = source.readString8(); mStartingThemeResName = source.readString8(); mExcludedSurfaces = source.readInt(); } @Override Loading Loading @@ -2237,6 +2277,7 @@ public final class ShortcutInfo implements Parcelable { dest.writeParcelable(mLocusId, flags); dest.writeString8(mIconUri); dest.writeString8(mStartingThemeResName); dest.writeInt(mExcludedSurfaces); } public static final @NonNull Creator<ShortcutInfo> CREATOR = Loading Loading @@ -2346,6 +2387,9 @@ public final class ShortcutInfo implements Parcelable { if (isLongLived()) { sb.append("Liv"); } if (!isIncludedIn(SURFACE_LAUNCHER)) { sb.append("Hid-L"); } sb.append("]"); addIndentOrComma(sb, indent); Loading services/core/java/com/android/server/pm/ShortcutPackage.java +49 −28 Original line number Diff line number Diff line Loading @@ -96,8 +96,6 @@ import java.util.stream.Collectors; /** * Package information used by {@link ShortcutService}. * User information used by {@link ShortcutService}. * * All methods should be guarded by {@code #mShortcutUser.mService.mLock}. */ class ShortcutPackage extends ShortcutPackageItem { private static final String TAG = ShortcutService.TAG; Loading Loading @@ -162,10 +160,18 @@ class ShortcutPackage extends ShortcutPackageItem { private final Executor mExecutor; /** * An temp in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs. * An in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs. */ @GuardedBy("mLock") final ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>(); /** * A temporary copy of shortcuts that are to be cleared once persisted into AppSearch, keyed on * IDs. */ @GuardedBy("mLock") private ArrayMap<String, ShortcutInfo> mTransientShortcuts = new ArrayMap<>(0); /** * All the share targets from the package */ Loading Loading @@ -330,6 +336,15 @@ class ShortcutPackage extends ShortcutPackageItem { } } public void ensureAllShortcutsVisibleToLauncher(@NonNull List<ShortcutInfo> shortcuts) { for (ShortcutInfo shortcut : shortcuts) { if (!shortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) { throw new IllegalArgumentException("Shortcut ID=" + shortcut.getId() + " is hidden from launcher and may not be manipulated via APIs"); } } } /** * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible. */ Loading Loading @@ -384,7 +399,15 @@ class ShortcutPackage extends ShortcutPackageItem { & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL)); } if (!newShortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) { if (isAppSearchEnabled()) { synchronized (mLock) { mTransientShortcuts.put(newShortcut.getId(), newShortcut); } } } else { forceReplaceShortcutInner(newShortcut); } return oldShortcut != null; } Loading Loading @@ -444,7 +467,15 @@ class ShortcutPackage extends ShortcutPackageItem { & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL)); } if (!newShortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) { if (isAppSearchEnabled()) { synchronized (mLock) { mTransientShortcuts.put(newShortcut.getId(), newShortcut); } } } else { forceReplaceShortcutInner(newShortcut); } if (isAppSearchEnabled()) { runAsSystem(() -> fromAppSearch().thenAccept(session -> session.reportUsage(new ReportUsageRequest.Builder( Loading Loading @@ -669,7 +700,6 @@ class ShortcutPackage extends ShortcutPackageItem { forEachShortcutMutate(si -> { if (!pinnedShortcuts.contains(si.getId()) && si.isPinned()) { si.clearFlags(ShortcutInfo.FLAG_PINNED); return; } }); Loading Loading @@ -1704,8 +1734,15 @@ class ShortcutPackage extends ShortcutPackageItem { for (int j = 0; j < shareTargetSize; j++) { mShareTargets.get(j).saveToXml(out); } saveShortcutsAsync(mShortcuts.values().stream().filter(ShortcutInfo::usesQuota) .collect(Collectors.toList())); synchronized (mLock) { final Map<String, ShortcutInfo> copy = mShortcuts; if (!mTransientShortcuts.isEmpty()) { copy.putAll(mTransientShortcuts); mTransientShortcuts.clear(); } saveShortcutsAsync(copy.values().stream().filter(ShortcutInfo::usesQuota).collect( Collectors.toList())); } } out.endTag(null, TAG_ROOT); Loading Loading @@ -2233,26 +2270,6 @@ class ShortcutPackage extends ShortcutPackageItem { } } void updateVisibility(String packageName, byte[] certificate, boolean visible) { if (!isAppSearchEnabled()) { return; } if (visible) { mPackageIdentifiers.put(packageName, new PackageIdentifier(packageName, certificate)); } else { mPackageIdentifiers.remove(packageName); } synchronized (mLock) { mIsAppSearchSchemaUpToDate = false; } final long callingIdentity = Binder.clearCallingIdentity(); try { fromAppSearch(); } finally { Binder.restoreCallingIdentity(callingIdentity); } } void mutateShortcut(@NonNull final String id, @Nullable final ShortcutInfo shortcut, @NonNull final Consumer<ShortcutInfo> transform) { Objects.requireNonNull(id); Loading Loading @@ -2358,6 +2375,7 @@ class ShortcutPackage extends ShortcutPackageItem { .addFilterSchemas(AppSearchShortcutInfo.SCHEMA_TYPE) .addFilterNamespaces(getPackageName()) .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY) .setResultCountPerPage(mShortcutUser.mService.getMaxActivityShortcuts()) .build(); } Loading Loading @@ -2451,6 +2469,9 @@ class ShortcutPackage extends ShortcutPackageItem { @VisibleForTesting void getTopShortcutsFromPersistence(AndroidFuture<List<ShortcutInfo>> cb) { if (!isAppSearchEnabled()) { cb.complete(null); } runAsSystem(() -> fromAppSearch().thenAccept(session -> { SearchResults res = session.search("", getSearchSpec()); res.getNextPage(mShortcutUser.mExecutor, results -> { Loading services/core/java/com/android/server/pm/ShortcutService.java +4 −0 Original line number Diff line number Diff line Loading @@ -2014,6 +2014,7 @@ public class ShortcutService extends IShortcutService.Stub { ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true); ps.ensureNoBitmapIconIfShortcutIsLongLived(newShortcuts); ps.ensureAllShortcutsVisibleToLauncher(newShortcuts); // For update, don't fill in the default activity. Having null activity means // "don't update the activity" here. Loading Loading @@ -2214,6 +2215,9 @@ public class ShortcutService extends IShortcutService.Stub { IntentSender resultIntent, int userId, AndroidFuture<String> ret) { Objects.requireNonNull(shortcut); Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled"); Preconditions.checkArgument( shortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER), "Shortcut excluded from launcher cannot be pinned"); ret.complete(String.valueOf(requestPinItem( packageName, userId, shortcut, null, null, resultIntent))); } Loading services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -1500,6 +1500,20 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); } /** * Make a hidden shortcut with an ID. */ protected ShortcutInfo makeShortcutExcludedFromLauncher(String id) { final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) .setActivity(new ComponentName(mClientContext.getPackageName(), "main")) .setShortLabel("Title-" + id) .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class)) .setExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER); final ShortcutInfo s = b.build(); s.setTimestamp(mInjectedCurrentTimeMillis); return s; } @Deprecated // Title was renamed to short label. protected ShortcutInfo makeShortcutWithTitle(String id, String title) { return makeShortcut( Loading Loading @@ -1889,6 +1903,18 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { assertEquals("Exception type different", expectedException, thrown.getClass()); } protected void assertThrown(@NonNull final Class<?> expectedException, @NonNull final Runnable fn) { Exception thrown = null; try { fn.run(); } catch (Exception e) { thrown = e; } assertNotNull("Exception was not thrown", thrown); assertEquals("Exception type different", expectedException, thrown.getClass()); } protected void assertBitmapDirectories(int userId, String... expectedDirectories) { final Set<String> expected = hashSet(set(expectedDirectories)); Loading Loading
core/api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -13385,6 +13385,7 @@ package android.content.pm { method public boolean isDynamic(); method public boolean isEnabled(); method public boolean isImmutable(); method public boolean isIncludedIn(int); method public boolean isPinned(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR; Loading @@ -13397,6 +13398,7 @@ package android.content.pm { field public static final int DISABLED_REASON_UNKNOWN = 3; // 0x3 field public static final int DISABLED_REASON_VERSION_LOWER = 100; // 0x64 field public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation"; field public static final int SURFACE_LAUNCHER = 1; // 0x1 } public static class ShortcutInfo.Builder { Loading @@ -13405,6 +13407,7 @@ package android.content.pm { method @NonNull public android.content.pm.ShortcutInfo.Builder setActivity(@NonNull android.content.ComponentName); method @NonNull public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>); method @NonNull public android.content.pm.ShortcutInfo.Builder setDisabledMessage(@NonNull CharSequence); method @NonNull public android.content.pm.ShortcutInfo.Builder setExcludedFromSurfaces(int); method @NonNull public android.content.pm.ShortcutInfo.Builder setExtras(@NonNull android.os.PersistableBundle); method @NonNull public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); method @NonNull public android.content.pm.ShortcutInfo.Builder setIntent(@NonNull android.content.Intent);
core/java/android/content/pm/ShortcutInfo.java +44 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,16 @@ public final class ShortcutInfo implements Parcelable { return disabledReason >= DISABLED_REASON_RESTORE_ISSUE_START; } /** @hide */ @IntDef(flag = true, value = {SURFACE_LAUNCHER}) @Retention(RetentionPolicy.SOURCE) public @interface Surface {} /** * Indicates system surfaces managed by a launcher app. e.g. Long-Press Menu. */ public static final int SURFACE_LAUNCHER = 1 << 0; /** * Shortcut category for messaging related actions, such as chat. */ Loading Loading @@ -451,6 +461,8 @@ public final class ShortcutInfo implements Parcelable { @Nullable private String mStartingThemeResName; private int mExcludedSurfaces; private ShortcutInfo(Builder b) { mUserId = b.mContext.getUserId(); Loading @@ -474,6 +486,7 @@ public final class ShortcutInfo implements Parcelable { if (b.mIsLongLived) { setLongLived(); } mExcludedSurfaces = b.mExcludedSurfaces; mRank = b.mRank; mExtras = b.mExtras; mLocusId = b.mLocusId; Loading Loading @@ -587,6 +600,7 @@ public final class ShortcutInfo implements Parcelable { mLastChangedTimestamp = source.mLastChangedTimestamp; mDisabledReason = source.mDisabledReason; mLocusId = source.mLocusId; mExcludedSurfaces = source.mExcludedSurfaces; // Just always keep it since it's cheep. mIconResId = source.mIconResId; Loading Loading @@ -1025,6 +1039,8 @@ public final class ShortcutInfo implements Parcelable { private int mStartingThemeResId; private int mExcludedSurfaces; /** * Old style constructor. * @hide Loading Loading @@ -1384,6 +1400,22 @@ public final class ShortcutInfo implements Parcelable { return this; } /** * Sets which surfaces a shortcut will be excluded from. * * If the shortcut is set to be excluded from {@link #SURFACE_LAUNCHER}, shortcuts will be * excluded from the search result of {@link android.content.pm.LauncherApps#getShortcuts( * android.content.pm.LauncherApps.ShortcutQuery, UserHandle)} nor * {@link android.content.pm.ShortcutManager#getShortcuts(int)}. This generally means the * shortcut would not be displayed by a launcher app (e.g. in Long-Press menu), while * remain visible in other surfaces such as assistant or on-device-intelligence. */ @NonNull public Builder setExcludedFromSurfaces(final int surfaces) { mExcludedSurfaces = surfaces; return this; } /** * Creates a {@link ShortcutInfo} instance. */ Loading Loading @@ -2137,6 +2169,13 @@ public final class ShortcutInfo implements Parcelable { mCategories = cloneCategories(categories); } /** * Return true if the shortcut is included in specified surface. */ public boolean isIncludedIn(@Surface int surface) { return (mExcludedSurfaces & surface) == 0; } private ShortcutInfo(Parcel source) { final ClassLoader cl = getClass().getClassLoader(); Loading Loading @@ -2185,6 +2224,7 @@ public final class ShortcutInfo implements Parcelable { mLocusId = source.readParcelable(cl); mIconUri = source.readString8(); mStartingThemeResName = source.readString8(); mExcludedSurfaces = source.readInt(); } @Override Loading Loading @@ -2237,6 +2277,7 @@ public final class ShortcutInfo implements Parcelable { dest.writeParcelable(mLocusId, flags); dest.writeString8(mIconUri); dest.writeString8(mStartingThemeResName); dest.writeInt(mExcludedSurfaces); } public static final @NonNull Creator<ShortcutInfo> CREATOR = Loading Loading @@ -2346,6 +2387,9 @@ public final class ShortcutInfo implements Parcelable { if (isLongLived()) { sb.append("Liv"); } if (!isIncludedIn(SURFACE_LAUNCHER)) { sb.append("Hid-L"); } sb.append("]"); addIndentOrComma(sb, indent); Loading
services/core/java/com/android/server/pm/ShortcutPackage.java +49 −28 Original line number Diff line number Diff line Loading @@ -96,8 +96,6 @@ import java.util.stream.Collectors; /** * Package information used by {@link ShortcutService}. * User information used by {@link ShortcutService}. * * All methods should be guarded by {@code #mShortcutUser.mService.mLock}. */ class ShortcutPackage extends ShortcutPackageItem { private static final String TAG = ShortcutService.TAG; Loading Loading @@ -162,10 +160,18 @@ class ShortcutPackage extends ShortcutPackageItem { private final Executor mExecutor; /** * An temp in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs. * An in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs. */ @GuardedBy("mLock") final ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>(); /** * A temporary copy of shortcuts that are to be cleared once persisted into AppSearch, keyed on * IDs. */ @GuardedBy("mLock") private ArrayMap<String, ShortcutInfo> mTransientShortcuts = new ArrayMap<>(0); /** * All the share targets from the package */ Loading Loading @@ -330,6 +336,15 @@ class ShortcutPackage extends ShortcutPackageItem { } } public void ensureAllShortcutsVisibleToLauncher(@NonNull List<ShortcutInfo> shortcuts) { for (ShortcutInfo shortcut : shortcuts) { if (!shortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) { throw new IllegalArgumentException("Shortcut ID=" + shortcut.getId() + " is hidden from launcher and may not be manipulated via APIs"); } } } /** * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible. */ Loading Loading @@ -384,7 +399,15 @@ class ShortcutPackage extends ShortcutPackageItem { & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL)); } if (!newShortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) { if (isAppSearchEnabled()) { synchronized (mLock) { mTransientShortcuts.put(newShortcut.getId(), newShortcut); } } } else { forceReplaceShortcutInner(newShortcut); } return oldShortcut != null; } Loading Loading @@ -444,7 +467,15 @@ class ShortcutPackage extends ShortcutPackageItem { & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL)); } if (!newShortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) { if (isAppSearchEnabled()) { synchronized (mLock) { mTransientShortcuts.put(newShortcut.getId(), newShortcut); } } } else { forceReplaceShortcutInner(newShortcut); } if (isAppSearchEnabled()) { runAsSystem(() -> fromAppSearch().thenAccept(session -> session.reportUsage(new ReportUsageRequest.Builder( Loading Loading @@ -669,7 +700,6 @@ class ShortcutPackage extends ShortcutPackageItem { forEachShortcutMutate(si -> { if (!pinnedShortcuts.contains(si.getId()) && si.isPinned()) { si.clearFlags(ShortcutInfo.FLAG_PINNED); return; } }); Loading Loading @@ -1704,8 +1734,15 @@ class ShortcutPackage extends ShortcutPackageItem { for (int j = 0; j < shareTargetSize; j++) { mShareTargets.get(j).saveToXml(out); } saveShortcutsAsync(mShortcuts.values().stream().filter(ShortcutInfo::usesQuota) .collect(Collectors.toList())); synchronized (mLock) { final Map<String, ShortcutInfo> copy = mShortcuts; if (!mTransientShortcuts.isEmpty()) { copy.putAll(mTransientShortcuts); mTransientShortcuts.clear(); } saveShortcutsAsync(copy.values().stream().filter(ShortcutInfo::usesQuota).collect( Collectors.toList())); } } out.endTag(null, TAG_ROOT); Loading Loading @@ -2233,26 +2270,6 @@ class ShortcutPackage extends ShortcutPackageItem { } } void updateVisibility(String packageName, byte[] certificate, boolean visible) { if (!isAppSearchEnabled()) { return; } if (visible) { mPackageIdentifiers.put(packageName, new PackageIdentifier(packageName, certificate)); } else { mPackageIdentifiers.remove(packageName); } synchronized (mLock) { mIsAppSearchSchemaUpToDate = false; } final long callingIdentity = Binder.clearCallingIdentity(); try { fromAppSearch(); } finally { Binder.restoreCallingIdentity(callingIdentity); } } void mutateShortcut(@NonNull final String id, @Nullable final ShortcutInfo shortcut, @NonNull final Consumer<ShortcutInfo> transform) { Objects.requireNonNull(id); Loading Loading @@ -2358,6 +2375,7 @@ class ShortcutPackage extends ShortcutPackageItem { .addFilterSchemas(AppSearchShortcutInfo.SCHEMA_TYPE) .addFilterNamespaces(getPackageName()) .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY) .setResultCountPerPage(mShortcutUser.mService.getMaxActivityShortcuts()) .build(); } Loading Loading @@ -2451,6 +2469,9 @@ class ShortcutPackage extends ShortcutPackageItem { @VisibleForTesting void getTopShortcutsFromPersistence(AndroidFuture<List<ShortcutInfo>> cb) { if (!isAppSearchEnabled()) { cb.complete(null); } runAsSystem(() -> fromAppSearch().thenAccept(session -> { SearchResults res = session.search("", getSearchSpec()); res.getNextPage(mShortcutUser.mExecutor, results -> { Loading
services/core/java/com/android/server/pm/ShortcutService.java +4 −0 Original line number Diff line number Diff line Loading @@ -2014,6 +2014,7 @@ public class ShortcutService extends IShortcutService.Stub { ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true); ps.ensureNoBitmapIconIfShortcutIsLongLived(newShortcuts); ps.ensureAllShortcutsVisibleToLauncher(newShortcuts); // For update, don't fill in the default activity. Having null activity means // "don't update the activity" here. Loading Loading @@ -2214,6 +2215,9 @@ public class ShortcutService extends IShortcutService.Stub { IntentSender resultIntent, int userId, AndroidFuture<String> ret) { Objects.requireNonNull(shortcut); Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled"); Preconditions.checkArgument( shortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER), "Shortcut excluded from launcher cannot be pinned"); ret.complete(String.valueOf(requestPinItem( packageName, userId, shortcut, null, null, resultIntent))); } Loading
services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -1500,6 +1500,20 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0); } /** * Make a hidden shortcut with an ID. */ protected ShortcutInfo makeShortcutExcludedFromLauncher(String id) { final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id) .setActivity(new ComponentName(mClientContext.getPackageName(), "main")) .setShortLabel("Title-" + id) .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class)) .setExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER); final ShortcutInfo s = b.build(); s.setTimestamp(mInjectedCurrentTimeMillis); return s; } @Deprecated // Title was renamed to short label. protected ShortcutInfo makeShortcutWithTitle(String id, String title) { return makeShortcut( Loading Loading @@ -1889,6 +1903,18 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { assertEquals("Exception type different", expectedException, thrown.getClass()); } protected void assertThrown(@NonNull final Class<?> expectedException, @NonNull final Runnable fn) { Exception thrown = null; try { fn.run(); } catch (Exception e) { thrown = e; } assertNotNull("Exception was not thrown", thrown); assertEquals("Exception type different", expectedException, thrown.getClass()); } protected void assertBitmapDirectories(int userId, String... expectedDirectories) { final Set<String> expected = hashSet(set(expectedDirectories)); Loading