Merge \"ShortcutManager: Make sure persisted default launcher still exists.\" into nyc-mr1-dev
am: 5b080d4e90
Change-Id: I8f1db21f5372a23b6584c1275aa0a2ee6edadb53
This commit is contained in:
@@ -260,9 +260,6 @@ class ShortcutPackage extends ShortcutPackageItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Check max dynamic count.
|
|
||||||
// mShortcutUser.mService.enforceMaxDynamicShortcuts(newDynamicCount);
|
|
||||||
|
|
||||||
// If it was originally pinned, the new one should be pinned too.
|
// If it was originally pinned, the new one should be pinned too.
|
||||||
if (wasPinned) {
|
if (wasPinned) {
|
||||||
newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
|
newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.annotation.UserIdInt;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ShortcutInfo;
|
import android.content.pm.ShortcutInfo;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
@@ -79,7 +78,7 @@ public class ShortcutParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final ActivityInfo activityInfoWithMetadata =
|
final ActivityInfo activityInfoWithMetadata =
|
||||||
service.injectGetActivityInfoWithMetadata(
|
service.getActivityInfoWithMetadata(
|
||||||
activityInfoNoMetadata.getComponentName(), userId);
|
activityInfoNoMetadata.getComponentName(), userId);
|
||||||
if (activityInfoWithMetadata != null) {
|
if (activityInfoWithMetadata != null) {
|
||||||
result = parseShortcutsOneFile(
|
result = parseShortcutsOneFile(
|
||||||
|
|||||||
@@ -232,6 +232,13 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
|
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
|
private static List<ResolveInfo> EMPTY_RESOLVE_INFO = new ArrayList<>(0);
|
||||||
|
|
||||||
|
private static Predicate<ResolveInfo> ACTIVITY_NOT_EXPORTED =
|
||||||
|
ri -> !ri.activityInfo.exported;
|
||||||
|
|
||||||
|
private static Predicate<PackageInfo> PACKAGE_NOT_INSTALLED = pi -> !isInstalled(pi);
|
||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@@ -318,8 +325,9 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
int RESOURCE_NAME_LOOKUP = 10;
|
int RESOURCE_NAME_LOOKUP = 10;
|
||||||
int GET_LAUNCHER_ACTIVITY = 11;
|
int GET_LAUNCHER_ACTIVITY = 11;
|
||||||
int CHECK_LAUNCHER_ACTIVITY = 12;
|
int CHECK_LAUNCHER_ACTIVITY = 12;
|
||||||
|
int IS_ACTIVITY_ENABLED = 13;
|
||||||
|
|
||||||
int COUNT = CHECK_LAUNCHER_ACTIVITY + 1;
|
int COUNT = IS_ACTIVITY_ENABLED + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object mStatLock = new Object();
|
final Object mStatLock = new Object();
|
||||||
@@ -348,11 +356,11 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ShortcutService(Context context) {
|
public ShortcutService(Context context) {
|
||||||
this(context, BackgroundThread.get().getLooper());
|
this(context, BackgroundThread.get().getLooper(), /*onyForPackgeManagerApis*/ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
ShortcutService(Context context, Looper looper) {
|
ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) {
|
||||||
mContext = Preconditions.checkNotNull(context);
|
mContext = Preconditions.checkNotNull(context);
|
||||||
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
|
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
|
||||||
mHandler = new Handler(looper);
|
mHandler = new Handler(looper);
|
||||||
@@ -363,6 +371,10 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
mUsageStatsManagerInternal = Preconditions.checkNotNull(
|
mUsageStatsManagerInternal = Preconditions.checkNotNull(
|
||||||
LocalServices.getService(UsageStatsManagerInternal.class));
|
LocalServices.getService(UsageStatsManagerInternal.class));
|
||||||
|
|
||||||
|
if (onlyForPackageManagerApis) {
|
||||||
|
return; // Don't do anything further. For unit tests only.
|
||||||
|
}
|
||||||
|
|
||||||
mPackageMonitor.register(context, looper, UserHandle.ALL, /* externalStorage= */ false);
|
mPackageMonitor.register(context, looper, UserHandle.ALL, /* externalStorage= */ false);
|
||||||
|
|
||||||
injectRegisterUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE
|
injectRegisterUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE
|
||||||
@@ -1571,11 +1583,6 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
removeIcon(userId, target);
|
removeIcon(userId, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.getActivity() != null &&
|
|
||||||
!source.getActivity().equals(target.getActivity())) {
|
|
||||||
// TODO When activity is changing, check the dynamic count.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note copyNonNullFieldsFrom() does the "updatable with?" check too.
|
// Note copyNonNullFieldsFrom() does the "updatable with?" check too.
|
||||||
target.copyNonNullFieldsFrom(source);
|
target.copyNonNullFieldsFrom(source);
|
||||||
target.setTimestamp(injectCurrentTimeMillis());
|
target.setTimestamp(injectCurrentTimeMillis());
|
||||||
@@ -1915,10 +1922,17 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
} else {
|
} else {
|
||||||
detected = user.getDefaultLauncherComponent();
|
detected = user.getDefaultLauncherComponent();
|
||||||
|
|
||||||
// TODO: Make sure it's still enabled.
|
if (detected != null) {
|
||||||
|
if (injectIsActivityEnabledAndExported(detected, userId)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.v(TAG, "Cached launcher: " + detected);
|
Slog.v(TAG, "Cached launcher: " + detected);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "Cached launcher " + detected + " no longer exists");
|
||||||
|
detected = null;
|
||||||
|
user.setDefaultLauncherComponent(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detected == null) {
|
if (detected == null) {
|
||||||
@@ -2363,6 +2377,10 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
return; // Don't delete shadow information.
|
return; // Don't delete shadow information.
|
||||||
}
|
}
|
||||||
if (!isPackageInstalled(spi.getPackageName(), spi.getPackageUserId())) {
|
if (!isPackageInstalled(spi.getPackageName(), spi.getPackageUserId())) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Uninstalled: " + spi.getPackageName()
|
||||||
|
+ " user " + spi.getPackageUserId());
|
||||||
|
}
|
||||||
gonePackages.add(PackageWithUser.of(spi));
|
gonePackages.add(PackageWithUser.of(spi));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2457,21 +2475,26 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
|
|
||||||
// === PackageManager interaction ===
|
// === PackageManager interaction ===
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link PackageInfo} unless it's uninstalled or disabled.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
PackageInfo getPackageInfoWithSignatures(String packageName, @UserIdInt int userId) {
|
final PackageInfo getPackageInfoWithSignatures(String packageName, @UserIdInt int userId) {
|
||||||
return injectPackageInfo(packageName, userId, true);
|
return getPackageInfo(packageName, userId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link PackageInfo} unless it's uninstalled or disabled.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
PackageInfo getPackageInfo(String packageName, @UserIdInt int userId) {
|
final PackageInfo getPackageInfo(String packageName, @UserIdInt int userId) {
|
||||||
return injectPackageInfo(packageName, userId, false);
|
return getPackageInfo(packageName, userId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
|
int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
return mIPackageManager.getPackageUid(packageName, PACKAGE_MATCH_FLAGS
|
return mIPackageManager.getPackageUid(packageName, PACKAGE_MATCH_FLAGS, userId);
|
||||||
, userId);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Shouldn't happen.
|
// Shouldn't happen.
|
||||||
Slog.wtf(TAG, "RemoteException", e);
|
Slog.wtf(TAG, "RemoteException", e);
|
||||||
@@ -2481,16 +2504,30 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link PackageInfo} unless it's uninstalled or disabled.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
PackageInfo injectPackageInfo(String packageName, @UserIdInt int userId,
|
final PackageInfo getPackageInfo(String packageName, @UserIdInt int userId,
|
||||||
|
boolean getSignatures) {
|
||||||
|
return isInstalledOrNull(injectPackageInfoWithUninstalled(
|
||||||
|
packageName, userId, getSignatures));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use directly; this returns uninstalled packages too.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@VisibleForTesting
|
||||||
|
PackageInfo injectPackageInfoWithUninstalled(String packageName, @UserIdInt int userId,
|
||||||
boolean getSignatures) {
|
boolean getSignatures) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
return mIPackageManager.getPackageInfo(packageName, PACKAGE_MATCH_FLAGS
|
return mIPackageManager.getPackageInfo(
|
||||||
| (getSignatures ? PackageManager.GET_SIGNATURES : 0)
|
packageName, PACKAGE_MATCH_FLAGS
|
||||||
, userId);
|
| (getSignatures ? PackageManager.GET_SIGNATURES : 0), userId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Shouldn't happen.
|
// Shouldn't happen.
|
||||||
Slog.wtf(TAG, "RemoteException", e);
|
Slog.wtf(TAG, "RemoteException", e);
|
||||||
@@ -2504,9 +2541,22 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link ApplicationInfo} unless it's uninstalled or disabled.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
ApplicationInfo injectApplicationInfo(String packageName, @UserIdInt int userId) {
|
final ApplicationInfo getApplicationInfo(String packageName, @UserIdInt int userId) {
|
||||||
|
return isInstalledOrNull(injectApplicationInfoWithUninstalled(packageName, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use directly; this returns uninstalled packages too.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@VisibleForTesting
|
||||||
|
ApplicationInfo injectApplicationInfoWithUninstalled(
|
||||||
|
String packageName, @UserIdInt int userId) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -2522,13 +2572,27 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link ActivityInfo} with its metadata unless it's uninstalled or disabled.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ActivityInfo injectGetActivityInfoWithMetadata(ComponentName activity, @UserIdInt int userId) {
|
final ActivityInfo getActivityInfoWithMetadata(ComponentName activity, @UserIdInt int userId) {
|
||||||
|
return isInstalledOrNull(injectGetActivityInfoWithMetadataWithUninstalled(
|
||||||
|
activity, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use directly; this returns uninstalled packages too.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@VisibleForTesting
|
||||||
|
ActivityInfo injectGetActivityInfoWithMetadataWithUninstalled(
|
||||||
|
ComponentName activity, @UserIdInt int userId) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
return mIPackageManager.getActivityInfo(activity,
|
return mIPackageManager.getActivityInfo(activity,
|
||||||
PACKAGE_MATCH_FLAGS | PackageManager.GET_META_DATA, userId);
|
(PACKAGE_MATCH_FLAGS | PackageManager.GET_META_DATA), userId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Shouldn't happen.
|
// Shouldn't happen.
|
||||||
Slog.wtf(TAG, "RemoteException", e);
|
Slog.wtf(TAG, "RemoteException", e);
|
||||||
@@ -2540,18 +2604,20 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
/**
|
||||||
|
* Return all installed and enabled packages.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
List<PackageInfo> injectInstalledPackages(@UserIdInt int userId) {
|
final List<PackageInfo> getInstalledPackages(@UserIdInt int userId) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
final ParceledListSlice<PackageInfo> parceledList =
|
final List<PackageInfo> all = injectGetPackagesWithUninstalled(userId);
|
||||||
mIPackageManager.getInstalledPackages(PACKAGE_MATCH_FLAGS, userId);
|
|
||||||
if (parceledList == null) {
|
all.removeIf(PACKAGE_NOT_INSTALLED);
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
return all;
|
||||||
return parceledList.getList();
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Shouldn't happen.
|
// Shouldn't happen.
|
||||||
Slog.wtf(TAG, "RemoteException", e);
|
Slog.wtf(TAG, "RemoteException", e);
|
||||||
@@ -2563,17 +2629,31 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use directly; this returns uninstalled packages too.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@VisibleForTesting
|
||||||
|
List<PackageInfo> injectGetPackagesWithUninstalled(@UserIdInt int userId)
|
||||||
|
throws RemoteException {
|
||||||
|
final ParceledListSlice<PackageInfo> parceledList =
|
||||||
|
mIPackageManager.getInstalledPackages(PACKAGE_MATCH_FLAGS, userId);
|
||||||
|
if (parceledList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return parceledList.getList();
|
||||||
|
}
|
||||||
|
|
||||||
private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime,
|
private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime,
|
||||||
Consumer<ApplicationInfo> callback) {
|
Consumer<ApplicationInfo> callback) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime);
|
Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime);
|
||||||
}
|
}
|
||||||
final List<PackageInfo> list = injectInstalledPackages(userId);
|
final List<PackageInfo> list = getInstalledPackages(userId);
|
||||||
for (int i = list.size() - 1; i >= 0; i--) {
|
for (int i = list.size() - 1; i >= 0; i--) {
|
||||||
final PackageInfo pi = list.get(i);
|
final PackageInfo pi = list.get(i);
|
||||||
|
|
||||||
if (((pi.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0)
|
if (pi.lastUpdateTime >= lastScanTime) {
|
||||||
&& (pi.lastUpdateTime >= lastScanTime)) {
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Found updated package " + pi.packageName);
|
Slog.d(TAG, "Found updated package " + pi.packageName);
|
||||||
}
|
}
|
||||||
@@ -2582,13 +2662,37 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isApplicationFlagSet(String packageName, int userId, int flags) {
|
private boolean isApplicationFlagSet(@NonNull String packageName, int userId, int flags) {
|
||||||
final ApplicationInfo ai = injectApplicationInfo(packageName, userId);
|
final ApplicationInfo ai = injectApplicationInfoWithUninstalled(packageName, userId);
|
||||||
return (ai != null) && ((ai.flags & flags) == flags);
|
return (ai != null) && ((ai.flags & flags) == flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isInstalled(@Nullable ApplicationInfo ai) {
|
||||||
|
return (ai != null) && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInstalled(@Nullable PackageInfo pi) {
|
||||||
|
return (pi != null) && isInstalled(pi.applicationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInstalled(@Nullable ActivityInfo ai) {
|
||||||
|
return (ai != null) && isInstalled(ai.applicationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ApplicationInfo isInstalledOrNull(ApplicationInfo ai) {
|
||||||
|
return isInstalled(ai) ? ai : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PackageInfo isInstalledOrNull(PackageInfo pi) {
|
||||||
|
return isInstalled(pi) ? pi : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActivityInfo isInstalledOrNull(ActivityInfo ai) {
|
||||||
|
return isInstalled(ai) ? ai : null;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isPackageInstalled(String packageName, int userId) {
|
boolean isPackageInstalled(String packageName, int userId) {
|
||||||
return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_INSTALLED);
|
return getApplicationInfo(packageName, userId) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -2619,20 +2723,46 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as queryIntentActivitiesAsUser, except it makes sure the package is installed,
|
||||||
|
* and only returns exported activities.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@VisibleForTesting
|
||||||
|
List<ResolveInfo> queryActivities(@NonNull Intent baseIntent,
|
||||||
|
@NonNull String packageName, @Nullable ComponentName activity, int userId) {
|
||||||
|
|
||||||
|
baseIntent.setPackage(Preconditions.checkNotNull(packageName));
|
||||||
|
if (activity != null) {
|
||||||
|
baseIntent.setComponent(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<ResolveInfo> resolved =
|
||||||
|
mContext.getPackageManager().queryIntentActivitiesAsUser(
|
||||||
|
baseIntent, PACKAGE_MATCH_FLAGS, userId);
|
||||||
|
if (resolved == null || resolved.size() == 0) {
|
||||||
|
return EMPTY_RESOLVE_INFO;
|
||||||
|
}
|
||||||
|
// Make sure the package is installed.
|
||||||
|
if (!isInstalled(resolved.get(0).activityInfo)) {
|
||||||
|
return EMPTY_RESOLVE_INFO;
|
||||||
|
}
|
||||||
|
resolved.removeIf(ACTIVITY_NOT_EXPORTED);
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the main activity that is enabled and exported. If multiple activities are found,
|
||||||
|
* return the first one.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) {
|
ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
final Intent intent = getMainActivityIntent();
|
|
||||||
intent.setPackage(packageName);
|
|
||||||
|
|
||||||
final List<ResolveInfo> resolved =
|
final List<ResolveInfo> resolved =
|
||||||
mContext.getPackageManager().queryIntentActivitiesAsUser(
|
queryActivities(getMainActivityIntent(), packageName, null, userId);
|
||||||
intent, PACKAGE_MATCH_FLAGS, userId);
|
return resolved.size() == 0 ? null : resolved.get(0).activityInfo.getComponentName();
|
||||||
|
|
||||||
return (resolved == null || resolved.size() == 0)
|
|
||||||
? null : resolved.get(0).activityInfo.getComponentName();
|
|
||||||
} finally {
|
} finally {
|
||||||
injectRestoreCallingIdentity(token);
|
injectRestoreCallingIdentity(token);
|
||||||
|
|
||||||
@@ -2640,19 +2770,17 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether an activity is enabled, exported and main.
|
||||||
|
*/
|
||||||
boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) {
|
boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
final Intent intent = getMainActivityIntent();
|
|
||||||
intent.setPackage(activity.getPackageName());
|
|
||||||
intent.setComponent(activity);
|
|
||||||
|
|
||||||
final List<ResolveInfo> resolved =
|
final List<ResolveInfo> resolved =
|
||||||
mContext.getPackageManager().queryIntentActivitiesAsUser(
|
queryActivities(getMainActivityIntent(), activity.getPackageName(),
|
||||||
intent, PACKAGE_MATCH_FLAGS, userId);
|
activity, userId);
|
||||||
|
return resolved.size() > 0;
|
||||||
return resolved != null && resolved.size() > 0;
|
|
||||||
} finally {
|
} finally {
|
||||||
injectRestoreCallingIdentity(token);
|
injectRestoreCallingIdentity(token);
|
||||||
|
|
||||||
@@ -2660,19 +2788,15 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all the enabled, exported and main activities from a package.
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) {
|
List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) {
|
||||||
final long start = injectElapsedRealtime();
|
final long start = injectElapsedRealtime();
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
final Intent intent = getMainActivityIntent();
|
return queryActivities(getMainActivityIntent(), packageName, null, userId);
|
||||||
intent.setPackage(packageName);
|
|
||||||
|
|
||||||
final List<ResolveInfo> resolved =
|
|
||||||
mContext.getPackageManager().queryIntentActivitiesAsUser(
|
|
||||||
intent, PACKAGE_MATCH_FLAGS, userId);
|
|
||||||
|
|
||||||
return (resolved != null) ? resolved : new ArrayList<>(0);
|
|
||||||
} finally {
|
} finally {
|
||||||
injectRestoreCallingIdentity(token);
|
injectRestoreCallingIdentity(token);
|
||||||
|
|
||||||
@@ -2680,6 +2804,24 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether an activity is enabled and exported.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean injectIsActivityEnabledAndExported(
|
||||||
|
@NonNull ComponentName activity, @UserIdInt int userId) {
|
||||||
|
final long start = injectElapsedRealtime();
|
||||||
|
final long token = injectClearCallingIdentity();
|
||||||
|
try {
|
||||||
|
return queryActivities(new Intent(), activity.getPackageName(), activity, userId)
|
||||||
|
.size() > 0;
|
||||||
|
} finally {
|
||||||
|
injectRestoreCallingIdentity(token);
|
||||||
|
|
||||||
|
logDurationStat(Stats.IS_ACTIVITY_ENABLED, start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean injectIsSafeModeEnabled() {
|
boolean injectIsSafeModeEnabled() {
|
||||||
final long token = injectClearCallingIdentity();
|
final long token = injectClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -2839,6 +2981,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
|||||||
dumpStatLS(pw, p, Stats.RESOURCE_NAME_LOOKUP, "resourceNameLookup");
|
dumpStatLS(pw, p, Stats.RESOURCE_NAME_LOOKUP, "resourceNameLookup");
|
||||||
dumpStatLS(pw, p, Stats.GET_LAUNCHER_ACTIVITY, "getLauncherActivity");
|
dumpStatLS(pw, p, Stats.GET_LAUNCHER_ACTIVITY, "getLauncherActivity");
|
||||||
dumpStatLS(pw, p, Stats.CHECK_LAUNCHER_ACTIVITY, "checkLauncherActivity");
|
dumpStatLS(pw, p, Stats.CHECK_LAUNCHER_ACTIVITY, "checkLauncherActivity");
|
||||||
|
dumpStatLS(pw, p, Stats.IS_ACTIVITY_ENABLED, "isActivityEnabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mUsers.size(); i++) {
|
for (int i = 0; i < mUsers.size(); i++) {
|
||||||
|
|||||||
@@ -108,9 +108,53 @@
|
|||||||
<service android:name="com.android.server.job.MockPriorityJobService"
|
<service android:name="com.android.server.job.MockPriorityJobService"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
<activity android:name="com.android.server.pm.ShortcutManagerTest$ShortcutActivity" />
|
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity" />
|
||||||
<activity android:name="com.android.server.pm.ShortcutManagerTest$ShortcutActivity2" />
|
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity2" />
|
||||||
<activity android:name="com.android.server.pm.ShortcutManagerTest$ShortcutActivity3" />
|
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity3" />
|
||||||
|
|
||||||
|
<activity android:name="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="true" android:exported="true" />
|
||||||
|
|
||||||
|
<activity-alias android:name="a.ShortcutEnabled"
|
||||||
|
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="true" android:exported="true">
|
||||||
|
</activity-alias>
|
||||||
|
<activity-alias android:name="a.ShortcutDisabled"
|
||||||
|
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="false" android:exported="true">
|
||||||
|
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_5"/>
|
||||||
|
</activity-alias>
|
||||||
|
<activity-alias android:name="a.ShortcutUnexported"
|
||||||
|
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="true" android:exported="false">
|
||||||
|
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_5"/>
|
||||||
|
</activity-alias>
|
||||||
|
<activity-alias android:name="a.Shortcut1"
|
||||||
|
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="true" android:exported="true">
|
||||||
|
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_1"/>
|
||||||
|
</activity-alias>
|
||||||
|
|
||||||
|
<activity-alias android:name="a.DisabledMain"
|
||||||
|
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="false" android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity-alias>
|
||||||
|
|
||||||
|
<activity-alias android:name="a.UnexportedMain"
|
||||||
|
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
|
||||||
|
android:enabled="true" android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity-alias>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<instrumentation
|
<instrumentation
|
||||||
|
|||||||
@@ -103,8 +103,6 @@ import java.util.Set;
|
|||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
||||||
protected static final String TAG = "ShortcutManagerTest";
|
protected static final String TAG = "ShortcutManagerTest";
|
||||||
@@ -206,7 +204,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
IUidObserver mUidObserver;
|
IUidObserver mUidObserver;
|
||||||
|
|
||||||
public ShortcutServiceTestable(ServiceContext context, Looper looper) {
|
public ShortcutServiceTestable(ServiceContext context, Looper looper) {
|
||||||
super(context, looper);
|
super(context, looper, /* onyForPackageManagerApis */ false);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,24 +299,26 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
PackageInfo injectPackageInfo(String packageName, @UserIdInt int userId,
|
PackageInfo injectPackageInfoWithUninstalled(String packageName, @UserIdInt int userId,
|
||||||
boolean getSignatures) {
|
boolean getSignatures) {
|
||||||
return getInjectedPackageInfo(packageName, userId, getSignatures);
|
return getInjectedPackageInfo(packageName, userId, getSignatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ApplicationInfo injectApplicationInfo(String packageName, @UserIdInt int userId) {
|
ApplicationInfo injectApplicationInfoWithUninstalled(
|
||||||
PackageInfo pi = injectPackageInfo(packageName, userId, /* getSignatures= */ false);
|
String packageName, @UserIdInt int userId) {
|
||||||
|
PackageInfo pi = injectPackageInfoWithUninstalled(
|
||||||
|
packageName, userId, /* getSignatures= */ false);
|
||||||
return pi != null ? pi.applicationInfo : null;
|
return pi != null ? pi.applicationInfo : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
List<PackageInfo> injectInstalledPackages(@UserIdInt int userId) {
|
List<PackageInfo> injectGetPackagesWithUninstalled(@UserIdInt int userId) {
|
||||||
return getInstalledPackages(userId);
|
return BaseShortcutManagerTest.this.getInstalledPackagesWithUninstalled(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ActivityInfo injectGetActivityInfoWithMetadata(ComponentName activity,
|
ActivityInfo injectGetActivityInfoWithMetadataWithUninstalled(ComponentName activity,
|
||||||
@UserIdInt int userId) {
|
@UserIdInt int userId) {
|
||||||
final PackageInfo pi = mContext.injectGetActivitiesWithMetadata(
|
final PackageInfo pi = mContext.injectGetActivitiesWithMetadata(
|
||||||
activity.getPackageName(), userId);
|
activity.getPackageName(), userId);
|
||||||
@@ -369,6 +369,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
return mMainActivityFetcher.apply(packageName, userId);
|
return mMainActivityFetcher.apply(packageName, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) {
|
||||||
|
return mEnabledActivityChecker.test(activity, userId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
|
XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
|
||||||
return mContext.injectXmlMetaData(activityInfo, key);
|
return mContext.injectXmlMetaData(activityInfo, key);
|
||||||
@@ -951,7 +956,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PackageInfo> getInstalledPackages(int userId) {
|
private List<PackageInfo> getInstalledPackagesWithUninstalled(int userId) {
|
||||||
final ArrayList<PackageInfo> ret = new ArrayList<>();
|
final ArrayList<PackageInfo> ret = new ArrayList<>();
|
||||||
|
|
||||||
addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret);
|
addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret);
|
||||||
@@ -990,6 +995,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
ai.name = cn.getClassName();
|
ai.name = cn.getClassName();
|
||||||
ai.metaData = new Bundle();
|
ai.metaData = new Bundle();
|
||||||
ai.metaData.putInt(ShortcutParser.METADATA_KEY, activities.get(cn));
|
ai.metaData.putInt(ShortcutParser.METADATA_KEY, activities.get(cn));
|
||||||
|
ai.applicationInfo = ret.applicationInfo;
|
||||||
list.add(ai);
|
list.add(ai);
|
||||||
}
|
}
|
||||||
ret.activities = list.toArray(new ActivityInfo[list.size()]);
|
ret.activities = list.toArray(new ActivityInfo[list.size()]);
|
||||||
@@ -1462,14 +1468,18 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
return infoList.get(0);
|
return infoList.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Intent genPackageAddIntent(String pakcageName, int userId) {
|
protected Intent genPackageAddIntent(String packageName, int userId) {
|
||||||
|
installPackage(userId, packageName);
|
||||||
|
|
||||||
Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
|
Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
|
||||||
i.setData(Uri.parse("package:" + pakcageName));
|
i.setData(Uri.parse("package:" + packageName));
|
||||||
i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Intent genPackageDeleteIntent(String pakcageName, int userId) {
|
protected Intent genPackageDeleteIntent(String pakcageName, int userId) {
|
||||||
|
uninstallPackage(userId, pakcageName);
|
||||||
|
|
||||||
Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED);
|
Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED);
|
||||||
i.setData(Uri.parse("package:" + pakcageName));
|
i.setData(Uri.parse("package:" + pakcageName));
|
||||||
i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
||||||
@@ -1477,6 +1487,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Intent genPackageUpdateIntent(String pakcageName, int userId) {
|
protected Intent genPackageUpdateIntent(String pakcageName, int userId) {
|
||||||
|
installPackage(userId, pakcageName);
|
||||||
|
|
||||||
Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
|
Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
|
||||||
i.setData(Uri.parse("package:" + pakcageName));
|
i.setData(Uri.parse("package:" + pakcageName));
|
||||||
i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
|
|||||||
|
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.anyString;
|
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -86,7 +85,6 @@ import com.android.frameworks.servicestests.R;
|
|||||||
import com.android.server.pm.ShortcutService.ConfigConstants;
|
import com.android.server.pm.ShortcutService.ConfigConstants;
|
||||||
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
|
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
|
||||||
import com.android.server.pm.ShortcutUser.PackageWithUser;
|
import com.android.server.pm.ShortcutUser.PackageWithUser;
|
||||||
import com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.ShortcutListAsserter;
|
|
||||||
|
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
@@ -94,9 +92,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for ShortcutService and ShortcutManager.
|
* Tests for ShortcutService and ShortcutManager.
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
|
public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
|
||||||
|
|
||||||
private static Bundle sIntentExtras = makeBundle(
|
private static Bundle sIntentExtras = makeBundle(
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.ShortcutServiceInternal;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
|
||||||
|
import com.android.server.LocalServices;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for all the IPackageManager related methods in {@link ShortcutService}.
|
||||||
|
*
|
||||||
|
* All the tests here actually talks to the real IPackageManager, so we can't test complicated
|
||||||
|
* cases. Instead we just make sure they all work reasonably without at least crashing.
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
public class ShortcutManagerTest5 extends BaseShortcutManagerTest {
|
||||||
|
private ShortcutService mShortcutService;
|
||||||
|
|
||||||
|
private String mMyPackage;
|
||||||
|
private int mMyUserId;
|
||||||
|
|
||||||
|
public static class ShortcutEnabled extends Activity {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ShortcutDisabled extends Activity {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
|
||||||
|
mShortcutService = new ShortcutService(getTestContext(), Looper.getMainLooper(),
|
||||||
|
/* onyForPackageManagerApis */ true);
|
||||||
|
|
||||||
|
mMyPackage = getTestContext().getPackageName();
|
||||||
|
mMyUserId = android.os.Process.myUserHandle().getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetPackageUid() {
|
||||||
|
assertTrue(mShortcutService.injectGetPackageUid(
|
||||||
|
mMyPackage, mMyUserId) != 0);
|
||||||
|
|
||||||
|
assertEquals(-1, mShortcutService.injectGetPackageUid(
|
||||||
|
"no.such.package", mMyUserId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetPackageInfo() {
|
||||||
|
PackageInfo pi = mShortcutService.getPackageInfo(
|
||||||
|
mMyPackage, mMyUserId, /*signature*/ false);
|
||||||
|
assertEquals(mMyPackage, pi.packageName);
|
||||||
|
assertNull(pi.signatures);
|
||||||
|
|
||||||
|
pi = mShortcutService.getPackageInfo(
|
||||||
|
mMyPackage, mMyUserId, /*signature*/ true);
|
||||||
|
assertEquals(mMyPackage, pi.packageName);
|
||||||
|
assertNotNull(pi.signatures);
|
||||||
|
|
||||||
|
pi = mShortcutService.getPackageInfo(
|
||||||
|
"no.such.package", mMyUserId, /*signature*/ true);
|
||||||
|
assertNull(pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetApplicationInfo() {
|
||||||
|
ApplicationInfo ai = mShortcutService.getApplicationInfo(
|
||||||
|
mMyPackage, mMyUserId);
|
||||||
|
assertEquals(mMyPackage, ai.packageName);
|
||||||
|
|
||||||
|
ai = mShortcutService.getApplicationInfo(
|
||||||
|
"no.such.package", mMyUserId);
|
||||||
|
assertNull(ai);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetActivityInfoWithMetadata() {
|
||||||
|
// Disabled activity
|
||||||
|
ActivityInfo ai = mShortcutService.getActivityInfoWithMetadata(
|
||||||
|
new ComponentName(mMyPackage, "ShortcutDisabled"), mMyUserId);
|
||||||
|
assertNull(ai);
|
||||||
|
|
||||||
|
// Nonexistent
|
||||||
|
ai = mShortcutService.getActivityInfoWithMetadata(
|
||||||
|
new ComponentName("no.such.package", "ShortcutDisabled"), mMyUserId);
|
||||||
|
assertNull(ai);
|
||||||
|
|
||||||
|
// Existent, with no metadata.
|
||||||
|
ai = mShortcutService.getActivityInfoWithMetadata(
|
||||||
|
new ComponentName(mMyPackage, "a.ShortcutEnabled"), mMyUserId);
|
||||||
|
assertEquals(mMyPackage, ai.packageName);
|
||||||
|
assertEquals("a.ShortcutEnabled", ai.name);
|
||||||
|
assertNull(ai.loadXmlMetaData(getTestContext().getPackageManager(),
|
||||||
|
"android.app.shortcuts"));
|
||||||
|
|
||||||
|
// Existent, with a shortcut metadata.
|
||||||
|
ai = mShortcutService.getActivityInfoWithMetadata(
|
||||||
|
new ComponentName(mMyPackage, "a.Shortcut1"), mMyUserId);
|
||||||
|
assertEquals(mMyPackage, ai.packageName);
|
||||||
|
assertEquals("a.Shortcut1", ai.name);
|
||||||
|
XmlResourceParser meta = ai.loadXmlMetaData(getTestContext().getPackageManager(),
|
||||||
|
"android.app.shortcuts");
|
||||||
|
assertNotNull(meta);
|
||||||
|
meta.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetInstalledPackages() {
|
||||||
|
List<PackageInfo> apks = mShortcutService.getInstalledPackages(mMyUserId);
|
||||||
|
|
||||||
|
Set<String> expectedPackages = set("com.android.settings", mMyPackage);
|
||||||
|
for (PackageInfo pi : apks) {
|
||||||
|
expectedPackages.remove(pi.packageName);
|
||||||
|
}
|
||||||
|
assertEquals(set(), expectedPackages);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDefaultMainActivity() {
|
||||||
|
ComponentName cn = mShortcutService.injectGetDefaultMainActivity(
|
||||||
|
"com.android.settings", mMyUserId);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
ComponentName.unflattenFromString("com.android.settings/.Settings"),
|
||||||
|
cn);
|
||||||
|
|
||||||
|
// This package has no main activity.
|
||||||
|
assertNull(mShortcutService.injectGetDefaultMainActivity(
|
||||||
|
mMyPackage, mMyUserId));
|
||||||
|
|
||||||
|
// Nonexistent.
|
||||||
|
assertNull(mShortcutService.injectGetDefaultMainActivity(
|
||||||
|
"no.such.package", mMyUserId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsMainActivity() {
|
||||||
|
assertTrue(mShortcutService.injectIsMainActivity(
|
||||||
|
ComponentName.unflattenFromString("com.android.settings/.Settings"), mMyUserId));
|
||||||
|
assertFalse(mShortcutService.injectIsMainActivity(
|
||||||
|
ComponentName.unflattenFromString("com.android.settings/.xxx"), mMyUserId));
|
||||||
|
assertFalse(mShortcutService.injectIsMainActivity(
|
||||||
|
ComponentName.unflattenFromString("no.such.package/.xxx"), mMyUserId));
|
||||||
|
|
||||||
|
assertFalse(mShortcutService.injectIsMainActivity(
|
||||||
|
new ComponentName(mMyPackage, "a.DisabledMain"), mMyUserId));
|
||||||
|
assertFalse(mShortcutService.injectIsMainActivity(
|
||||||
|
new ComponentName(mMyPackage, "a.UnexportedMain"), mMyUserId));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetMainActivities() {
|
||||||
|
assertEquals(1, mShortcutService.injectGetMainActivities(
|
||||||
|
"com.android.settings", mMyUserId).size());
|
||||||
|
|
||||||
|
// This APK has no main activities.
|
||||||
|
assertEquals(0, mShortcutService.injectGetMainActivities(
|
||||||
|
mMyPackage, mMyUserId).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsActivityEnabledAndExported() {
|
||||||
|
assertTrue(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
ComponentName.unflattenFromString("com.android.settings/.Settings"), mMyUserId));
|
||||||
|
assertFalse(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
ComponentName.unflattenFromString("com.android.settings/.xxx"), mMyUserId));
|
||||||
|
assertFalse(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
ComponentName.unflattenFromString("no.such.package/.xxx"), mMyUserId));
|
||||||
|
|
||||||
|
assertTrue(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
new ComponentName(mMyPackage, "com.android.server.pm.ShortcutTestActivity"),
|
||||||
|
mMyUserId));
|
||||||
|
|
||||||
|
assertTrue(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
new ComponentName(mMyPackage, "a.ShortcutEnabled"), mMyUserId));
|
||||||
|
|
||||||
|
assertFalse(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
new ComponentName(mMyPackage, "a.ShortcutDisabled"), mMyUserId));
|
||||||
|
assertFalse(mShortcutService.injectIsActivityEnabledAndExported(
|
||||||
|
new ComponentName(mMyPackage, "a.ShortcutUnexported"), mMyUserId));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
public class ShortcutTestActivity extends Activity {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user