Merge "ShortcutManager: First cut of CTS" into nyc-dev
This commit is contained in:
@@ -9505,6 +9505,7 @@ package android.content.pm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class LauncherApps {
|
public class LauncherApps {
|
||||||
|
ctor public LauncherApps(android.content.Context);
|
||||||
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
|
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
|
||||||
method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
|
method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
|
||||||
method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
|
method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
|
||||||
@@ -10092,6 +10093,7 @@ package android.content.pm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class ShortcutManager {
|
public class ShortcutManager {
|
||||||
|
ctor public ShortcutManager(android.content.Context);
|
||||||
method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
|
method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
|
||||||
method public void deleteAllDynamicShortcuts();
|
method public void deleteAllDynamicShortcuts();
|
||||||
method public void deleteDynamicShortcut(java.lang.String);
|
method public void deleteDynamicShortcut(java.lang.String);
|
||||||
|
|||||||
@@ -589,9 +589,7 @@ final class SystemServiceRegistry {
|
|||||||
new CachedServiceFetcher<LauncherApps>() {
|
new CachedServiceFetcher<LauncherApps>() {
|
||||||
@Override
|
@Override
|
||||||
public LauncherApps createService(ContextImpl ctx) {
|
public LauncherApps createService(ContextImpl ctx) {
|
||||||
IBinder b = ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE);
|
return new LauncherApps(ctx);
|
||||||
ILauncherApps service = ILauncherApps.Stub.asInterface(b);
|
|
||||||
return new LauncherApps(ctx, service);
|
|
||||||
}});
|
}});
|
||||||
|
|
||||||
registerService(Context.RESTRICTIONS_SERVICE, RestrictionsManager.class,
|
registerService(Context.RESTRICTIONS_SERVICE, RestrictionsManager.class,
|
||||||
@@ -758,8 +756,7 @@ final class SystemServiceRegistry {
|
|||||||
new CachedServiceFetcher<ShortcutManager>() {
|
new CachedServiceFetcher<ShortcutManager>() {
|
||||||
@Override
|
@Override
|
||||||
public ShortcutManager createService(ContextImpl ctx) {
|
public ShortcutManager createService(ContextImpl ctx) {
|
||||||
IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
|
return new ShortcutManager(ctx);
|
||||||
return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
|
|
||||||
}});
|
}});
|
||||||
|
|
||||||
registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
|
registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.content.pm;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -30,6 +31,7 @@ import android.os.Looper;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -261,6 +263,13 @@ public class LauncherApps {
|
|||||||
mPm = context.getPackageManager();
|
mPm = context.getPackageManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@TestApi
|
||||||
|
public LauncherApps(Context context) {
|
||||||
|
this(context, ILauncherApps.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
|
* Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
|
||||||
* {@link Intent#CATEGORY_LAUNCHER}, for a specified user.
|
* {@link Intent#CATEGORY_LAUNCHER}, for a specified user.
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
package android.content.pm;
|
package android.content.pm;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -96,6 +99,15 @@ public class ShortcutManager {
|
|||||||
mService = service;
|
mService = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@TestApi
|
||||||
|
public ShortcutManager(Context context) {
|
||||||
|
this(context, IShortcutService.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.SHORTCUT_SERVICE)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish a list of shortcuts. All existing dynamic shortcuts from the caller application
|
* Publish a list of shortcuts. All existing dynamic shortcuts from the caller application
|
||||||
* will be replaced.
|
* will be replaced.
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ public class LauncherAppsService extends SystemService {
|
|||||||
@Override
|
@Override
|
||||||
public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
|
public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
verifyCallingPackage(callingPackage);
|
||||||
synchronized (mListeners) {
|
synchronized (mListeners) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
|
Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
|
||||||
|
|||||||
@@ -419,26 +419,26 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mSaveDelayMillis = (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS,
|
mSaveDelayMillis = Math.max(0, (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS,
|
||||||
DEFAULT_SAVE_DELAY_MS);
|
DEFAULT_SAVE_DELAY_MS));
|
||||||
|
|
||||||
mResetInterval = parser.getLong(
|
mResetInterval = Math.max(1, parser.getLong(
|
||||||
ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
|
ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
|
||||||
* 1000L;
|
* 1000L);
|
||||||
|
|
||||||
mMaxDailyUpdates = (int) parser.getLong(
|
mMaxDailyUpdates = Math.max(0, (int) parser.getLong(
|
||||||
ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES);
|
ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES));
|
||||||
|
|
||||||
mMaxDynamicShortcuts = (int) parser.getLong(
|
mMaxDynamicShortcuts = Math.max(0, (int) parser.getLong(
|
||||||
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP);
|
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP));
|
||||||
|
|
||||||
final int iconDimensionDp = injectIsLowRamDevice()
|
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
|
||||||
? (int) parser.getLong(
|
? (int) parser.getLong(
|
||||||
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
|
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
|
||||||
DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
|
DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
|
||||||
: (int) parser.getLong(
|
: (int) parser.getLong(
|
||||||
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
|
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
|
||||||
DEFAULT_MAX_ICON_DIMENSION_DP);
|
DEFAULT_MAX_ICON_DIMENSION_DP));
|
||||||
|
|
||||||
mMaxIconDimension = injectDipToPixel(iconDimensionDp);
|
mMaxIconDimension = injectDipToPixel(iconDimensionDp);
|
||||||
|
|
||||||
@@ -1128,7 +1128,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) {
|
if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) {
|
||||||
return; // Caller is valid.
|
return; // Caller is valid.
|
||||||
}
|
}
|
||||||
throw new SecurityException("Caller UID= doesn't own " + packageName);
|
throw new SecurityException("Calling package name mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
void postToHandler(Runnable r) {
|
void postToHandler(Runnable r) {
|
||||||
@@ -1425,6 +1425,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIconMaxDimensions(String packageName, int userId) throws RemoteException {
|
public int getIconMaxDimensions(String packageName, int userId) throws RemoteException {
|
||||||
|
verifyCaller(packageName, userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
return mMaxIconDimension;
|
return mMaxIconDimension;
|
||||||
}
|
}
|
||||||
@@ -1445,7 +1447,15 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
getUserShortcutsLocked(userId).resetThrottling();
|
getUserShortcutsLocked(userId).resetThrottling();
|
||||||
}
|
}
|
||||||
scheduleSaveUser(userId);
|
scheduleSaveUser(userId);
|
||||||
Slog.i(TAG, "ShortcutManager: throttling counter reset");
|
Slog.i(TAG, "ShortcutManager: throttling counter reset for user " + userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetAllThrottlingInner() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mRawLastResetTime = injectCurrentTimeMillis();
|
||||||
|
}
|
||||||
|
scheduleSaveBaseState();
|
||||||
|
Slog.i(TAG, "ShortcutManager: throttling counter reset for all users");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We override this method in unit tests to do a simpler check.
|
// We override this method in unit tests to do a simpler check.
|
||||||
@@ -1528,14 +1538,20 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
|
|
||||||
// === House keeping ===
|
// === House keeping ===
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
|
||||||
|
cleanUpPackageLocked(packageName, owningUserId, packageUserId,
|
||||||
|
/* forceForCommandLine= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all the information associated with a package. This will really remove all the
|
* Remove all the information associated with a package. This will really remove all the
|
||||||
* information, including the restore information (i.e. it'll remove packages even if they're
|
* information, including the restore information (i.e. it'll remove packages even if they're
|
||||||
* shadow).
|
* shadow).
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
private void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId,
|
||||||
void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
|
boolean forceForCommandLine) {
|
||||||
if (isPackageInstalled(packageName, packageUserId)) {
|
if (!forceForCommandLine && isPackageInstalled(packageName, packageUserId)) {
|
||||||
wtf("Package " + packageName + " is still installed for user " + packageUserId);
|
wtf("Package " + packageName + " is still installed for user " + packageUserId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1863,9 +1879,15 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName,
|
Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName,
|
||||||
packageUserId));
|
packageUserId));
|
||||||
}
|
}
|
||||||
|
handlePackageRemovedInner(packageName, packageUserId, /* forceForCommandLine =*/ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handlePackageRemovedInner(String packageName, @UserIdInt int packageUserId,
|
||||||
|
boolean forceForCommandLine) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
forEachLoadedUserLocked(user ->
|
forEachLoadedUserLocked(user ->
|
||||||
cleanUpPackageLocked(packageName, user.getUserId(), packageUserId));
|
cleanUpPackageLocked(packageName, user.getUserId(), packageUserId,
|
||||||
|
forceForCommandLine));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2046,12 +2068,21 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
pw.print(formatTime(next));
|
pw.print(formatTime(next));
|
||||||
pw.println();
|
pw.println();
|
||||||
|
|
||||||
|
pw.print(" Config:");
|
||||||
pw.print(" Max icon dim: ");
|
pw.print(" Max icon dim: ");
|
||||||
pw.print(mMaxIconDimension);
|
pw.println(mMaxIconDimension);
|
||||||
pw.print(" Icon format: ");
|
pw.print(" Icon format: ");
|
||||||
pw.print(mIconPersistFormat);
|
pw.println(mIconPersistFormat);
|
||||||
pw.print(" Icon quality: ");
|
pw.print(" Icon quality: ");
|
||||||
pw.println(mIconPersistQuality);
|
pw.println(mIconPersistQuality);
|
||||||
|
pw.print(" saveDelayMillis:");
|
||||||
|
pw.println(mSaveDelayMillis);
|
||||||
|
pw.print(" resetInterval:");
|
||||||
|
pw.println(mResetInterval);
|
||||||
|
pw.print(" maxDailyUpdates:");
|
||||||
|
pw.println(mMaxDailyUpdates);
|
||||||
|
pw.print(" maxDynamicShortcuts:");
|
||||||
|
pw.println(mMaxDynamicShortcuts);
|
||||||
pw.println();
|
pw.println();
|
||||||
|
|
||||||
pw.println(" Stats:");
|
pw.println(" Stats:");
|
||||||
@@ -2142,6 +2173,9 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
case "reset-throttling":
|
case "reset-throttling":
|
||||||
handleResetThrottling();
|
handleResetThrottling();
|
||||||
break;
|
break;
|
||||||
|
case "reset-all-throttling":
|
||||||
|
handleResetAllThrottling();
|
||||||
|
break;
|
||||||
case "override-config":
|
case "override-config":
|
||||||
handleOverrideConfig();
|
handleOverrideConfig();
|
||||||
break;
|
break;
|
||||||
@@ -2160,6 +2194,9 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
case "unload-user":
|
case "unload-user":
|
||||||
handleUnloadUser();
|
handleUnloadUser();
|
||||||
break;
|
break;
|
||||||
|
case "clear-shortcuts":
|
||||||
|
handleClearShortcuts();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return handleDefaultCommands(cmd);
|
return handleDefaultCommands(cmd);
|
||||||
}
|
}
|
||||||
@@ -2179,9 +2216,12 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
pw.println("cmd shortcut reset-package-throttling [--user USER_ID] PACKAGE");
|
pw.println("cmd shortcut reset-package-throttling [--user USER_ID] PACKAGE");
|
||||||
pw.println(" Reset throttling for a package");
|
pw.println(" Reset throttling for a package");
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.println("cmd shortcut reset-throttling");
|
pw.println("cmd shortcut reset-throttling [--user USER_ID]");
|
||||||
pw.println(" Reset throttling for all packages and users");
|
pw.println(" Reset throttling for all packages and users");
|
||||||
pw.println();
|
pw.println();
|
||||||
|
pw.println("cmd shortcut reset-all-throttling");
|
||||||
|
pw.println(" Reset the throttling state for all users");
|
||||||
|
pw.println();
|
||||||
pw.println("cmd shortcut override-config CONFIG");
|
pw.println("cmd shortcut override-config CONFIG");
|
||||||
pw.println(" Override the configuration for testing (will last until reboot)");
|
pw.println(" Override the configuration for testing (will last until reboot)");
|
||||||
pw.println();
|
pw.println();
|
||||||
@@ -2201,13 +2241,23 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
pw.println(" Unload a user from the memory");
|
pw.println(" Unload a user from the memory");
|
||||||
pw.println(" (This should not affect any observable behavior)");
|
pw.println(" (This should not affect any observable behavior)");
|
||||||
pw.println();
|
pw.println();
|
||||||
|
pw.println("cmd shortcut clear-shortcuts [--user USER_ID] PACKAGE");
|
||||||
|
pw.println(" Remove all shortcuts from a package, including pinned shortcuts");
|
||||||
|
pw.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int handleResetThrottling() throws CommandException {
|
private void handleResetThrottling() throws CommandException {
|
||||||
parseOptions(/* takeUser =*/ true);
|
parseOptions(/* takeUser =*/ true);
|
||||||
|
|
||||||
|
Slog.i(TAG, "cmd: handleResetThrottling");
|
||||||
|
|
||||||
resetThrottlingInner(mUserId);
|
resetThrottlingInner(mUserId);
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
private void handleResetAllThrottling() {
|
||||||
|
Slog.i(TAG, "cmd: handleResetAllThrottling");
|
||||||
|
|
||||||
|
resetAllThrottlingInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleResetPackageThrottling() throws CommandException {
|
private void handleResetPackageThrottling() throws CommandException {
|
||||||
@@ -2215,6 +2265,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
|
|
||||||
final String packageName = getNextArgRequired();
|
final String packageName = getNextArgRequired();
|
||||||
|
|
||||||
|
Slog.i(TAG, "cmd: handleResetPackageThrottling: " + packageName);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
getPackageShortcutsLocked(packageName, mUserId).resetRateLimitingForCommandLine();
|
getPackageShortcutsLocked(packageName, mUserId).resetRateLimitingForCommandLine();
|
||||||
saveUserLocked(mUserId);
|
saveUserLocked(mUserId);
|
||||||
@@ -2224,6 +2276,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
private void handleOverrideConfig() throws CommandException {
|
private void handleOverrideConfig() throws CommandException {
|
||||||
final String config = getNextArgRequired();
|
final String config = getNextArgRequired();
|
||||||
|
|
||||||
|
Slog.i(TAG, "cmd: handleOverrideConfig: " + config);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (!updateConfigurationLocked(config)) {
|
if (!updateConfigurationLocked(config)) {
|
||||||
throw new CommandException("override-config failed. See logcat for details.");
|
throw new CommandException("override-config failed. See logcat for details.");
|
||||||
@@ -2232,6 +2286,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleResetConfig() {
|
private void handleResetConfig() {
|
||||||
|
Slog.i(TAG, "cmd: handleResetConfig");
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
loadConfigurationLocked();
|
loadConfigurationLocked();
|
||||||
}
|
}
|
||||||
@@ -2276,8 +2332,20 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
private void handleUnloadUser() throws CommandException {
|
private void handleUnloadUser() throws CommandException {
|
||||||
parseOptions(/* takeUser =*/ true);
|
parseOptions(/* takeUser =*/ true);
|
||||||
|
|
||||||
|
Slog.i(TAG, "cmd: handleUnloadUser: " + mUserId);
|
||||||
|
|
||||||
ShortcutService.this.handleCleanupUser(mUserId);
|
ShortcutService.this.handleCleanupUser(mUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleClearShortcuts() throws CommandException {
|
||||||
|
parseOptions(/* takeUser =*/ true);
|
||||||
|
final String packageName = getNextArgRequired();
|
||||||
|
|
||||||
|
Slog.i(TAG, "cmd: handleClearShortcuts: " + mUserId + ", " + packageName);
|
||||||
|
|
||||||
|
ShortcutService.this.handlePackageRemovedInner(packageName, mUserId,
|
||||||
|
/* forceForCommandLine= */ true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Unit test support ===
|
// === Unit test support ===
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import android.util.Log;
|
|||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.KeyCharacterMap;
|
import android.view.KeyCharacterMap;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
|
|||||||
easymocklib \
|
easymocklib \
|
||||||
guava \
|
guava \
|
||||||
android-support-test \
|
android-support-test \
|
||||||
mockito-target
|
mockito-target \
|
||||||
|
ShortcutManagerTestUtils
|
||||||
|
|
||||||
LOCAL_JAVA_LIBRARIES := android.test.runner
|
LOCAL_JAVA_LIBRARIES := android.test.runner
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.spy;
|
|||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -608,14 +609,6 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
addPackage(packageName, uid, version, packageName);
|
addPackage(packageName, uid, version, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> List<T> list(T... array) {
|
|
||||||
return Arrays.asList(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> Set<T> set(Set<T> in) {
|
|
||||||
return new ArraySet<T>(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Signature[] genSignatures(String... signatures) {
|
private Signature[] genSignatures(String... signatures) {
|
||||||
final Signature[] sigs = new Signature[signatures.length];
|
final Signature[] sigs = new Signature[signatures.length];
|
||||||
for (int i = 0; i < signatures.length; i++){
|
for (int i = 0; i < signatures.length; i++){
|
||||||
@@ -799,33 +792,6 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
runTestOnUiThread(() -> {});
|
runTestOnUiThread(() -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bundle makeBundle(Object... keysAndValues) {
|
|
||||||
Preconditions.checkState((keysAndValues.length % 2) == 0);
|
|
||||||
|
|
||||||
if (keysAndValues.length == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final Bundle ret = new Bundle();
|
|
||||||
|
|
||||||
for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
|
|
||||||
final String key = keysAndValues[i].toString();
|
|
||||||
final Object value = keysAndValues[i + 1];
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
ret.putString(key, null);
|
|
||||||
} else if (value instanceof Integer) {
|
|
||||||
ret.putInt(key, (Integer) value);
|
|
||||||
} else if (value instanceof String) {
|
|
||||||
ret.putString(key, (String) value);
|
|
||||||
} else if (value instanceof Bundle) {
|
|
||||||
ret.putBundle(key, (Bundle) value);
|
|
||||||
} else {
|
|
||||||
fail("Type not supported yet: " + value.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a shortcut with an ID.
|
* Make a shortcut with an ID.
|
||||||
*/
|
*/
|
||||||
@@ -923,20 +889,6 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
return new ComponentName(mClientContext, clazz);
|
return new ComponentName(mClientContext, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> Set<T> makeSet(T... values) {
|
|
||||||
final HashSet<T> ret = new HashSet<>();
|
|
||||||
for (T s : values) {
|
|
||||||
ret.add(s);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void resetAll(Collection<?> mocks) {
|
|
||||||
for (Object o : mocks) {
|
|
||||||
reset(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
|
private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
|
||||||
for (ShortcutInfo s : list) {
|
for (ShortcutInfo s : list) {
|
||||||
@@ -957,94 +909,14 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
|
assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
public static List<ShortcutInfo> assertAllNotHaveIcon(
|
||||||
private List<ShortcutInfo> assertShortcutIds(@NonNull List<ShortcutInfo> actualShortcuts,
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
String... expectedIds) {
|
|
||||||
final HashSet<String> expected = new HashSet<>(list(expectedIds));
|
|
||||||
final HashSet<String> actual = new HashSet<>();
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
actual.add(s.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the sets.
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllHaveIntents(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
assertNotNull("ID " + s.getId(), s.getIntent());
|
|
||||||
}
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllNotHaveIntents(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
assertNull("ID " + s.getId(), s.getIntent());
|
|
||||||
}
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllHaveTitle(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
assertNotNull("ID " + s.getId(), s.getTitle());
|
|
||||||
}
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllNotHaveTitle(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
assertNull("ID " + s.getId(), s.getTitle());
|
|
||||||
}
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllNotHaveIcon(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
assertNull("ID " + s.getId(), s.getIcon());
|
assertNull("ID " + s.getId(), s.getIcon());
|
||||||
}
|
}
|
||||||
return actualShortcuts;
|
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> assertAllHaveIcon(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
|
|
||||||
}
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
|
private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
|
||||||
int shortcutFlags) {
|
int shortcutFlags) {
|
||||||
@@ -1055,87 +927,6 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
return actualShortcuts;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllPinned(@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_PINNED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<ShortcutInfo> assertAllDynamicOrPinned(
|
|
||||||
@NonNull List<ShortcutInfo> actualShortcuts) {
|
|
||||||
for (ShortcutInfo s : actualShortcuts) {
|
|
||||||
assertTrue("ID " + s.getId(), s.isDynamic() || s.isPinned());
|
|
||||||
}
|
|
||||||
return actualShortcuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertDynamicOnly(ShortcutInfo si) {
|
|
||||||
assertTrue(si.isDynamic());
|
|
||||||
assertFalse(si.isPinned());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertPinnedOnly(ShortcutInfo si) {
|
|
||||||
assertFalse(si.isDynamic());
|
|
||||||
assertTrue(si.isPinned());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertDynamicAndPinned(ShortcutInfo si) {
|
|
||||||
assertTrue(si.isDynamic());
|
|
||||||
assertTrue(si.isPinned());
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertBundleEmpty(BaseBundle b) {
|
|
||||||
assertTrue(b == null || b.size() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
|
private ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
|
||||||
return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
|
return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
|
||||||
}
|
}
|
||||||
@@ -1718,7 +1509,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
assertFalse(mManager.setDynamicShortcuts(list(si2)));
|
assertFalse(mManager.setDynamicShortcuts(list(si2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIcons() {
|
public void testIcons() throws IOException {
|
||||||
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
|
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
|
||||||
final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
|
final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
|
||||||
final Icon res512x512 = Icon.createWithResource(getTestContext(), R.drawable.black_512x512);
|
final Icon res512x512 = Icon.createWithResource(getTestContext(), R.drawable.black_512x512);
|
||||||
@@ -2242,7 +2033,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
getCallingUser())),
|
getCallingUser())),
|
||||||
"s1", "s3");
|
"s1", "s3");
|
||||||
|
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
IllegalArgumentException.class, "package name must also be set", () -> {
|
IllegalArgumentException.class, "package name must also be set", () -> {
|
||||||
mLauncherApps.getShortcuts(buildQuery(
|
mLauncherApps.getShortcuts(buildQuery(
|
||||||
/* time =*/ 0, /* package= */ null, list("id"),
|
/* time =*/ 0, /* package= */ null, list("id"),
|
||||||
@@ -3341,20 +3132,6 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
assertEquals(0, shortcuts.getValue().size());
|
assertEquals(0, shortcuts.getValue().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCallbackNotReceived(LauncherApps.Callback mock) {
|
|
||||||
verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
|
|
||||||
any(UserHandle.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertCallbackReceived(LauncherApps.Callback mock,
|
|
||||||
UserHandle user, String packageName, String... ids) {
|
|
||||||
ArgumentCaptor<List> shortcutsCaptor = ArgumentCaptor.forClass(List.class);
|
|
||||||
|
|
||||||
verify(mock, times(1)).onShortcutsChanged(eq(packageName), shortcutsCaptor.capture(),
|
|
||||||
eq(user));
|
|
||||||
assertShortcutIds(shortcutsCaptor.getValue(), ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLauncherCallback_crossProfile() throws Throwable {
|
public void testLauncherCallback_crossProfile() throws Throwable {
|
||||||
prepareCrossProfileDataSet();
|
prepareCrossProfileDataSet();
|
||||||
|
|
||||||
@@ -3724,18 +3501,18 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
|
|
||||||
// Check the registered packages.
|
// Check the registered packages.
|
||||||
dumpsysOnLogcat();
|
dumpsysOnLogcat();
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
|
set(PackageWithUser.of(USER_10, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_10, LAUNCHER_2)),
|
PackageWithUser.of(USER_10, LAUNCHER_2)),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_1", "s0_2");
|
"s0_1", "s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -3756,18 +3533,18 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
mService.cleanUpPackageLocked("abc", USER_0, USER_0);
|
mService.cleanUpPackageLocked("abc", USER_0, USER_0);
|
||||||
|
|
||||||
// No changes.
|
// No changes.
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
|
set(PackageWithUser.of(USER_10, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_10, LAUNCHER_2)),
|
PackageWithUser.of(USER_10, LAUNCHER_2)),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_1", "s0_2");
|
"s0_1", "s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -3787,18 +3564,18 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
uninstallPackage(USER_0, CALLING_PACKAGE_1);
|
uninstallPackage(USER_0, CALLING_PACKAGE_1);
|
||||||
mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0);
|
mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0);
|
||||||
|
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
|
set(PackageWithUser.of(USER_10, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_10, LAUNCHER_2)),
|
PackageWithUser.of(USER_10, LAUNCHER_2)),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_2");
|
"s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -3818,17 +3595,17 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
uninstallPackage(USER_10, LAUNCHER_1);
|
uninstallPackage(USER_10, LAUNCHER_1);
|
||||||
mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10);
|
mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10);
|
||||||
|
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_10, LAUNCHER_2)),
|
set(PackageWithUser.of(USER_10, LAUNCHER_2)),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_2");
|
"s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -3846,17 +3623,17 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
uninstallPackage(USER_10, CALLING_PACKAGE_2);
|
uninstallPackage(USER_10, CALLING_PACKAGE_2);
|
||||||
mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10);
|
mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10);
|
||||||
|
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1),
|
assertEquals(set(CALLING_PACKAGE_1),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_10, LAUNCHER_2)),
|
set(PackageWithUser.of(USER_10, LAUNCHER_2)),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_2");
|
"s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -3874,17 +3651,17 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
uninstallPackage(USER_10, LAUNCHER_2);
|
uninstallPackage(USER_10, LAUNCHER_2);
|
||||||
mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10);
|
mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10);
|
||||||
|
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_1),
|
assertEquals(set(CALLING_PACKAGE_1),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(),
|
set(),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_2");
|
"s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -3902,16 +3679,16 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
uninstallPackage(USER_10, CALLING_PACKAGE_1);
|
uninstallPackage(USER_10, CALLING_PACKAGE_1);
|
||||||
mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10);
|
mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10);
|
||||||
|
|
||||||
assertEquals(makeSet(CALLING_PACKAGE_2),
|
assertEquals(set(CALLING_PACKAGE_2),
|
||||||
set(user0.getAllPackages().keySet()));
|
hashSet(user0.getAllPackages().keySet()));
|
||||||
assertEquals(makeSet(),
|
assertEquals(set(),
|
||||||
set(user10.getAllPackages().keySet()));
|
hashSet(user10.getAllPackages().keySet()));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
|
set(PackageWithUser.of(USER_0, LAUNCHER_1),
|
||||||
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
PackageWithUser.of(USER_0, LAUNCHER_2)),
|
||||||
set(user0.getAllLaunchers().keySet()));
|
hashSet(user0.getAllLaunchers().keySet()));
|
||||||
assertEquals(makeSet(),
|
assertEquals(set(),
|
||||||
set(user10.getAllLaunchers().keySet()));
|
hashSet(user10.getAllLaunchers().keySet()));
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
|
||||||
"s0_2");
|
"s0_2");
|
||||||
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
|
||||||
@@ -5052,7 +4829,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
assertShortcutIds(
|
assertShortcutIds(
|
||||||
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
|
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
|
||||||
/* empty */);
|
/* empty */);
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
SecurityException.class, "", () -> {
|
SecurityException.class, "", () -> {
|
||||||
mLauncherApps.getShortcuts(
|
mLauncherApps.getShortcuts(
|
||||||
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
|
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
|
||||||
@@ -5131,7 +4908,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
assertShortcutIds(
|
assertShortcutIds(
|
||||||
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
|
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
|
||||||
"s1", "s4");
|
"s1", "s4");
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
SecurityException.class, "unrelated profile", () -> {
|
SecurityException.class, "unrelated profile", () -> {
|
||||||
mLauncherApps.getShortcuts(
|
mLauncherApps.getShortcuts(
|
||||||
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
|
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
|
||||||
@@ -5147,12 +4924,12 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
assertShortcutIds(
|
assertShortcutIds(
|
||||||
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
|
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
|
||||||
/* empty */);
|
/* empty */);
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
SecurityException.class, "unrelated profile", () -> {
|
SecurityException.class, "unrelated profile", () -> {
|
||||||
mLauncherApps.getShortcuts(
|
mLauncherApps.getShortcuts(
|
||||||
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0);
|
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0);
|
||||||
});
|
});
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
SecurityException.class, "unrelated profile", () -> {
|
SecurityException.class, "unrelated profile", () -> {
|
||||||
mLauncherApps.getShortcuts(
|
mLauncherApps.getShortcuts(
|
||||||
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
|
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
|
||||||
@@ -5163,16 +4940,16 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
// ShortcutInfo tests
|
// ShortcutInfo tests
|
||||||
|
|
||||||
public void testShortcutInfoMissingMandatoryFields() {
|
public void testShortcutInfoMissingMandatoryFields() {
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
"ID must be provided",
|
"ID must be provided",
|
||||||
() -> new ShortcutInfo.Builder(getTestContext()).build());
|
() -> new ShortcutInfo.Builder(getTestContext()).build());
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
"title must be provided",
|
"title must be provided",
|
||||||
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").build()
|
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").build()
|
||||||
.enforceMandatoryFields());
|
.enforceMandatoryFields());
|
||||||
TestUtils.assertExpectException(
|
assertExpectException(
|
||||||
NullPointerException.class,
|
NullPointerException.class,
|
||||||
"Intent must be provided",
|
"Intent must be provided",
|
||||||
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").setTitle("x").build()
|
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").setTitle("x").build()
|
||||||
@@ -5493,7 +5270,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
dumpsysOnLogcat("test1", /* force= */ true);
|
dumpsysOnLogcat("test1", /* force= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDumpsys_withIcons() {
|
public void testDumpsys_withIcons() throws IOException {
|
||||||
testIcons();
|
testIcons();
|
||||||
// Dump after having some icons.
|
// Dump after having some icons.
|
||||||
dumpsysOnLogcat("test1", /* force= */ true);
|
dumpsysOnLogcat("test1", /* force= */ true);
|
||||||
|
|||||||
31
services/tests/shortcutmanagerutils/Android.mk
Normal file
31
services/tests/shortcutmanagerutils/Android.mk
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Copyright (C) 2016 The Android Open Source Project
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
$(call all-java-files-under, src)
|
||||||
|
|
||||||
|
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||||
|
mockito-target
|
||||||
|
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
|
||||||
|
LOCAL_MODULE := ShortcutManagerTestUtils
|
||||||
|
|
||||||
|
LOCAL_SDK_VERSION := current
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||||
@@ -0,0 +1,506 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.server.pm.shortcutmanagertest;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
import static junit.framework.Assert.assertNull;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
import static junit.framework.Assert.fail;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyList;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.LauncherApps;
|
||||||
|
import android.content.pm.ShortcutInfo;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.os.BaseBundle;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.test.MoreAsserts;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.hamcrest.BaseMatcher;
|
||||||
|
import org.hamcrest.Description;
|
||||||
|
import org.hamcrest.Matcher;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class ShortcutManagerTestUtils {
|
||||||
|
private static final String TAG = "ShortcutManagerUtils";
|
||||||
|
|
||||||
|
private static final boolean ENABLE_DUMPSYS = true; // DO NOT SUBMIT WITH true
|
||||||
|
|
||||||
|
private static final int STANDARD_TIMEOUT_SEC = 5;
|
||||||
|
|
||||||
|
private ShortcutManagerTestUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> readAll(ParcelFileDescriptor pfd) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
final ArrayList<String> ret = new ArrayList<>();
|
||||||
|
try (BufferedReader r = new BufferedReader(
|
||||||
|
new FileReader(pfd.getFileDescriptor()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = r.readLine()) != null) {
|
||||||
|
ret.add(line);
|
||||||
|
}
|
||||||
|
r.readLine();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
} finally {
|
||||||
|
pfd.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String concatResult(List<String> result) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for (String s : result) {
|
||||||
|
sb.append(s);
|
||||||
|
sb.append("\n");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> runCommand(Instrumentation instrumentation, String command) {
|
||||||
|
return runCommand(instrumentation, command, null);
|
||||||
|
}
|
||||||
|
private static List<String> runCommand(Instrumentation instrumentation, String command,
|
||||||
|
Predicate<List<String>> resultAsserter) {
|
||||||
|
Log.d(TAG, "Running command: " + command);
|
||||||
|
final List<String> result;
|
||||||
|
try {
|
||||||
|
result = readAll(
|
||||||
|
instrumentation.getUiAutomation().executeShellCommand(command));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
if (resultAsserter != null && !resultAsserter.test(result)) {
|
||||||
|
fail("Command '" + command + "' failed, output was:\n" + concatResult(result));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void runCommandForNoOutput(Instrumentation instrumentation, String command) {
|
||||||
|
runCommand(instrumentation, command, result -> result.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> runShortcutCommand(Instrumentation instrumentation, String command,
|
||||||
|
Predicate<List<String>> resultAsserter) {
|
||||||
|
return runCommand(instrumentation, "cmd shortcut " + command, resultAsserter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> runShortcutCommandForSuccess(Instrumentation instrumentation,
|
||||||
|
String command) {
|
||||||
|
return runShortcutCommand(instrumentation, command, result -> result.contains("Success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDefaultLauncher(Instrumentation instrumentation) {
|
||||||
|
final String PREFIX = "Launcher: ComponentInfo{";
|
||||||
|
final String POSTFIX = "}";
|
||||||
|
final List<String> result = runShortcutCommandForSuccess(
|
||||||
|
instrumentation, "get-default-launcher");
|
||||||
|
for (String s : result) {
|
||||||
|
if (s.startsWith(PREFIX) && s.endsWith(POSTFIX)) {
|
||||||
|
return s.substring(PREFIX.length(), s.length() - POSTFIX.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fail("Default launcher not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultLauncher(Instrumentation instrumentation, String component) {
|
||||||
|
runCommandForNoOutput(instrumentation, "cmd package set-home-activity " + component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultLauncher(Instrumentation instrumentation, Context packageContext) {
|
||||||
|
setDefaultLauncher(instrumentation, packageContext.getPackageName()
|
||||||
|
+ "/android.content.pm.cts.shortcutmanager.packages.Launcher");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void overrideConfig(Instrumentation instrumentation, String config) {
|
||||||
|
runShortcutCommandForSuccess(instrumentation, "override-config " + config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetConfig(Instrumentation instrumentation) {
|
||||||
|
runShortcutCommandForSuccess(instrumentation, "reset-config");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetThrottling(Instrumentation instrumentation) {
|
||||||
|
runShortcutCommandForSuccess(instrumentation, "reset-throttling");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetAllThrottling(Instrumentation instrumentation) {
|
||||||
|
runShortcutCommandForSuccess(instrumentation, "reset-all-throttling");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearShortcuts(Instrumentation instrumentation, int userId,
|
||||||
|
String packageName) {
|
||||||
|
runShortcutCommandForSuccess(instrumentation, "clear-shortcuts "
|
||||||
|
+ " --user " + userId + " " + packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpsysShortcut(Instrumentation instrumentation) {
|
||||||
|
if (!ENABLE_DUMPSYS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String s : runCommand(instrumentation, "dumpsys shortcut")) {
|
||||||
|
Log.e(TAG, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bundle makeBundle(Object... keysAndValues) {
|
||||||
|
assertTrue((keysAndValues.length % 2) == 0);
|
||||||
|
|
||||||
|
if (keysAndValues.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Bundle ret = new Bundle();
|
||||||
|
|
||||||
|
for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
|
||||||
|
final String key = keysAndValues[i].toString();
|
||||||
|
final Object value = keysAndValues[i + 1];
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
ret.putString(key, null);
|
||||||
|
} else if (value instanceof Integer) {
|
||||||
|
ret.putInt(key, (Integer) value);
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
ret.putString(key, (String) value);
|
||||||
|
} else if (value instanceof Bundle) {
|
||||||
|
ret.putBundle(key, (Bundle) value);
|
||||||
|
} else {
|
||||||
|
fail("Type not supported yet: " + value.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> list(T... array) {
|
||||||
|
return Arrays.asList(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Set<T> hashSet(Set<T> in) {
|
||||||
|
return new HashSet<T>(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Set<T> set(T... values) {
|
||||||
|
return set(v -> v, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, V> Set<T> set(Function<V, T> converter, V... values) {
|
||||||
|
return set(converter, Arrays.asList(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, V> Set<T> set(Function<V, T> converter, List<V> values) {
|
||||||
|
final HashSet<T> ret = new HashSet<>();
|
||||||
|
for (V v : values) {
|
||||||
|
ret.add(converter.apply(v));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetAll(Collection<?> mocks) {
|
||||||
|
for (Object o : mocks) {
|
||||||
|
reset(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
|
||||||
|
String expectedExceptionMessageRegex, Runnable r) {
|
||||||
|
assertExpectException("", expectedExceptionType, expectedExceptionMessageRegex, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertDynamicShortcutCountExceeded(Runnable r) {
|
||||||
|
assertExpectException(IllegalArgumentException.class,
|
||||||
|
"Max number of dynamic shortcuts exceeded", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertExpectException(String message,
|
||||||
|
Class<? extends Throwable> expectedExceptionType,
|
||||||
|
String expectedExceptionMessageRegex, Runnable r) {
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
Assert.fail("Expected exception type " + expectedExceptionType.getName()
|
||||||
|
+ " was not thrown (message=" + message + ")");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Assert.assertTrue(
|
||||||
|
"Expected exception type was " + expectedExceptionType.getName()
|
||||||
|
+ " but caught " + e + " (message=" + message + ")",
|
||||||
|
expectedExceptionType.isAssignableFrom(e.getClass()));
|
||||||
|
if (expectedExceptionMessageRegex != null) {
|
||||||
|
MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertShortcutIds(List<ShortcutInfo> actualShortcuts,
|
||||||
|
String... expectedIds) {
|
||||||
|
final HashSet<String> expected = new HashSet<>(list(expectedIds));
|
||||||
|
final HashSet<String> actual = new HashSet<>();
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
actual.add(s.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the sets.
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllHaveIntents(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertNotNull("ID " + s.getId(), s.getIntent());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllNotHaveIntents(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertNull("ID " + s.getId(), s.getIntent());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllHaveTitle(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertNotNull("ID " + s.getId(), s.getTitle());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllNotHaveTitle(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertNull("ID " + s.getId(), s.getTitle());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllHaveIconResId(
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllHaveIconFile(
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllHaveIcon(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllKeyFieldsOnly(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllNotKeyFieldsOnly(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllDynamic(List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertTrue("ID " + s.getId(), s.isDynamic());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertTrue("ID " + s.getId(), s.isPinned());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> assertAllDynamicOrPinned(
|
||||||
|
List<ShortcutInfo> actualShortcuts) {
|
||||||
|
for (ShortcutInfo s : actualShortcuts) {
|
||||||
|
assertTrue("ID " + s.getId(), s.isDynamic() || s.isPinned());
|
||||||
|
}
|
||||||
|
return actualShortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertDynamicOnly(ShortcutInfo si) {
|
||||||
|
assertTrue(si.isDynamic());
|
||||||
|
assertFalse(si.isPinned());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertPinnedOnly(ShortcutInfo si) {
|
||||||
|
assertFalse(si.isDynamic());
|
||||||
|
assertTrue(si.isPinned());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertDynamicAndPinned(ShortcutInfo si) {
|
||||||
|
assertTrue(si.isDynamic());
|
||||||
|
assertTrue(si.isPinned());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertBitmapSize(int expectedWidth, int expectedHeight, Bitmap bitmap) {
|
||||||
|
assertEquals("width", expectedWidth, bitmap.getWidth());
|
||||||
|
assertEquals("height", expectedHeight, bitmap.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap pfdToBitmap(ParcelFileDescriptor pfd) {
|
||||||
|
assertNotNull(pfd);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
|
||||||
|
} finally {
|
||||||
|
pfd.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertBundleEmpty(BaseBundle b) {
|
||||||
|
assertTrue(b == null || b.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertCallbackNotReceived(LauncherApps.Callback mock) {
|
||||||
|
verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
|
||||||
|
any(UserHandle.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertCallbackReceived(LauncherApps.Callback mock,
|
||||||
|
UserHandle user, String packageName, String... ids) {
|
||||||
|
verify(mock).onShortcutsChanged(eq(packageName), checkShortcutIds(ids),
|
||||||
|
eq(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkAssertSuccess(Runnable r) {
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
return true;
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T checkArgument(Predicate<T> checker, String description,
|
||||||
|
List<T> matchedCaptor) {
|
||||||
|
final Matcher<T> m = new BaseMatcher<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean matches(Object item) {
|
||||||
|
if (item == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final T value = (T) item;
|
||||||
|
if (!checker.test(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchedCaptor != null) {
|
||||||
|
matchedCaptor.add(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describeTo(Description d) {
|
||||||
|
d.appendText(description);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Mockito.argThat(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShortcutInfo> checkShortcutIds(String... ids) {
|
||||||
|
return checkArgument((List<ShortcutInfo> list) -> {
|
||||||
|
final Set<String> actualSet = set(si -> si.getId(), list);
|
||||||
|
return actualSet.equals(set(ids));
|
||||||
|
|
||||||
|
}, "Shortcut IDs=[" + Arrays.toString(ids) + "]", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void waitUntil(String message, BooleanSupplier condition) {
|
||||||
|
waitUntil(message, condition, STANDARD_TIMEOUT_SEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void waitUntil(String message, BooleanSupplier condition, int timeoutSeconds) {
|
||||||
|
final long timeout = System.currentTimeMillis() + (timeoutSeconds * 1000L);
|
||||||
|
while (System.currentTimeMillis() < timeout) {
|
||||||
|
if (condition.getAsBoolean()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fail("Timed out for: " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user