From c05f5d12d9a1b98221833ec0919d081a869d2486 Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Tue, 25 Apr 2017 11:11:40 -0700 Subject: [PATCH] Add concept of implicitly exposed components Implicitly exposed components are those that can still be accessed via generic startActivity() calls. However, they cannot be started by specifying a package or component. Additionally, package info can't be obtained if the package only has implicitly shared components. Change-Id: I404a4dff87559cfeee6ad78f7dcc7f5d849d6869 Fixes: b_37343345 Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest --- core/java/android/content/IntentFilter.java | 44 ++++++++-- .../java/android/content/pm/ActivityInfo.java | 23 +++++- .../android/content/pm/PackageManager.java | 10 ++- .../android/content/pm/PackageParser.java | 79 +++++++++++------- .../java/android/content/pm/ProviderInfo.java | 2 +- core/java/android/content/pm/ServiceInfo.java | 2 +- .../server/am/ActivityManagerService.java | 10 ++- .../com/android/server/am/BroadcastQueue.java | 2 +- .../server/pm/PackageManagerService.java | 80 ++++++++++++------- 9 files changed, 180 insertions(+), 72 deletions(-) diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index d64f018c3f2e8..c9bce530be3ed 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -16,6 +16,7 @@ package android.content; +import android.annotation.IntDef; import android.annotation.SystemApi; import android.net.Uri; import android.os.Parcel; @@ -33,6 +34,8 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Iterator; import java.util.Set; @@ -283,9 +286,22 @@ public class IntentFilter implements Parcelable { private static final int STATE_VERIFIED = 0x00001000; private int mVerifyState; - + /** @hide */ + public static final int VISIBILITY_NONE = 0; + /** @hide */ + public static final int VISIBILITY_EXPLICIT = 1; + /** @hide */ + public static final int VISIBILITY_IMPLICIT = 2; + /** @hide */ + @IntDef(prefix = { "VISIBILITY_" }, value = { + VISIBILITY_NONE, + VISIBILITY_EXPLICIT, + VISIBILITY_IMPLICIT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface InstantAppVisibility {} /** Whether or not the intent filter is visible to instant apps. */ - private boolean mVisibleToInstantApp; + private @InstantAppVisibility int mInstantAppVisibility; // These functions are the start of more optimized code for managing // the string sets... not yet implemented. @@ -452,7 +468,7 @@ public class IntentFilter implements Parcelable { } mHasPartialTypes = o.mHasPartialTypes; mVerifyState = o.mVerifyState; - mVisibleToInstantApp = o.mVisibleToInstantApp; + mInstantAppVisibility = o.mInstantAppVisibility; } /** @@ -655,12 +671,24 @@ public class IntentFilter implements Parcelable { } /** @hide */ - public void setVisibleToInstantApp(boolean visibleToInstantApp) { - mVisibleToInstantApp = visibleToInstantApp; + public void setVisibilityToInstantApp(@InstantAppVisibility int visibility) { + mInstantAppVisibility = visibility; + } + /** @hide */ + public @InstantAppVisibility int getVisibilityToInstantApp() { + return mInstantAppVisibility; } /** @hide */ public boolean isVisibleToInstantApp() { - return mVisibleToInstantApp; + return mInstantAppVisibility != VISIBILITY_NONE; + } + /** @hide */ + public boolean isExplicitlyVisibleToInstantApp() { + return mInstantAppVisibility == VISIBILITY_EXPLICIT; + } + /** @hide */ + public boolean isImplicitlyVisibleToInstantApp() { + return mInstantAppVisibility == VISIBILITY_IMPLICIT; } /** @@ -1859,7 +1887,7 @@ public class IntentFilter implements Parcelable { dest.writeInt(mPriority); dest.writeInt(mHasPartialTypes ? 1 : 0); dest.writeInt(getAutoVerify() ? 1 : 0); - dest.writeInt(isVisibleToInstantApp() ? 1 : 0); + dest.writeInt(mInstantAppVisibility); } /** @@ -1928,7 +1956,7 @@ public class IntentFilter implements Parcelable { mPriority = source.readInt(); mHasPartialTypes = source.readInt() > 0; setAutoVerify(source.readInt() > 0); - setVisibleToInstantApp(source.readInt() > 0); + setVisibilityToInstantApp(source.readInt()); } private final boolean findMimeType(String type) { diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index b01e6a156f959..0be0885c5bdcf 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -17,6 +17,7 @@ package android.content.pm; import android.annotation.IntDef; +import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration.NativeConfig; import android.os.Parcel; @@ -412,17 +413,33 @@ public class ActivityInfo extends ComponentInfo public static final int FLAG_ALWAYS_FOCUSABLE = 0x40000; /** - * Bit in {@link #flags} indicating if the activity is visible to ephemeral applications. + * Bit in {@link #flags} indicating if the activity is visible to instant + * applications. The activity is visible if it's either implicitly or + * explicitly exposed. * @hide */ - public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000; + public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000; + + /** + * Bit in {@link #flags} indicating if the activity is implicitly visible + * to instant applications. Implicitly visible activities are those that + * implement certain intent-filters: + * + * @hide + */ + public static final int FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP = 0x200000; /** * Bit in {@link #flags} indicating if the activity supports picture-in-picture mode. * See {@link android.R.attr#supportsPictureInPicture}. * @hide */ - public static final int FLAG_SUPPORTS_PICTURE_IN_PICTURE = 0x200000; + public static final int FLAG_SUPPORTS_PICTURE_IN_PICTURE = 0x400000; /** * @hide Bit in {@link #flags}: If set, this component will only be seen diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index ecaf7ebe07d28..d2468d97fdca8 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -461,11 +461,19 @@ public abstract class PackageManager { /** * Internal {@link PackageInfo} flag: include only components that are exposed to - * ephemeral apps. + * instant apps. Matched components may have been either explicitly or implicitly + * exposed. * @hide */ public static final int MATCH_VISIBLE_TO_INSTANT_APP_ONLY = 0x01000000; + /** + * Internal {@link PackageInfo} flag: include only components that have been + * explicitly exposed to instant apps. + * @hide + */ + public static final int MATCH_EXPLICITLY_VISIBLE_ONLY = 0x02000000; + /** * Internal flag used to indicate that a system component has done their * homework and verified that they correctly handle packages and components diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 86093512090e8..e4db0f07b8018 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4271,7 +4271,7 @@ public class PackageParser { boolean visibleToEphemeral = sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false); if (visibleToEphemeral) { - a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; owner.visibleToInstantApps = true; } @@ -4313,9 +4313,17 @@ public class PackageParser { a.intents.add(intent); } // adjust activity flags when we implicitly expose it via a browsable filter - intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent)); + final int visibility = visibleToEphemeral + ? IntentFilter.VISIBILITY_EXPLICIT + : !receiver && isImplicitlyExposedIntent(intent) + ? IntentFilter.VISIBILITY_IMPLICIT + : IntentFilter.VISIBILITY_NONE; + intent.setVisibilityToInstantApp(visibility); if (intent.isVisibleToInstantApp()) { - a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + if (intent.isImplicitlyVisibleToInstantApp()) { + a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; } if (LOG_UNSAFE_BROADCASTS && receiver && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) { @@ -4346,9 +4354,17 @@ public class PackageParser { owner.preferredActivityFilters.add(intent); } // adjust activity flags when we implicitly expose it via a browsable filter - intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent)); + final int visibility = visibleToEphemeral + ? IntentFilter.VISIBILITY_EXPLICIT + : !receiver && isImplicitlyExposedIntent(intent) + ? IntentFilter.VISIBILITY_IMPLICIT + : IntentFilter.VISIBILITY_NONE; + intent.setVisibilityToInstantApp(visibility); if (intent.isVisibleToInstantApp()) { - a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + if (intent.isImplicitlyVisibleToInstantApp()) { + a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; } } else if (parser.getName().equals("meta-data")) { if ((a.metaData = parseMetaData(res, parser, a.metaData, @@ -4358,16 +4374,18 @@ public class PackageParser { // we don't have an attribute [or it's false], but, we have meta-data if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) { visibleToEphemeral = true; // set in case there are more intent filters - a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; owner.visibleToInstantApps = true; // cycle through any filters already seen for (int i = a.intents.size() - 1; i >= 0; --i) { - a.intents.get(i).setVisibleToInstantApp(true /*visibleToInstantApp*/); + a.intents.get(i) + .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); } if (owner.preferredActivityFilters != null) { for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) { owner.preferredActivityFilters.get(i) - .setVisibleToInstantApp(true /*visibleToInstantApp*/); + .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); } } } @@ -4645,7 +4663,7 @@ public class PackageParser { // TODO add visibleToInstantApps attribute to activity alias final boolean visibleToEphemeral = - ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0); + ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0); sa.recycle(); @@ -4673,13 +4691,20 @@ public class PackageParser { + mArchiveSourcePath + " " + parser.getPositionDescription()); } else { - intent.setVisibleToInstantApp( - visibleToEphemeral || isImplicitlyExposedIntent(intent)); a.intents.add(intent); } // adjust activity flags when we implicitly expose it via a browsable filter + final int visibility = visibleToEphemeral + ? IntentFilter.VISIBILITY_EXPLICIT + : isImplicitlyExposedIntent(intent) + ? IntentFilter.VISIBILITY_IMPLICIT + : IntentFilter.VISIBILITY_NONE; + intent.setVisibilityToInstantApp(visibility); if (intent.isVisibleToInstantApp()) { - a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + if (intent.isImplicitlyVisibleToInstantApp()) { + a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; } } else if (parser.getName().equals("meta-data")) { if ((a.metaData=parseMetaData(res, parser, a.metaData, @@ -4822,7 +4847,7 @@ public class PackageParser { final boolean visibleToEphemeral = sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false); if (visibleToEphemeral) { - p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL; + p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; owner.visibleToInstantApps = true; } @@ -4874,12 +4899,11 @@ public class PackageParser { intent, outError)) { return false; } - outInfo.intents.add(intent); - // adjust provider flags when we implicitly expose it via a browsable filter - intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent)); - if (intent.isVisibleToInstantApp()) { - outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL; + if (visibleToEphemeral) { + intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); + outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; } + outInfo.intents.add(intent); } else if (parser.getName().equals("meta-data")) { if ((outInfo.metaData=parseMetaData(res, parser, @@ -4889,11 +4913,12 @@ public class PackageParser { // we don't have an attribute [or it's false], but, we have meta-data if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) { visibleToEphemeral = true; // set in case there are more intent filters - outInfo.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; owner.visibleToInstantApps = true; // cycle through any filters already seen for (int i = outInfo.intents.size() - 1; i >= 0; --i) { - outInfo.intents.get(i).setVisibleToInstantApp(true /*visibleToInstantApp*/); + outInfo.intents.get(i) + .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); } } @@ -5149,7 +5174,7 @@ public class PackageParser { boolean visibleToEphemeral = sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false); if (visibleToEphemeral) { - s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL; + s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; owner.visibleToInstantApps = true; } @@ -5180,10 +5205,9 @@ public class PackageParser { intent, outError)) { return null; } - // adjust activity flags when we implicitly expose it via a browsable filter - intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent)); - if (intent.isVisibleToInstantApp()) { - s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL; + if (visibleToEphemeral) { + intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); + s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; } s.intents.add(intent); } else if (parser.getName().equals("meta-data")) { @@ -5194,11 +5218,12 @@ public class PackageParser { // we don't have an attribute [or it's false], but, we have meta-data if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) { visibleToEphemeral = true; // set in case there are more intent filters - s.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; + s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; owner.visibleToInstantApps = true; // cycle through any filters already seen for (int i = s.intents.size() - 1; i >= 0; --i) { - s.intents.get(i).setVisibleToInstantApp(true /*visibleToInstantApp*/); + s.intents.get(i) + .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); } } } else { diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index 8c21563198abb..91dc06e121382 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -79,7 +79,7 @@ public final class ProviderInfo extends ComponentInfo * Bit in {@link #flags} indicating if the provider is visible to ephemeral applications. * @hide */ - public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000; + public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000; /** * Bit in {@link #flags}: If set, a single instance of the provider will diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index f0766beb5d3f7..c683ea5d9739d 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -59,7 +59,7 @@ public class ServiceInfo extends ComponentInfo * Bit in {@link #flags} indicating if the service is visible to ephemeral applications. * @hide */ - public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000; + public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000; /** * Bit in {@link #flags}: If set, a single instance of the service will diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 45c2054d6587b..41f3b1470b7b9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -11255,9 +11255,13 @@ public class ActivityManagerService extends IActivityManager.Stub holder.provider = null; return holder; } - // Don't expose instant app providers - if (cpr.appInfo.isInstantApp()) { - return null; + // Don't expose providers between normal apps and instant apps + try { + if (AppGlobals.getPackageManager() + .resolveContentProvider(name, 0 /*flags*/, userId) == null) { + return null; + } + } catch (RemoteException e) { } final long origId = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 349180fd28a96..d08298bcac058 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1180,7 +1180,7 @@ public final class BroadcastQueue { skip = true; } if (!skip && r.callerInstantApp - && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0 + && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0 && r.callingUid != info.activityInfo.applicationInfo.uid) { Slog.w(TAG, "Instant App Denial: receiving " + r.intent diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index faa99342b9dc6..7dc159ba4e611 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4074,14 +4074,26 @@ public class PackageManagerService extends IPackageManager.Stub * action and a {@code android.intent.category.BROWSABLE} category * */ + int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) { + return updateFlagsForResolve(flags, userId, intent, callingUid, + false /*includeInstantApps*/, false /*onlyExposedExplicitly*/); + } int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid, boolean includeInstantApps) { + return updateFlagsForResolve(flags, userId, intent, callingUid, + includeInstantApps, false /*onlyExposedExplicitly*/); + } + int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid, + boolean includeInstantApps, boolean onlyExposedExplicitly) { // Safe mode means we shouldn't match any third-party components if (mSafeMode) { flags |= PackageManager.MATCH_SYSTEM_ONLY; } if (getInstantAppPackageName(callingUid) != null) { // But, ephemeral apps see both ephemeral and exposed, non-ephemeral components + if (onlyExposedExplicitly) { + flags |= PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY; + } flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY; flags |= PackageManager.MATCH_INSTANT; } else { @@ -4098,7 +4110,8 @@ public class PackageManagerService extends IPackageManager.Stub || isSpecialProcess || mContext.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED; - flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY; + flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY + | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY); if (!allowMatchInstant) { flags &= ~PackageManager.MATCH_INSTANT; } @@ -5659,19 +5672,19 @@ public class PackageManagerService extends IPackageManager.Stub } private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType, - int flags, int userId, boolean includeInstantApps) { + int flags, int userId, boolean resolveForStart) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent"); if (!sUserManager.exists(userId)) return null; final int callingUid = Binder.getCallingUid(); - flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps); + flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart); enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "resolve intent"); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities"); final List query = queryIntentActivitiesInternal(intent, resolvedType, - flags, userId, includeInstantApps); + flags, userId, resolveForStart); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); final ResolveInfo bestChoice = @@ -6208,14 +6221,14 @@ public class PackageManagerService extends IPackageManager.Stub } private @NonNull List queryIntentActivitiesInternal(Intent intent, - String resolvedType, int flags, int userId, boolean includeInstantApps) { + String resolvedType, int flags, int userId, boolean resolveForStart) { if (!sUserManager.exists(userId)) return Collections.emptyList(); final int callingUid = Binder.getCallingUid(); final String instantAppPkgName = getInstantAppPackageName(callingUid); - flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps); enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "query intent activities"); + final String pkgName = intent.getPackage(); ComponentName comp = intent.getComponent(); if (comp == null) { if (intent.getSelector() != null) { @@ -6224,6 +6237,8 @@ public class PackageManagerService extends IPackageManager.Stub } } + flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart, + comp != null || pkgName != null /*onlyExposedExplicitly*/); if (comp != null) { final List list = new ArrayList(1); final ActivityInfo ai = getActivityInfo(comp, flags, userId); @@ -6236,6 +6251,8 @@ public class PackageManagerService extends IPackageManager.Stub (flags & PackageManager.MATCH_INSTANT) != 0; final boolean matchVisibleToInstantAppOnly = (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0; + final boolean matchExplicitlyVisibleOnly = + (flags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0; final boolean isCallerInstantApp = instantAppPkgName != null; final boolean isTargetSameInstantApp = @@ -6243,8 +6260,14 @@ public class PackageManagerService extends IPackageManager.Stub final boolean isTargetInstantApp = (ai.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0; + final boolean isTargetVisibleToInstantApp = + (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; + final boolean isTargetExplicitlyVisibleToInstantApp = + isTargetVisibleToInstantApp + && (ai.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0; final boolean isTargetHiddenFromInstantApp = - (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0; + !isTargetVisibleToInstantApp + || (matchExplicitlyVisibleOnly && !isTargetExplicitlyVisibleToInstantApp); final boolean blockResolution = !isTargetSameInstantApp && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp) @@ -6263,7 +6286,6 @@ public class PackageManagerService extends IPackageManager.Stub boolean sortResult = false; boolean addEphemeral = false; List result; - final String pkgName = intent.getPackage(); final boolean ephemeralDisabled = isEphemeralDisabled(); synchronized (mPackages) { if (pkgName == null) { @@ -6529,7 +6551,7 @@ public class PackageManagerService extends IPackageManager.Stub } // allow activities that have been explicitly exposed to ephemeral apps if (!isEphemeralApp - && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) { + && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) { continue; } resolveInfos.remove(i); @@ -7069,16 +7091,16 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) { final int callingUid = Binder.getCallingUid(); - return resolveServiceInternal( - intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/); + return resolveServiceInternal(intent, resolvedType, flags, userId, callingUid); } private ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags, - int userId, int callingUid, boolean includeInstantApps) { + int userId, int callingUid) { if (!sUserManager.exists(userId)) return null; - flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps); + flags = updateFlagsForResolve( + flags, userId, intent, callingUid, false /*includeInstantApps*/); List query = queryIntentServicesInternal( - intent, resolvedType, flags, userId, callingUid, includeInstantApps); + intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/); if (query != null) { if (query.size() >= 1) { // If there is more than one service with the same priority, @@ -7130,7 +7152,7 @@ public class PackageManagerService extends IPackageManager.Stub (si.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0; final boolean isTargetHiddenFromInstantApp = - (si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0; + (si.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0; final boolean blockResolution = !isTargetSameInstantApp && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp) @@ -7202,7 +7224,7 @@ public class PackageManagerService extends IPackageManager.Stub } // allow services that have been explicitly exposed to ephemeral apps if (!isEphemeralApp - && ((info.serviceInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) { + && ((info.serviceInfo.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) { continue; } resolveInfos.remove(i); @@ -7251,7 +7273,7 @@ public class PackageManagerService extends IPackageManager.Stub (pi.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0; final boolean isTargetHiddenFromInstantApp = - (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0; + (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0; final boolean blockResolution = !isTargetSameInstantApp && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp) @@ -7323,7 +7345,7 @@ public class PackageManagerService extends IPackageManager.Stub } // allow providers that have been explicitly exposed to instant applications if (!isEphemeralApp - && ((info.providerInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) { + && ((info.providerInfo.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) { continue; } resolveInfos.remove(i); @@ -7684,7 +7706,7 @@ public class PackageManagerService extends IPackageManager.Stub // instant application; filter out non-exposed provider if (instantAppPkgName != null && !isInstantApp - && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) { + && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0) { return null; } // provider not enabled @@ -12430,16 +12452,21 @@ public class PackageManagerService extends IPackageManager.Stub if (ai == null) { return null; } + final boolean matchExplicitlyVisibleOnly = + (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0; final boolean matchVisibleToInstantApp = (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0; - final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; + final boolean componentVisible = + matchVisibleToInstantApp + && info.isVisibleToInstantApp() + && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp()); + final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; // throw out filters that aren't visible to ephemeral apps - if (matchVisibleToInstantApp - && !(info.isVisibleToInstantApp() || userState.instantApp)) { + if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) { return null; } - // throw out ephemeral filters if we're not explicitly requesting them - if (!isInstantApp && userState.instantApp) { + // throw out instant app filters if we're not explicitly requesting them + if (!matchInstantApp && userState.instantApp) { return null; } // throw out instant app filters if updates are available; will trigger @@ -23517,14 +23544,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { return resolveIntentInternal( - intent, resolvedType, flags, userId, true /*includeInstantApps*/); + intent, resolvedType, flags, userId, true /*resolveForStart*/); } @Override public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId, int callingUid) { - return resolveServiceInternal( - intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/); + return resolveServiceInternal(intent, resolvedType, flags, userId, callingUid); } @Override