From 4d1de7da79010be3e1f0eb85aa50b6002a8241fd Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Thu, 23 Feb 2017 10:32:18 -0800 Subject: [PATCH] Add new internal resolve method Instant apps are unique in that any application can start them with a VIEW/BROWSABLE while only very few apps can see an instant app using queryIntentActivites, etc... In order to support this dichotomy, we need an internal hook to resolution for activity start. Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest Bug: 25119046 Change-Id: If6974c09c733ff0417ef72cabb9d9e9aca86c37c --- .../android/content/pm/PackageManagerInternal.java | 6 ++ .../android/server/am/ActivityStackSupervisor.java | 6 +- .../android/server/pm/PackageManagerService.java | 77 +++++++++++++++++----- .../core/java/com/android/server/pm/Settings.java | 2 +- 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 94fe572360b5..6272822ac308 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -306,4 +306,10 @@ public abstract class PackageManagerInternal { */ public abstract boolean setEnabledOverlayPackages(int userId, String targetPackageName, List overlayPackageNames); + + /** + * Resolves an intent, allowing instant apps to be resolved. + */ + public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType, + int flags, int userId); } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 1e33bb9a3362..6f79bc271198 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1196,13 +1196,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) { - try { - return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType, + synchronized (mService) { + return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType, PackageManager.MATCH_INSTANT | PackageManager.MATCH_DEFAULT_ONLY | flags | ActivityManagerService.STOCK_PM_FLAGS, userId); - } catch (RemoteException e) { } - return null; } ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index fe2fb66822f1..33bd3508b998 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4012,8 +4012,17 @@ public class PackageManagerService extends IPackageManager.Stub { /** * Update given flags when being used to request {@link ResolveInfo}. + *

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: + *

*/ - 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; @@ -4025,15 +4034,24 @@ public class PackageManagerService extends IPackageManager.Stub { 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 @@ -5558,17 +5576,23 @@ public class PackageManagerService extends IPackageManager.Stub { @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 query = queryIntentActivitiesInternal(intent, resolvedType, - flags, userId); + flags, userId, includeInstantApp); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); final ResolveInfo bestChoice = @@ -5590,7 +5614,7 @@ public class PackageManagerService extends IPackageManager.Stub { } 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 query = queryIntentActivitiesInternal(intent, resolvedType, flags, userId); synchronized (mPackages) { @@ -5749,6 +5773,13 @@ public class PackageManagerService extends IPackageManager.Stub { 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()); @@ -5867,7 +5898,7 @@ public class PackageManagerService extends IPackageManager.Stub { List 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) { @@ -6035,7 +6066,7 @@ public class PackageManagerService extends IPackageManager.Stub { // 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; @@ -6094,9 +6125,14 @@ public class PackageManagerService extends IPackageManager.Stub { private @NonNull List queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int userId) { + return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false); + } + + private @NonNull List 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"); @@ -6723,7 +6759,7 @@ public class PackageManagerService extends IPackageManager.Stub { 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"); @@ -6903,7 +6939,7 @@ public class PackageManagerService extends IPackageManager.Stub { private @NonNull List 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) { @@ -6940,7 +6976,7 @@ public class PackageManagerService extends IPackageManager.Stub { @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 query = queryIntentServicesInternal(intent, resolvedType, flags, userId); if (query != null) { if (query.size() >= 1) { @@ -6962,7 +6998,7 @@ public class PackageManagerService extends IPackageManager.Stub { private @NonNull List 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) { @@ -7006,7 +7042,7 @@ public class PackageManagerService extends IPackageManager.Stub { private @NonNull List 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) { @@ -23003,13 +23039,18 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); return targetPackages; } - @Override public boolean setEnabledOverlayPackages(int userId, String targetPackageName, List 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 diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index a8a5ff056521..a057e9b566c2 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3370,7 +3370,7 @@ final class Settings { private void applyDefaultPreferredActivityLPw(PackageManagerService service, Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp, IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) { - flags = service.updateFlagsForResolve(flags, userId, intent); + flags = service.updateFlagsForResolve(flags, userId, intent, false); List ri = service.mActivities.queryIntent(intent, intent.getType(), flags, 0); if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent -- 2.11.0