/**
* Update given flags when being used to request {@link ResolveInfo}.
+ * <p>Instant apps are resolved specially, depending upon context. Minimally,
+ * {@code}flags{@code} must have the {@link PackageManager#MATCH_INSTANT}
+ * flag set. However, this flag is only honoured in three circumstances:
+ * <ul>
+ * <li>when called from a system process</li>
+ * <li>when the caller holds the permission {@code android.permission.ACCESS_INSTANT_APPS}</li>
+ * <li>when resolution occurs to start an activity with a {@code android.intent.action.VIEW}
+ * action and a {@code android.intent.category.BROWSABLE} category</li>
+ * </ul>
*/
- int updateFlagsForResolve(int flags, int userId, Object cookie) {
+ int updateFlagsForResolve(int flags, int userId, Intent intent, boolean includeInstantApp) {
// Safe mode means we shouldn't match any third-party components
if (mSafeMode) {
flags |= PackageManager.MATCH_SYSTEM_ONLY;
flags |= PackageManager.MATCH_INSTANT;
} else {
// Otherwise, prevent leaking ephemeral components
+ final boolean isSpecialProcess =
+ callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID
+ || callingUid == 0;
+ final boolean allowMatchInstant =
+ (includeInstantApp
+ && Intent.ACTION_VIEW.equals(intent.getAction())
+ && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
+ && hasWebURI(intent))
+ || isSpecialProcess
+ || mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
- if (callingUid != Process.SYSTEM_UID
- && callingUid != Process.SHELL_UID
- && callingUid != 0) {
- // Unless called from the system process
+ if (!allowMatchInstant) {
flags &= ~PackageManager.MATCH_INSTANT;
}
}
- return updateFlagsForComponent(flags, userId, cookie);
+ return updateFlagsForComponent(flags, userId, intent /*cookie*/);
}
@Override
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
+ return resolveIntentInternal(
+ intent, resolvedType, flags, userId, false /*includeInstantApp*/);
+ }
+
+ private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
+ int flags, int userId, boolean includeInstantApp) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
- flags, userId);
+ flags, userId, includeInstantApp);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
}
intent = updateIntentForResolve(intent);
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
- final int flags = updateFlagsForResolve(0, userId, intent);
+ final int flags = updateFlagsForResolve(0, userId, intent, false);
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
userId);
synchronized (mPackages) {
if (ri != null) {
return ri;
}
+ // If we have an ephemeral app, use it
+ for (int i = 0; i < N; i++) {
+ ri = query.get(i);
+ if (ri.activityInfo.applicationInfo.isInstantApp()) {
+ return ri;
+ }
+ }
ri = new ResolveInfo(mResolveInfo);
ri.activityInfo = new ActivityInfo(ri.activityInfo);
ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
List<ResolveInfo> query, int priority, boolean always,
boolean removeMatches, boolean debug, int userId) {
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, false);
intent = updateIntentForResolve(intent);
// writer
synchronized (mPackages) {
// cross-profile app linking works only towards the parent.
final UserInfo parent = getProfileParent(sourceUserId);
synchronized(mPackages) {
- int flags = updateFlagsForResolve(0, parent.id, intent);
+ int flags = updateFlagsForResolve(0, parent.id, intent, false);
CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
intent, resolvedType, flags, sourceUserId, parent.id);
return xpDomainInfo != null;
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
+ return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false);
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
+ String resolvedType, int flags, int userId, boolean includeInstantApp) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */,
"query intent activities");
Intent[] specifics, String[] specificTypes, Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, false);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */,
"query intent activity options");
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, false);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@Override
public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, false);
List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
if (query != null) {
if (query.size() >= 1) {
private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, false);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
private @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent);
+ flags = updateFlagsForResolve(flags, userId, intent, false);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
return targetPackages;
}
-
@Override
public boolean setEnabledOverlayPackages(int userId, String targetPackageName,
List<String> overlayPackageNames) {
// TODO: implement when we integrate OMS properly
return false;
}
+
+ public ResolveInfo resolveIntent(Intent intent, String resolvedType,
+ int flags, int userId) {
+ return resolveIntentInternal(
+ intent, resolvedType, flags, userId, true /*includeInstantApp*/);
+ }
}
@Override