Adds CACHED shortcuts and methods to retrieve and remove

Adds a new flag to ShortcutInfo to mark it as cached. Also adds new
APIs in ShortcutManager to remove or retrieve a cached shortcut.

Bug: 148084870
Test: atest com.android.server.pm.ShortcutManagerTest1 \
            com.android.server.pm.ShortcutManagerTest2 \
            com.android.server.pm.ShortcutManagerTest3 \
            com.android.server.pm.ShortcutManagerTest4 \
            com.android.server.pm.ShortcutManagerTest5 \
            com.android.server.pm.ShortcutManagerTest6 \
            com.android.server.pm.ShortcutManagerTest7 \
            com.android.server.pm.ShortcutManagerTest8 \
            com.android.server.pm.ShortcutManagerTest9 \
            com.android.server.pm.ShortcutManagerTest10
Change-Id: I859b416ccd4228eec10a436550ff98866a62af66
This commit is contained in:
Mehdi Alizadeh
2020-01-21 17:26:24 -08:00
parent 879bc4ae15
commit 505fb76065
8 changed files with 395 additions and 16 deletions

View File

@@ -11672,6 +11672,7 @@ package android.content.pm {
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(@Nullable java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
field public static final int FLAG_MATCH_CACHED = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -12365,6 +12366,7 @@ package android.content.pm {
method @Nullable public CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
method public boolean isCached();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -12414,14 +12416,20 @@ package android.content.pm {
method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getManifestShortcuts();
method public int getMaxShortcutCountPerActivity();
method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(int);
method public boolean isRateLimitingActive();
method public boolean isRequestPinShortcutSupported();
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>);
method public void reportShortcutUsed(String);
method public boolean requestPinShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.content.IntentSender);
method public boolean setDynamicShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
method public boolean updateShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
field public static final int FLAG_MATCH_CACHED = 8; // 0x8
field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
field public static final int FLAG_MATCH_MANIFEST = 1; // 0x1
field public static final int FLAG_MATCH_PINNED = 4; // 0x4
}
public class Signature implements android.os.Parcelable {

View File

@@ -78,4 +78,8 @@ interface IShortcutService {
ParceledListSlice getShareTargets(String packageName, in IntentFilter filter, int userId);
boolean hasShareTargets(String packageName, String packageToCheck, int userId);
void removeLongLivedShortcuts(String packageName, in List shortcutIds, int userId);
ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId);
}

View File

@@ -324,6 +324,11 @@ public class LauncherApps {
*/
public static final int FLAG_MATCH_MANIFEST = 1 << 3;
/**
* Include cached shortcuts in the result.
*/
public static final int FLAG_MATCH_CACHED = 1 << 4;
/** @hide kept for unit tests */
@Deprecated
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
@@ -345,11 +350,11 @@ public class LauncherApps {
public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;
/**
* FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST
* FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_CACHED
* @hide
*/
public static final int FLAG_MATCH_ALL_KINDS =
FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST;
FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_CACHED;
/**
* FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_ALL_PINNED
@@ -386,8 +391,8 @@ public class LauncherApps {
FLAG_MATCH_DYNAMIC,
FLAG_MATCH_PINNED,
FLAG_MATCH_MANIFEST,
FLAG_MATCH_CACHED,
FLAG_GET_KEY_FIELDS_ONLY,
FLAG_MATCH_MANIFEST,
})
@Retention(RetentionPolicy.SOURCE)
public @interface QueryFlags {}
@@ -454,6 +459,7 @@ public class LauncherApps {
* <li>{@link #FLAG_MATCH_DYNAMIC}
* <li>{@link #FLAG_MATCH_PINNED}
* <li>{@link #FLAG_MATCH_MANIFEST}
* <li>{@link #FLAG_MATCH_CACHED}
* <li>{@link #FLAG_GET_KEY_FIELDS_ONLY}
* </ul>
*/

View File

@@ -119,6 +119,9 @@ public final class ShortcutInfo implements Parcelable {
/** @hide */
public static final int FLAG_LONG_LIVED = 1 << 13;
/** @hide */
public static final int FLAG_CACHED = 1 << 14;
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DYNAMIC,
@@ -135,6 +138,7 @@ public final class ShortcutInfo implements Parcelable {
FLAG_ICON_FILE_PENDING_SAVE,
FLAG_SHADOW,
FLAG_LONG_LIVED,
FLAG_CACHED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -1681,6 +1685,16 @@ public final class ShortcutInfo implements Parcelable {
addFlags(FLAG_LONG_LIVED);
}
/** @hide */
public void setCached() {
addFlags(FLAG_CACHED);
}
/** Return whether a shortcut is cached. */
public boolean isCached() {
return hasFlags(FLAG_CACHED);
}
/** Return whether a shortcut is dynamic. */
public boolean isDynamic() {
return hasFlags(FLAG_DYNAMIC);
@@ -1765,7 +1779,8 @@ public final class ShortcutInfo implements Parcelable {
/** @hide */
public boolean isAlive() {
return hasFlags(FLAG_PINNED) || hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_MANIFEST);
return hasFlags(FLAG_PINNED) || hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_MANIFEST)
|| hasFlags(FLAG_CACHED);
}
/** @hide */

View File

@@ -16,6 +16,7 @@
package android.content.pm;
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -40,6 +41,8 @@ import android.os.ServiceManager;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
@@ -62,6 +65,44 @@ import java.util.List;
public class ShortcutManager {
private static final String TAG = "ShortcutManager";
/**
* Include manifest shortcuts in the result.
*
* @see #getShortcuts(int)
*/
public static final int FLAG_MATCH_MANIFEST = 1 << 0;
/**
* Include dynamic shortcuts in the result.
*
* @see #getShortcuts(int)
*/
public static final int FLAG_MATCH_DYNAMIC = 1 << 1;
/**
* Include pinned shortcuts in the result.
*
* @see #getShortcuts(int)
*/
public static final int FLAG_MATCH_PINNED = 1 << 2;
/**
* Include cached shortcuts in the result.
*
* @see #getShortcuts(int)
*/
public static final int FLAG_MATCH_CACHED = 1 << 3;
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_MATCH_" }, value = {
FLAG_MATCH_MANIFEST,
FLAG_MATCH_DYNAMIC,
FLAG_MATCH_PINNED,
FLAG_MATCH_CACHED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutMatchFlags {}
private final Context mContext;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final IShortcutService mService;
@@ -118,8 +159,8 @@ public class ShortcutManager {
@NonNull
public List<ShortcutInfo> getDynamicShortcuts() {
try {
return mService.getDynamicShortcuts(mContext.getPackageName(), injectMyUserId())
.getList();
return mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_DYNAMIC,
injectMyUserId()).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -137,7 +178,35 @@ public class ShortcutManager {
@NonNull
public List<ShortcutInfo> getManifestShortcuts() {
try {
return mService.getManifestShortcuts(mContext.getPackageName(), injectMyUserId())
return mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_MANIFEST,
injectMyUserId()).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Returns {@link ShortcutInfo}s that match {@code matchFlags}.
*
* @param matchFlags result includes shortcuts matching this flags. Any combination of:
* <ul>
* <li>{@link #FLAG_MATCH_MANIFEST}
* <li>{@link #FLAG_MATCH_DYNAMIC}
* <li>{@link #FLAG_MATCH_PINNED}
* <li>{@link #FLAG_MATCH_CACHED}
* </ul>
* @return list of {@link ShortcutInfo}s that match the flag.
*
* <p>At least one of the {@code MATCH} flags should be set. Otherwise no shortcuts will be
* returned.
*
* @throws IllegalStateException when the user is locked.
*/
@NonNull
public List<ShortcutInfo> getShortcuts(@ShortcutMatchFlags int matchFlags) {
try {
return mService.getShortcuts(mContext.getPackageName(), matchFlags, injectMyUserId())
.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -193,6 +262,20 @@ public class ShortcutManager {
}
}
/**
* Delete long lived shortcuts by ID.
*
* @throws IllegalStateException when the user is locked.
*/
public void removeLongLivedShortcuts(@NonNull List<String> shortcutIds) {
try {
mService.removeLongLivedShortcuts(mContext.getPackageName(), shortcutIds,
injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return all pinned shortcuts from the caller app.
*
@@ -205,8 +288,8 @@ public class ShortcutManager {
@NonNull
public List<ShortcutInfo> getPinnedShortcuts() {
try {
return mService.getPinnedShortcuts(mContext.getPackageName(), injectMyUserId())
.getList();
return mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_PINNED,
injectMyUserId()).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -310,7 +310,7 @@ class ShortcutPackage extends ShortcutPackageItem {
}
/**
* Remove all shortcuts that aren't pinned nor dynamic.
* Remove all shortcuts that aren't pinned, cached nor dynamic.
*/
private void removeOrphans() {
ArrayList<String> removeList = null; // Lazily initialize.
@@ -356,10 +356,10 @@ class ShortcutPackage extends ShortcutPackageItem {
/**
* Remove a dynamic shortcut by ID. It'll be removed from the dynamic set, but if the shortcut
* is pinned, it'll remain as a pinned shortcut, and is still enabled.
* is pinned or cached, it'll remain as a pinned or cached shortcut, and is still enabled.
*
* @return true if it's actually removed because it wasn't pinned, or false if it's still
* pinned.
* @return true if it's removed, or false if it was not actually removed because it is either
* pinned or cached.
*/
public boolean deleteDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
final ShortcutInfo removed = deleteOrDisableWithId(
@@ -383,6 +383,24 @@ class ShortcutPackage extends ShortcutPackageItem {
return disabled == null;
}
/**
* Remove a long lived shortcut by ID. If the shortcut is pinned, it'll remain as a pinned
* shortcut, and is still enabled.
*
* @return true if it's actually removed because it wasn't pinned, or false if it's still
* pinned.
*/
public boolean deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
if (shortcut != null) {
shortcut.clearFlags(ShortcutInfo.FLAG_CACHED);
}
final ShortcutInfo removed = deleteOrDisableWithId(
shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
return removed == null;
}
/**
* Disable a dynamic shortcut by ID. It'll be removed from the dynamic set, but if the shortcut
* is pinned, it'll remain as a pinned shortcut but will be disabled.
@@ -419,7 +437,7 @@ class ShortcutPackage extends ShortcutPackageItem {
if (!overrideImmutable) {
ensureNotImmutable(oldShortcut, /*ignoreInvisible=*/ true);
}
if (oldShortcut.isPinned()) {
if (oldShortcut.isPinned() || oldShortcut.isCached()) {
oldShortcut.setRank(0);
oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
@@ -500,7 +518,7 @@ class ShortcutPackage extends ShortcutPackageItem {
}
});
// Lastly, remove the ones that are no longer pinned nor dynamic.
// Lastly, remove the ones that are no longer pinned, cached nor dynamic.
removeOrphans();
}
@@ -1328,6 +1346,10 @@ class ShortcutPackage extends ShortcutPackageItem {
// Don't adjust ranks for manifest shortcuts.
continue;
}
if (si.isCached() && !si.isDynamic()) {
// Don't adjust ranks for cached shortcuts that are not dynamic anymore.
continue;
}
// At this point, it must be dynamic.
if (!si.isDynamic()) {
s.wtf("Non-dynamic shortcut found.");
@@ -1869,7 +1891,7 @@ class ShortcutPackage extends ShortcutPackageItem {
// Verify each shortcut's status.
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned() || si.isCached())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is not manifest, dynamic or pinned.");

View File

@@ -2122,6 +2122,33 @@ public class ShortcutService extends IShortcutService.Stub {
verifyStates();
}
@Override
public void removeLongLivedShortcuts(String packageName, List shortcutIds,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
synchronized (mLock) {
throwIfUserLockedL(userId);
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
/*ignoreInvisible=*/ true);
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
ps.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
}
// We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
ps.adjustRanks();
}
packageShortcutsChanged(packageName, userId);
verifyStates();
}
@Override
public ParceledListSlice<ShortcutInfo> getDynamicShortcuts(String packageName,
@UserIdInt int userId) {
@@ -2164,6 +2191,31 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
@Override
public ParceledListSlice<ShortcutInfo> getShortcuts(String packageName,
@ShortcutManager.ShortcutMatchFlags int matchFlags, @UserIdInt int userId) {
verifyCaller(packageName, userId);
synchronized (mLock) {
throwIfUserLockedL(userId);
final boolean matchDynamic = (matchFlags & ShortcutManager.FLAG_MATCH_DYNAMIC) != 0;
final boolean matchPinned = (matchFlags & ShortcutManager.FLAG_MATCH_PINNED) != 0;
final boolean matchManifest = (matchFlags & ShortcutManager.FLAG_MATCH_MANIFEST) != 0;
final boolean matchCached = (matchFlags & ShortcutManager.FLAG_MATCH_CACHED) != 0;
final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0)
| (matchPinned ? ShortcutInfo.FLAG_PINNED : 0)
| (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
| (matchCached ? ShortcutInfo.FLAG_CACHED : 0);
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
(ShortcutInfo si) ->
si.isVisibleToPublisher() && (si.getFlags() & shortcutFlags) != 0);
}
}
@Override
public ParceledListSlice<ShortcutManager.ShareShortcutInfo> getShareTargets(String packageName,
IntentFilter filter, @UserIdInt int userId) {
@@ -2628,6 +2680,7 @@ public class ShortcutService extends IShortcutService.Stub {
final boolean matchDynamic = (queryFlags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0;
final boolean matchPinned = (queryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
final boolean matchManifest = (queryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
final boolean matchCached = (queryFlags & ShortcutQuery.FLAG_MATCH_CACHED) != 0;
final boolean canAccessAllShortcuts =
canSeeAnyPinnedShortcut(callingPackage, launcherUserId, callingPid, callingUid);
@@ -2659,6 +2712,9 @@ public class ShortcutService extends IShortcutService.Stub {
if (matchManifest && si.isDeclaredInManifest()) {
return true;
}
if (matchCached && si.isCached()) {
return true;
}
return false;
}, cloneFlag, callingPackage, launcherUserId, getPinnedByAnyLauncher);
}

View File

@@ -82,6 +82,7 @@ import android.content.pm.LauncherApps.PinItemRequest;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
@@ -1227,6 +1228,142 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
public void testShortcutManagerGetShortcuts_shortcutTypes() {
// Create 3 manifest and 3 dynamic shortcuts
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_3);
updatePackageVersion(CALLING_PACKAGE_1, 1);
mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
});
// Pin 2 and 3
runWithCaller(LAUNCHER_1, USER_0, () -> {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "ms3", "s2", "s3"),
HANDLE_USER_0);
});
// Cache 1 and 2
setCaller(CALLING_PACKAGE_1);
getCallerShortcut("s1").setCached();
getCallerShortcut("s2").setCached();
// Get manifest shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_MANIFEST),
"ms1", "ms2", "ms3");
// Get dynamic shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
"s1", "s2", "s3");
// Get pinned shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_PINNED),
"ms2", "ms3", "s2", "s3");
// Get cached shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
"s1", "s2");
// Get manifest and dynamic shortcuts
assertShortcutIds(mManager.getShortcuts(
ShortcutManager.FLAG_MATCH_MANIFEST | ShortcutManager.FLAG_MATCH_DYNAMIC),
"ms1", "ms2", "ms3", "s1", "s2", "s3");
// Get manifest and pinned shortcuts
assertShortcutIds(mManager.getShortcuts(
ShortcutManager.FLAG_MATCH_MANIFEST | ShortcutManager.FLAG_MATCH_PINNED),
"ms1", "ms2", "ms3", "s2", "s3");
// Get manifest and cached shortcuts
assertShortcutIds(mManager.getShortcuts(
ShortcutManager.FLAG_MATCH_MANIFEST | ShortcutManager.FLAG_MATCH_CACHED),
"ms1", "ms2", "ms3", "s1", "s2");
// Get dynamic and pinned shortcuts
assertShortcutIds(mManager.getShortcuts(
ShortcutManager.FLAG_MATCH_DYNAMIC | ShortcutManager.FLAG_MATCH_PINNED),
"ms2", "ms3", "s1", "s2", "s3");
// Get dynamic and cached shortcuts
assertShortcutIds(mManager.getShortcuts(
ShortcutManager.FLAG_MATCH_DYNAMIC | ShortcutManager.FLAG_MATCH_CACHED),
"s1", "s2", "s3");
// Get pinned and cached shortcuts
assertShortcutIds(mManager.getShortcuts(
ShortcutManager.FLAG_MATCH_PINNED | ShortcutManager.FLAG_MATCH_CACHED),
"ms2", "ms3", "s1", "s2", "s3");
// Remove a dynamic cached shortcut
mManager.removeDynamicShortcuts(list("s1"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC), "s2", "s3");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s1", "s2");
// Remove a dynamic cached and pinned shortcut
mManager.removeDynamicShortcuts(list("s2"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC), "s3");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_PINNED),
"ms2", "ms3", "s2", "s3");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s1", "s2");
}
public void testCachedShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"), makeShortcut("s2"),
makeShortcut("s3"), makeShortcut("s4"))));
});
// Pin s2
runWithCaller(LAUNCHER_1, USER_0, () -> {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"),
HANDLE_USER_0);
});
// Cache 2, 3 and 4
setCaller(CALLING_PACKAGE_1);
getCallerShortcut("s2").setCached();
getCallerShortcut("s3").setCached();
getCallerShortcut("s4").setCached();
// Get dynamic shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
"s1", "s2", "s3", "s4");
// Get pinned shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_PINNED),
"s2");
// Get cached shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
"s2", "s3", "s4");
// Remove a dynamic cached shortcut
mManager.removeDynamicShortcuts(list("s3"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
"s1", "s2", "s4");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
"s2", "s3", "s4");
// Remove dynamic cached long lived shortcuts
mManager.removeLongLivedShortcuts(list("s3", "s4"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
"s1", "s2");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
"s2");
// Remove a dynamic cached pinned long lived shortcut
mManager.removeLongLivedShortcuts(list("s2"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
"s1");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_PINNED),
"s2");
}
// === Test for launcher side APIs ===
public void testGetShortcuts() {
@@ -1366,6 +1503,54 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
// TODO More tests: pinned but dynamic.
// Cache some shortcuts
setCaller(CALLING_PACKAGE_1);
getCallerShortcut("s1").setCached();
setCaller(CALLING_PACKAGE_2);
getCallerShortcut("s4").setCached();
setCaller(CALLING_PACKAGE_3);
getCallerShortcut("s3").setCached();
setCaller(LAUNCHER_1);
// Cached ones only
assertShortcutIds(assertAllNotKeyFieldsOnly(
mLauncherApps.getShortcuts(buildQuery(
/* time =*/ 0, CALLING_PACKAGE_2,
/* activity =*/ null,
ShortcutQuery.FLAG_MATCH_CACHED),
getCallingUser())),
"s4");
// All packages.
assertShortcutIds(assertAllNotKeyFieldsOnly(
mLauncherApps.getShortcuts(buildQuery(
/* time =*/ 0, /* package= */ null,
/* activity =*/ null,
ShortcutQuery.FLAG_MATCH_CACHED),
getCallingUser())),
"s1", "s4", "s3");
assertExpectException(
IllegalArgumentException.class, "package name must also be set", () -> {
mLauncherApps.getShortcuts(buildQuery(
/* time =*/ 0, /* package= */ null, list("id"),
/* activity =*/ null, /* flags */ 0), getCallingUser());
});
// Change Launcher. Cached shortcuts are the same for all launchers.
setCaller(LAUNCHER_2);
// All packages.
assertShortcutIds(assertAllNotKeyFieldsOnly(
mLauncherApps.getShortcuts(buildQuery(
/* time =*/ 0, /* package= */ null,
/* activity =*/ null,
ShortcutQuery.FLAG_MATCH_CACHED),
getCallingUser())),
"s1", "s4", "s3");
}
public void testGetShortcuts_shortcutKinds() throws Exception {