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:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
*/
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user