Merge "ShortcutManager: add remaining APIs." into nyc-dev

am: 4a07c34ca8

* commit '4a07c34ca86fddb75332eba22a4d7b9bd48205db':
  ShortcutManager: add remaining APIs.
This commit is contained in:
Makoto Onuki
2016-03-09 22:33:35 +00:00
committed by android-build-merger
26 changed files with 1172 additions and 236 deletions

View File

@@ -9994,6 +9994,7 @@ package android.content.pm {
method public int getWeight();
method public boolean hasIconFile();
method public boolean hasIconResource();
method public boolean hasKeyFieldsOnly();
method public boolean isDynamic();
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
@@ -10004,6 +10005,7 @@ package android.content.pm {
field public static final int FLAG_DYNAMIC = 1; // 0x1
field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
field public static final int FLAG_PINNED = 2; // 0x2
}
@@ -10024,6 +10026,7 @@ package android.content.pm {
method public void deleteAllDynamicShortcuts();
method public void deleteDynamicShortcut(java.lang.String);
method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
method public int getIconMaxDimensions();
method public int getMaxDynamicShortcutCount();
method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method public long getRateLimitResetTime();
@@ -29030,7 +29033,6 @@ package android.os {
ctor public PersistableBundle();
ctor public PersistableBundle(int);
ctor public PersistableBundle(android.os.PersistableBundle);
ctor public PersistableBundle(android.os.Bundle);
method public java.lang.Object clone();
method public int describeContents();
method public android.os.PersistableBundle getPersistableBundle(java.lang.String);

View File

@@ -10388,6 +10388,7 @@ package android.content.pm {
method public int getWeight();
method public boolean hasIconFile();
method public boolean hasIconResource();
method public boolean hasKeyFieldsOnly();
method public boolean isDynamic();
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
@@ -10398,6 +10399,7 @@ package android.content.pm {
field public static final int FLAG_DYNAMIC = 1; // 0x1
field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
field public static final int FLAG_PINNED = 2; // 0x2
}
@@ -10418,6 +10420,7 @@ package android.content.pm {
method public void deleteAllDynamicShortcuts();
method public void deleteDynamicShortcut(java.lang.String);
method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
method public int getIconMaxDimensions();
method public int getMaxDynamicShortcutCount();
method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method public long getRateLimitResetTime();
@@ -31310,7 +31313,6 @@ package android.os {
ctor public PersistableBundle();
ctor public PersistableBundle(int);
ctor public PersistableBundle(android.os.PersistableBundle);
ctor public PersistableBundle(android.os.Bundle);
method public java.lang.Object clone();
method public int describeContents();
method public android.os.PersistableBundle getPersistableBundle(java.lang.String);

View File

@@ -10004,6 +10004,7 @@ package android.content.pm {
method public int getWeight();
method public boolean hasIconFile();
method public boolean hasIconResource();
method public boolean hasKeyFieldsOnly();
method public boolean isDynamic();
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
@@ -10014,6 +10015,7 @@ package android.content.pm {
field public static final int FLAG_DYNAMIC = 1; // 0x1
field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
field public static final int FLAG_PINNED = 2; // 0x2
}
@@ -10034,6 +10036,7 @@ package android.content.pm {
method public void deleteAllDynamicShortcuts();
method public void deleteDynamicShortcut(java.lang.String);
method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
method public int getIconMaxDimensions();
method public int getMaxDynamicShortcutCount();
method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method public long getRateLimitResetTime();
@@ -29096,7 +29099,6 @@ package android.os {
ctor public PersistableBundle();
ctor public PersistableBundle(int);
ctor public PersistableBundle(android.os.PersistableBundle);
ctor public PersistableBundle(android.os.Bundle);
method public java.lang.Object clone();
method public int describeContents();
method public android.os.PersistableBundle getPersistableBundle(java.lang.String);

View File

@@ -753,12 +753,11 @@ final class SystemServiceRegistry {
registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class,
new CachedServiceFetcher<ShortcutManager>() {
@Override
public ShortcutManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
return new ShortcutManager(ctx,
IShortcutService.Stub.asInterface(b));
}});
@Override
public ShortcutManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
}});
}
/**

View File

@@ -26,6 +26,8 @@ import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.ParcelFileDescriptor;
import java.util.List;
/**
@@ -52,4 +54,8 @@ interface ILauncherApps {
in UserHandle user);
boolean startShortcut(String callingPackage, String packageName, String id,
in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user);
int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user);
ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut,
in UserHandle user);
}

View File

@@ -44,5 +44,7 @@ interface IShortcutService {
long getRateLimitResetTime(String packageName, int userId);
int getIconMaxDimensions(String packageName, int userId);
void resetThrottling(); // system only API for developer opsions
}

View File

@@ -183,7 +183,8 @@ public class LauncherApps {
public static final int FLAG_GET_PINNED = 1 << 1;
/**
* Requests "key" fields only.
* Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()} for which
* fields are available.
*/
public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
@@ -473,7 +474,11 @@ public class LauncherApps {
*/
@RequiresPermission(permission.BIND_APPWIDGET)
public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
throw new RuntimeException("not implemented yet");
try {
return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
@@ -488,7 +493,11 @@ public class LauncherApps {
@RequiresPermission(permission.BIND_APPWIDGET)
public ParcelFileDescriptor getShortcutIconFd(
@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
throw new RuntimeException("not implemented yet");
try {
return mService.getShortcutIconFd(mContext.getPackageName(), shortcut, user);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**

View File

@@ -19,9 +19,11 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -60,6 +62,9 @@ public class ShortcutInfo implements Parcelable {
/* @hide */
public static final int FLAG_HAS_ICON_FILE = 1 << 3;
/* @hide */
public static final int FLAG_KEY_FIELDS_ONLY = 1 << 4;
/** @hide */
@IntDef(flag = true,
value = {
@@ -67,6 +72,7 @@ public class ShortcutInfo implements Parcelable {
FLAG_PINNED,
FLAG_HAS_ICON_RES,
FLAG_HAS_ICON_FILE,
FLAG_KEY_FIELDS_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -114,10 +120,15 @@ public class ShortcutInfo implements Parcelable {
@NonNull
private String mTitle;
/**
* Intent *with extras removed*.
*/
@NonNull
private Intent mIntent;
// Internal use only.
/**
* Extras for the intent.
*/
@NonNull
private PersistableBundle mIntentPersistableExtras;
@@ -149,6 +160,11 @@ public class ShortcutInfo implements Parcelable {
mIcon = b.mIcon;
mTitle = b.mTitle;
mIntent = b.mIntent;
final Bundle intentExtras = mIntent.getExtras();
if (intentExtras != null) {
mIntent.replaceExtras((Bundle) null);
mIntentPersistableExtras = new PersistableBundle(intentExtras);
}
mWeight = b.mWeight;
mExtras = b.mExtras;
updateTimestamp();
@@ -170,11 +186,12 @@ public class ShortcutInfo implements Parcelable {
private ShortcutInfo(ShortcutInfo source, @CloneFlags int cloneFlags) {
mId = source.mId;
mPackageName = source.mPackageName;
mActivityComponent = source.mActivityComponent;
mFlags = source.mFlags;
mLastChangedTimestamp = source.mLastChangedTimestamp;
if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) {
mActivityComponent = source.mActivityComponent;
if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
mIcon = source.mIcon;
}
@@ -188,6 +205,10 @@ public class ShortcutInfo implements Parcelable {
mExtras = source.mExtras;
mIconResourceId = source.mIconResourceId;
mBitmapPath = source.mBitmapPath;
} else {
// Set this bit.
mFlags |= FLAG_KEY_FIELDS_ONLY;
}
}
@@ -238,6 +259,39 @@ public class ShortcutInfo implements Parcelable {
updateTimestamp();
}
/**
* @hide
*/
public static Icon validateIcon(Icon icon) {
switch (icon.getType()) {
case Icon.TYPE_RESOURCE:
case Icon.TYPE_BITMAP:
break; // OK
case Icon.TYPE_URI:
if (ContentResolver.SCHEME_CONTENT.equals(icon.getUri().getScheme())) {
break;
}
// Note "file:" is not supported, because depending on the path, system server
// cannot access it. // TODO Revisit "file:" icon support
// fall through
default:
throw getInvalidIconException();
}
if (icon.hasTint()) {
// TODO support it
throw new IllegalArgumentException("Icons with tints are not supported");
}
return icon;
}
/** @hide */
public static IllegalArgumentException getInvalidIconException() {
return new IllegalArgumentException("Unsupported icon type:"
+" only bitmap, resource and content URI are supported");
}
/**
* Builder class for {@link ShortcutInfo} objects.
*/
@@ -273,7 +327,9 @@ public class ShortcutInfo implements Parcelable {
}
/**
* Optionally sets the target activity.
* Optionally sets the target activity. If it's not set, and if the caller application
* has multiple launcher icons, this shortcut will be shown on all those icons.
* If it's set, this shortcut will be only shown on this activity.
*/
@NonNull
public Builder setActivityComponent(@NonNull ComponentName activityComponent) {
@@ -284,15 +340,22 @@ public class ShortcutInfo implements Parcelable {
/**
* Optionally sets an icon.
*
* - Tint is not supported TODO Either check and throw, or support it.
* - URI icons will be converted into Bitmap icons at the registration time.
* <ul>
* <li>Tints are not supported.
* <li>Bitmaps, resources and "content:" URIs are supported.
* <li>"content:" URI will be fetched when a shortcut is registered to
* {@link ShortcutManager}. Changing the content from the same URI later will
* not be reflected to launcher icons.
* </ul>
*
* TODO Only allow Bitmap, Resource and URI types. byte[] type can easily go over
* binder size limit.
* <p>For performance reasons, icons will <b>NOT</b> be available on instances
* returned by {@link ShortcutManager} or {@link LauncherApps}. Launcher applications
* need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)}
* and {@link LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)}.
*/
@NonNull
public Builder setIcon(Icon icon) {
mIcon = icon;
mIcon = validateIcon(icon);
return this;
}
@@ -316,7 +379,7 @@ public class ShortcutInfo implements Parcelable {
}
/**
* Optionally sets the weight of a shortcut, which will be used by Launcher for sorting.
* Optionally sets the weight of a shortcut, which will be used by the launcher for sorting.
* The larger the weight, the more "important" a shortcut is.
*/
@NonNull
@@ -326,8 +389,8 @@ public class ShortcutInfo implements Parcelable {
}
/**
* Optional values that application can set.
* TODO: reserve keys starting with "android."
* Optional values that applications can set. Applications can store any meta-data of
* shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}.
*/
@NonNull
public Builder setExtras(@NonNull PersistableBundle extras) {
@@ -353,7 +416,7 @@ public class ShortcutInfo implements Parcelable {
}
/**
* Return the ID of the shortcut.
* Return the package name of the creator application.
*/
@NonNull
public String getPackageName() {
@@ -374,7 +437,7 @@ public class ShortcutInfo implements Parcelable {
*
* For performance reasons, this will <b>NOT</b> be available when an instance is returned
* by {@link ShortcutManager} or {@link LauncherApps}. A launcher application needs to use
* other APIs in LauncherApps to fetch the bitmap. TODO Add a precondition for it.
* other APIs in LauncherApps to fetch the bitmap.
*
* @hide
*/
@@ -385,22 +448,46 @@ public class ShortcutInfo implements Parcelable {
/**
* Return the shortcut title.
*
* <p>All shortcuts must have a non-empty title, but this method will return null when
* {@link #hasKeyFieldsOnly()} is true.
*/
@NonNull
@Nullable
public String getTitle() {
return mTitle;
}
/**
* Return the intent.
* TODO Set mIntentPersistableExtras and before returning.
*
* <p>All shortcuts must have an intent, but this method will return null when
* {@link #hasKeyFieldsOnly()} is true.
*/
@NonNull
@Nullable
public Intent getIntent() {
if (mIntent == null) {
return null;
}
final Intent intent = new Intent(mIntent);
intent.replaceExtras(
mIntentPersistableExtras != null ? new Bundle(mIntentPersistableExtras) : null);
return intent;
}
/**
* Return "raw" intent, which is the original intent without the extras.
* @hide
*/
@Nullable
public Intent getIntentNoExtras() {
return mIntent;
}
/** @hide */
/**
* The extras in the intent. We convert extras into {@link PersistableBundle} so we can
* persist them.
* @hide
*/
@Nullable
public PersistableBundle getIntentPersistableExtras() {
return mIntentPersistableExtras;
@@ -483,6 +570,23 @@ public class ShortcutInfo implements Parcelable {
return hasFlags(FLAG_HAS_ICON_FILE);
}
/**
* Return whether a shortcut only contains "key" information only or not. If true, only the
* following fields are available.
* <ul>
* <li>{@link #getId()}
* <li>{@link #getPackageName()}
* <li>{@link #getLastChangedTimestamp()}
* <li>{@link #isDynamic()}
* <li>{@link #isPinned()}
* <li>{@link #hasIconResource()}
* <li>{@link #hasIconFile()}
* </ul>
*/
public boolean hasKeyFieldsOnly() {
return hasFlags(FLAG_KEY_FIELDS_ONLY);
}
/** @hide */
public void updateTimestamp() {
mLastChangedTimestamp = System.currentTimeMillis();
@@ -495,33 +599,13 @@ public class ShortcutInfo implements Parcelable {
}
/** @hide */
public void setIcon(Icon icon) {
mIcon = icon;
public void clearIcon() {
mIcon = null;
}
/** @hide */
public void setTitle(String title) {
mTitle = title;
}
/** @hide */
public void setIntent(Intent intent) {
mIntent = intent;
}
/** @hide */
public void setIntentPersistableExtras(PersistableBundle intentPersistableExtras) {
mIntentPersistableExtras = intentPersistableExtras;
}
/** @hide */
public void setWeight(int weight) {
mWeight = weight;
}
/** @hide */
public void setExtras(PersistableBundle extras) {
mExtras = extras;
public void setIconResourceId(int iconResourceId) {
mIconResourceId = iconResourceId;
}
/** @hide */
@@ -643,9 +727,10 @@ public class ShortcutInfo implements Parcelable {
sb.append(", extras=");
sb.append(mExtras);
sb.append(", flags=");
sb.append(mFlags);
if (includeInternalData) {
sb.append(", flags=");
sb.append(mFlags);
sb.append(", iconRes=");
sb.append(mIconResourceId);

View File

@@ -239,6 +239,17 @@ public class ShortcutManager {
}
}
/**
* Return the max width and height for icons, in pixels.
*/
public int getIconMaxDimensions() {
try {
return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide injection point */
@VisibleForTesting
protected int injectMyUserId() {

View File

@@ -22,6 +22,8 @@ import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import java.util.List;
@@ -55,4 +57,10 @@ public abstract class ShortcutServiceInternal {
@NonNull String packageName, @NonNull String shortcutId, int userId);
public abstract void addListener(@NonNull ShortcutChangeListener listener);
public abstract int getShortcutIconResId(@NonNull String callingPackage,
@NonNull ShortcutInfo shortcut, int userId);
public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
@NonNull ShortcutInfo shortcut, int userId);
}

View File

@@ -86,6 +86,8 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
* @param b a Bundle to be copied.
*
* @throws IllegalArgumentException if any element of {@code b} cannot be persisted.
*
* @hide
*/
public PersistableBundle(Bundle b) {
this(b.getMap());

View File

@@ -627,6 +627,11 @@ public final class Icon implements Parcelable {
return this;
}
/** @hide */
public boolean hasTint() {
return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE);
}
/**
* Create an Icon pointing to an image file specified by path.
*

View File

@@ -42,6 +42,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IInterface;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -328,6 +329,26 @@ public class LauncherAppsService extends SystemService {
ids, user.getIdentifier());
}
@Override
public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
UserHandle user) {
enforceShortcutPermission(user);
verifyCallingPackage(callingPackage);
return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut,
user.getIdentifier());
}
@Override
public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
UserHandle user) {
enforceShortcutPermission(user);
verifyCallingPackage(callingPackage);
return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut,
user.getIdentifier());
}
@Override
public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
Rect sourceBounds, Bundle startActivityOptions, UserHandle user)

File diff suppressed because it is too large Load Diff

View File

@@ -726,9 +726,6 @@ public final class SystemServer {
// Always start the Device Policy Manager, so that the API is compatible with
// API8.
mSystemServiceManager.startService(DevicePolicyManagerService.Lifecycle.class);
// TODO is this a good place?
mSystemServiceManager.startService(ShortcutService.Lifecycle.class);
}
if (!disableSystemUI) {
@@ -1139,6 +1136,8 @@ public final class SystemServer {
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// LauncherAppsService uses ShortcutService.
mSystemServiceManager.startService(ShortcutService.Lifecycle.class);
mSystemServiceManager.startService(LauncherAppsService.class);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -25,19 +25,26 @@ import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.content.pm.ShortcutServiceInternal;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.test.AndroidTestCase;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import com.android.frameworks.servicestests.R;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import libcore.io.IoUtils;
import org.junit.Assert;
@@ -45,13 +52,16 @@ import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Tests for ShortcutService and ShortcutManager.
@@ -61,7 +71,11 @@ import java.util.Map;
-r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest \
-w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
* TODO: Add checks with assertAllNotHaveIcon()
* TODO: Cross-user test (do in CTS?)
*/
@SmallTest
public class ShortcutManagerTest extends AndroidTestCase {
private static final String TAG = "ShortcutManagerTest";
@@ -77,10 +91,19 @@ public class ShortcutManagerTest extends AndroidTestCase {
public String getPackageName() {
return mInjectedClientPackage;
}
@Override
public Resources getResources() {
return ShortcutManagerTest.this.getContext().getResources();
}
}
/** Context used in the service side */
private final class ServiceContext extends MockContext {
@Override
public Resources getResources() {
return ShortcutManagerTest.this.getContext().getResources();
}
}
/** ShortcutService with injection override methods. */
@@ -95,6 +118,7 @@ public class ShortcutManagerTest extends AndroidTestCase {
setResetIntervalForTest(INTERVAL);
setMaxDynamicShortcutsForTest(MAX_SHORTCUTS);
setMaxDailyUpdatesForTest(MAX_DAILY_UPDATES);
setMaxIconDimensionForTest(MAX_ICON_DIMENSION);
}
@Override
@@ -108,7 +132,7 @@ public class ShortcutManagerTest extends AndroidTestCase {
}
@Override
int injectGetPackageUid(String packageName) {
int injectGetPackageUid(String packageName, int userId) {
Integer uid = mInjectedPackageUidMap.get(packageName);
return uid != null ? uid : -1;
}
@@ -122,6 +146,11 @@ public class ShortcutManagerTest extends AndroidTestCase {
File injectUserDataPath(@UserIdInt int userId) {
return new File(mInjectedFilePathRoot, "user-" + userId);
}
@Override
void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
// Can't check
}
}
/** ShortcutManager with injection override methods. */
@@ -181,10 +210,12 @@ public class ShortcutManagerTest extends AndroidTestCase {
private static final long INTERVAL = 10000;
private static final int MAX_SHORTCUTS = 5;
private static final int MAX_SHORTCUTS = 10;
private static final int MAX_DAILY_UPDATES = 3;
private static final int MAX_ICON_DIMENSION = 128;
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -233,7 +264,8 @@ public class ShortcutManagerTest extends AndroidTestCase {
/** Replace the current calling package */
private void setCaller(String packageName) {
mInjectedClientPackage = packageName;
mInjectedCallingUid = Preconditions.checkNotNull(mInjectedPackageUidMap.get(packageName));
mInjectedCallingUid = Preconditions.checkNotNull(mInjectedPackageUidMap.get(packageName),
"Unknown package");
}
private String getCallingPackage() {
@@ -342,6 +374,28 @@ public class ShortcutManagerTest extends AndroidTestCase {
return s;
}
/**
* Make a shortcut with an ID and icon.
*/
private ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, icon,
makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
}
private ShortcutInfo makePackageShortcut(String packageName, String id) {
String origCaller = getCallingPackage();
setCaller(packageName);
ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
setCaller(origCaller); // restore the caller
return s;
}
/**
* Make multiple shortcuts with IDs.
*/
@@ -413,6 +467,7 @@ public class ShortcutManagerTest extends AndroidTestCase {
@NonNull
private List<ShortcutInfo> assertShortcutIds(@NonNull List<ShortcutInfo> actualShortcuts,
String... expectedIds) {
assertEquals(expectedIds.length, actualShortcuts.size());
final HashSet<String> expected = new HashSet<>(Arrays.asList(expectedIds));
final HashSet<String> actual = new HashSet<>();
for (ShortcutInfo s : actualShortcuts) {
@@ -460,6 +515,35 @@ public class ShortcutManagerTest extends AndroidTestCase {
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllNotHaveIcon(
@NonNull List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertNull("ID " + s.getId(), s.getIcon());
}
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllHaveIconResId(
@NonNull List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
}
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllHaveIconFile(
@NonNull List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
}
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
int shortcutFlags) {
@@ -469,6 +553,24 @@ public class ShortcutManagerTest extends AndroidTestCase {
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllKeyFieldsOnly(
@NonNull List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
}
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllNotKeyFieldsOnly(
@NonNull List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
}
return actualShortcuts;
}
@NonNull
private List<ShortcutInfo> assertAllDynamic(@NonNull List<ShortcutInfo> actualShortcuts) {
return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_DYNAMIC);
@@ -488,6 +590,31 @@ public class ShortcutManagerTest extends AndroidTestCase {
return actualShortcuts;
}
private void assertBitmapSize(int expectedWidth, int expectedHeight, @NonNull Bitmap bitmap) {
assertEquals("width", expectedWidth, bitmap.getWidth());
assertEquals("height", expectedHeight, bitmap.getHeight());
}
private <T> void assertAllUnique(Collection<T> list) {
final Set<Object> set = new HashSet<>();
for (T item : list) {
if (set.contains(item)) {
fail("Duplicate item found: " + item + " (in the list: " + list + ")");
}
set.add(item);
}
}
@NonNull
private Bitmap pfdToBitmap(@NonNull ParcelFileDescriptor pfd) {
Preconditions.checkNotNull(pfd);
try {
return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
} finally {
IoUtils.closeQuietly(pfd);
}
}
/**
* Test for the first launch path, no settings file available.
*/
@@ -594,13 +721,17 @@ public class ShortcutManagerTest extends AndroidTestCase {
final ShortcutInfo si3 = makeShortcut("shortcut3");
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
assertEquals(2, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1", "shortcut2");
assertEquals(2, mManager.getRemainingCallCount());
// TODO: Check fields
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(1, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1");
assertEquals(1, mManager.getRemainingCallCount());
assertTrue(mManager.setDynamicShortcuts(Arrays.asList()));
@@ -629,16 +760,22 @@ public class ShortcutManagerTest extends AndroidTestCase {
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(1, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1");
assertTrue(mManager.addDynamicShortcut(si2));
assertEquals(1, mManager.getRemainingCallCount());
assertEquals(2, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1", "shortcut2");
// Add with the same ID
assertTrue(mManager.addDynamicShortcut(makeShortcut("shortcut1")));
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(2, mManager.getDynamicShortcuts().size()); // Still 2
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1", "shortcut2");
// TODO Check max number
@@ -651,24 +788,35 @@ public class ShortcutManagerTest extends AndroidTestCase {
final ShortcutInfo si3 = makeShortcut("shortcut3");
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
assertEquals(3, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1", "shortcut2", "shortcut3");
assertEquals(2, mManager.getRemainingCallCount());
mManager.deleteDynamicShortcut("shortcut1");
assertEquals(2, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut2", "shortcut3");
mManager.deleteDynamicShortcut("shortcut1");
assertEquals(2, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut2", "shortcut3");
mManager.deleteDynamicShortcut("shortcutXXX");
assertEquals(2, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut2", "shortcut3");
mManager.deleteDynamicShortcut("shortcut2");
assertEquals(1, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut3");
mManager.deleteDynamicShortcut("shortcut3");
assertEquals(0, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()));
// Still 2 calls left.
assertEquals(2, mManager.getRemainingCallCount());
@@ -682,7 +830,9 @@ public class ShortcutManagerTest extends AndroidTestCase {
final ShortcutInfo si3 = makeShortcut("shortcut3");
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
assertEquals(3, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut1", "shortcut2", "shortcut3");
assertEquals(2, mManager.getRemainingCallCount());
@@ -732,7 +882,7 @@ public class ShortcutManagerTest extends AndroidTestCase {
// Now it should work.
mInjectedCurrentTimeLillis++;
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1))); // fail
assertEquals(2, mManager.getRemainingCallCount());
mInjectedCurrentTimeLillis++;
@@ -831,6 +981,226 @@ public class ShortcutManagerTest extends AndroidTestCase {
assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si2)));
}
public void testIcons() {
final Icon res32x32 = Icon.createWithResource(mContext, R.drawable.black_32x32);
final Icon res64x64 = Icon.createWithResource(mContext, R.drawable.black_64x64);
final Icon res512x512 = Icon.createWithResource(mContext, R.drawable.black_512x512);
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
mContext.getResources(), R.drawable.black_32x32));
final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource(
mContext.getResources(), R.drawable.black_64x64));
final Icon bmp512x512 = Icon.createWithBitmap(BitmapFactory.decodeResource(
mContext.getResources(), R.drawable.black_512x512));
// Set from package 1
setCaller(CALLING_PACKAGE_1);
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
makeShortcutWithIcon("res32x32", res32x32),
makeShortcutWithIcon("res64x64", res64x64),
makeShortcutWithIcon("bmp32x32", bmp32x32),
makeShortcutWithIcon("bmp64x64", bmp64x64),
makeShortcutWithIcon("bmp512x512", bmp512x512),
makeShortcut("none")
)));
// getDynamicShortcuts() shouldn't return icons, thus assertAllNotHaveIcon().
assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
"res32x32",
"res64x64",
"bmp32x32",
"bmp64x64",
"bmp512x512",
"none");
// Call from another caller with the same ID, just to make sure storage is per-package.
setCaller(CALLING_PACKAGE_2);
assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
makeShortcutWithIcon("res32x32", res512x512),
makeShortcutWithIcon("res64x64", res512x512),
makeShortcutWithIcon("none", res512x512)
)));
assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
"res32x32",
"res64x64",
"none");
dumpsysOnLogcat();
// Load from launcher.
Bitmap bmp;
setCaller(LAUNCHER_1);
// Check hasIconResource()/hasIconFile().
assertShortcutIds(assertAllHaveIconResId(mInternal.getShortcutInfo(
getCallingPackage(), CALLING_PACKAGE_1, Arrays.asList("res32x32"),
getCallingUserId())), "res32x32");
assertShortcutIds(assertAllHaveIconResId(mInternal.getShortcutInfo(
getCallingPackage(), CALLING_PACKAGE_1, Arrays.asList("res64x64"),
getCallingUserId())), "res64x64");
assertShortcutIds(assertAllHaveIconFile(mInternal.getShortcutInfo(
getCallingPackage(), CALLING_PACKAGE_1, Arrays.asList("bmp32x32"),
getCallingUserId())), "bmp32x32");
assertShortcutIds(assertAllHaveIconFile(mInternal.getShortcutInfo(
getCallingPackage(), CALLING_PACKAGE_1, Arrays.asList("bmp64x64"),
getCallingUserId())), "bmp64x64");
assertShortcutIds(assertAllHaveIconFile(mInternal.getShortcutInfo(
getCallingPackage(), CALLING_PACKAGE_1, Arrays.asList("bmp512x512"),
getCallingUserId())), "bmp512x512");
// Check
assertEquals(
R.drawable.black_32x32,
mInternal.getShortcutIconResId(getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "res32x32"), getCallingUserId()));
assertEquals(
R.drawable.black_64x64,
mInternal.getShortcutIconResId(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "res64x64"), getCallingUserId()));
assertEquals(
0, // because it's not a resource
mInternal.getShortcutIconResId(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUserId()));
assertEquals(
0, // because it's not a resource
mInternal.getShortcutIconResId(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUserId()));
assertEquals(
0, // because it's not a resource
mInternal.getShortcutIconResId(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUserId()));
bmp = pfdToBitmap(mInternal.getShortcutIconFd(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUserId()));
assertBitmapSize(32, 32, bmp);
bmp = pfdToBitmap(mInternal.getShortcutIconFd(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUserId()));
assertBitmapSize(64, 64, bmp);
bmp = pfdToBitmap(mInternal.getShortcutIconFd(
getCallingPackage(),
makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUserId()));
assertBitmapSize(128, 128, bmp);
// TODO Test the content URI case too.
}
private void checkShrinkBitmap(int expectedWidth, int expectedHeight, int resId, int maxSize) {
assertBitmapSize(expectedWidth, expectedHeight,
ShortcutService.shrinkBitmap(BitmapFactory.decodeResource(
mContext.getResources(), resId),
maxSize));
}
public void testShrinkBitmap() {
checkShrinkBitmap(32, 32, R.drawable.black_512x512, 32);
checkShrinkBitmap(511, 511, R.drawable.black_512x512, 511);
checkShrinkBitmap(512, 512, R.drawable.black_512x512, 512);
checkShrinkBitmap(1024, 4096, R.drawable.black_1024x4096, 4096);
checkShrinkBitmap(1024, 4096, R.drawable.black_1024x4096, 4100);
checkShrinkBitmap(512, 2048, R.drawable.black_1024x4096, 2048);
checkShrinkBitmap(4096, 1024, R.drawable.black_4096x1024, 4096);
checkShrinkBitmap(4096, 1024, R.drawable.black_4096x1024, 4100);
checkShrinkBitmap(2048, 512, R.drawable.black_4096x1024, 2048);
}
private File openIconFileForWriteAndGetPath(int userId, String packageName)
throws IOException {
// Shortcut IDs aren't used in the path, so just pass the same ID.
final FileOutputStreamWithPath out =
mService.openIconFileForWrite(userId, makePackageShortcut(packageName, "id"));
out.close();
return out.getFile();
}
public void testOpenIconFileForWrite() throws IOException {
mInjectedCurrentTimeLillis = 1000;
final File p10_1_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
final File p10_1_2 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
final File p10_2_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
final File p10_2_2 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
final File p11_1_1 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
final File p11_1_2 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
mInjectedCurrentTimeLillis++;
final File p10_1_3 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
final File p10_1_4 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
final File p10_1_5 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
final File p10_2_3 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
final File p11_1_3 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
// Make sure their paths are all unique
assertAllUnique(Arrays.asList(
p10_1_1,
p10_1_2,
p10_1_3,
p10_1_4,
p10_1_5,
p10_2_1,
p10_2_2,
p10_2_3,
p11_1_1,
p11_1_2,
p11_1_3
));
// Check each set has the same parent.
assertEquals(p10_1_1.getParent(), p10_1_2.getParent());
assertEquals(p10_1_1.getParent(), p10_1_3.getParent());
assertEquals(p10_1_1.getParent(), p10_1_4.getParent());
assertEquals(p10_1_1.getParent(), p10_1_5.getParent());
assertEquals(p10_2_1.getParent(), p10_2_2.getParent());
assertEquals(p10_2_1.getParent(), p10_2_3.getParent());
assertEquals(p11_1_1.getParent(), p11_1_2.getParent());
assertEquals(p11_1_1.getParent(), p11_1_3.getParent());
// Check the parents are still unique.
assertAllUnique(Arrays.asList(
p10_1_1.getParent(),
p10_2_1.getParent(),
p11_1_1.getParent()
));
// All files created at the same time for the same package/user, expcet for the first ones,
// will have "_" in the path.
assertFalse(p10_1_1.getName().contains("_"));
assertTrue(p10_1_2.getName().contains("_"));
assertFalse(p10_1_3.getName().contains("_"));
assertTrue(p10_1_4.getName().contains("_"));
assertTrue(p10_1_5.getName().contains("_"));
assertFalse(p10_2_1.getName().contains("_"));
assertTrue(p10_2_2.getName().contains("_"));
assertFalse(p10_2_3.getName().contains("_"));
assertFalse(p11_1_1.getName().contains("_"));
assertTrue(p11_1_2.getName().contains("_"));
assertFalse(p11_1_3.getName().contains("_"));
}
// TODO: updateShortcuts()
// TODO: getPinnedShortcuts()
@@ -860,9 +1230,10 @@ public class ShortcutManagerTest extends AndroidTestCase {
// Get dynamic
assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
assertAllNotKeyFieldsOnly(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_1,
/* activity =*/ null,
ShortcutQuery.FLAG_GET_DYNAMIC, getCallingUserId()),
ShortcutQuery.FLAG_GET_DYNAMIC, getCallingUserId())),
"s1", "s2"))));
// Get pinned
@@ -874,18 +1245,20 @@ public class ShortcutManagerTest extends AndroidTestCase {
// Get both, with timestamp
assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 1000, CALLING_PACKAGE_2,
assertAllNotKeyFieldsOnly(mInternal.getShortcuts(getCallingPackage(),
/* time =*/ 1000, CALLING_PACKAGE_2,
/* activity =*/ null,
ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC,
getCallingUserId()),
getCallingUserId())),
"s2", "s3"))));
// FLAG_GET_KEY_FIELDS_ONLY
assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 1000, CALLING_PACKAGE_2,
assertAllKeyFieldsOnly(mInternal.getShortcuts(getCallingPackage(),
/* time =*/ 1000, CALLING_PACKAGE_2,
/* activity =*/ null,
ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY,
getCallingUserId()),
getCallingUserId())),
"s2", "s3"))));
// Pin some shortcuts.
@@ -894,19 +1267,20 @@ public class ShortcutManagerTest extends AndroidTestCase {
// Pinned ones only
assertAllPinned(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 1000, CALLING_PACKAGE_2,
assertAllNotKeyFieldsOnly(mInternal.getShortcuts(getCallingPackage(),
/* time =*/ 1000, CALLING_PACKAGE_2,
/* activity =*/ null,
ShortcutQuery.FLAG_GET_PINNED,
getCallingUserId()),
getCallingUserId())),
"s3"))));
// All packages.
assertShortcutIds(
assertShortcutIds(assertAllNotKeyFieldsOnly(
mInternal.getShortcuts(getCallingPackage(),
/* time =*/ 5000, /* package= */ null,
/* activity =*/ null,
ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED,
getCallingUserId()),
getCallingUserId())),
"s1", "s3");
// TODO More tests: pinned but dynamic, filter by activity
@@ -968,8 +1342,9 @@ public class ShortcutManagerTest extends AndroidTestCase {
// Note we don't guarantee the orders.
list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
assertAllNotKeyFieldsOnly(
mInternal.getShortcutInfo(getCallingPackage(), CALLING_PACKAGE_1,
Arrays.asList("s2", "s1", "s3", null), getCallingUserId()))),
Arrays.asList("s2", "s1", "s3", null), getCallingUserId())))),
"s1", "s2");
assertEquals("Title 1", findById(list, "s1").getTitle());
assertEquals("Title 2", findById(list, "s2").getTitle());
@@ -1036,19 +1411,19 @@ public class ShortcutManagerTest extends AndroidTestCase {
setCaller(LAUNCHER_1);
// CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
assertShortcutIds(assertAllPinned(
assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_1,
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId())),
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId()))),
"s2");
assertShortcutIds(assertAllPinned(
assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_2,
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId())),
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId()))),
"s3", "s4");
assertShortcutIds(assertAllPinned(
assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_3,
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId()))
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId())))
/* none */);
}