OSDN Git Service

Add concept of implicitly exposed components
authorTodd Kennedy <toddke@google.com>
Tue, 25 Apr 2017 18:11:40 +0000 (11:11 -0700)
committerTodd Kennedy <toddke@google.com>
Tue, 25 Apr 2017 20:34:23 +0000 (13:34 -0700)
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
core/java/android/content/pm/ActivityInfo.java
core/java/android/content/pm/PackageManager.java
core/java/android/content/pm/PackageParser.java
core/java/android/content/pm/ProviderInfo.java
core/java/android/content/pm/ServiceInfo.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/BroadcastQueue.java
services/core/java/com/android/server/pm/PackageManagerService.java

index d64f018..c9bce53 100644 (file)
@@ -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) {
index b01e6a1..0be0885 100644 (file)
@@ -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:
+     * <ul>
+     * <li>action {@link Intent#CATEGORY_BROWSABLE}</li>
+     * <li>action {@link Intent#ACTION_SEND}</li>
+     * <li>action {@link Intent#ACTION_SENDTO}</li>
+     * <li>action {@link Intent#ACTION_SEND_MULTIPLE}</li>
+     * </ul>
+     * @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
index ecaf7eb..d2468d9 100644 (file)
@@ -461,12 +461,20 @@ 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
      * that come and go over time. In particular:
index 8609351..e4db0f0 100644 (file)
@@ -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 {
index 8c21563..91dc06e 100644 (file)
@@ -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
index f0766be..c683ea5 100644 (file)
@@ -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
index 45c2054..41f3b14 100644 (file)
@@ -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();
index 349180f..d08298b 100644 (file)
@@ -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
index faa9934..7dc159b 100644 (file)
@@ -4074,14 +4074,26 @@ public class PackageManagerService extends IPackageManager.Stub
      * action and a {@code android.intent.category.BROWSABLE} category</li>
      * </ul>
      */
+    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<ResolveInfo> 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<ResolveInfo> 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<ResolveInfo> list = new ArrayList<ResolveInfo>(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<ResolveInfo> 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<ResolveInfo> 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