Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c05f5d12 authored by Todd Kennedy's avatar Todd Kennedy
Browse files

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
parent ecabc596
Loading
Loading
Loading
Loading
+36 −8
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.content;
package android.content;


import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
import android.net.Uri;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcel;
@@ -33,6 +34,8 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import org.xmlpull.v1.XmlSerializer;


import java.io.IOException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Iterator;
import java.util.Set;
import java.util.Set;
@@ -283,9 +286,22 @@ public class IntentFilter implements Parcelable {
    private static final int STATE_VERIFIED            = 0x00001000;
    private static final int STATE_VERIFIED            = 0x00001000;


    private int mVerifyState;
    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. */
    /** 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
    // These functions are the start of more optimized code for managing
    // the string sets...  not yet implemented.
    // the string sets...  not yet implemented.


@@ -452,7 +468,7 @@ public class IntentFilter implements Parcelable {
        }
        }
        mHasPartialTypes = o.mHasPartialTypes;
        mHasPartialTypes = o.mHasPartialTypes;
        mVerifyState = o.mVerifyState;
        mVerifyState = o.mVerifyState;
        mVisibleToInstantApp = o.mVisibleToInstantApp;
        mInstantAppVisibility = o.mInstantAppVisibility;
    }
    }


    /**
    /**
@@ -655,12 +671,24 @@ public class IntentFilter implements Parcelable {
    }
    }


    /** @hide */
    /** @hide */
    public void setVisibleToInstantApp(boolean visibleToInstantApp) {
    public void setVisibilityToInstantApp(@InstantAppVisibility int visibility) {
        mVisibleToInstantApp = visibleToInstantApp;
        mInstantAppVisibility = visibility;
    }
    /** @hide */
    public @InstantAppVisibility int getVisibilityToInstantApp() {
        return mInstantAppVisibility;
    }
    }
    /** @hide */
    /** @hide */
    public boolean isVisibleToInstantApp() {
    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(mPriority);
        dest.writeInt(mHasPartialTypes ? 1 : 0);
        dest.writeInt(mHasPartialTypes ? 1 : 0);
        dest.writeInt(getAutoVerify() ? 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();
        mPriority = source.readInt();
        mHasPartialTypes = source.readInt() > 0;
        mHasPartialTypes = source.readInt() > 0;
        setAutoVerify(source.readInt() > 0);
        setAutoVerify(source.readInt() > 0);
        setVisibleToInstantApp(source.readInt() > 0);
        setVisibilityToInstantApp(source.readInt());
    }
    }


    private final boolean findMimeType(String type) {
    private final boolean findMimeType(String type) {
+20 −3
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content.pm;
package android.content.pm;


import android.annotation.IntDef;
import android.annotation.IntDef;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Configuration.NativeConfig;
import android.content.res.Configuration.NativeConfig;
import android.os.Parcel;
import android.os.Parcel;
@@ -412,17 +413,33 @@ public class ActivityInfo extends ComponentInfo
    public static final int FLAG_ALWAYS_FOCUSABLE = 0x40000;
    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
     * @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.
     * Bit in {@link #flags} indicating if the activity supports picture-in-picture mode.
     * See {@link android.R.attr#supportsPictureInPicture}.
     * See {@link android.R.attr#supportsPictureInPicture}.
     * @hide
     * @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
     * @hide Bit in {@link #flags}: If set, this component will only be seen
+9 −1
Original line number Original line Diff line number Diff line
@@ -461,11 +461,19 @@ public abstract class PackageManager {


    /**
    /**
     * Internal {@link PackageInfo} flag: include only components that are exposed to
     * 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
     * @hide
     */
     */
    public static final int MATCH_VISIBLE_TO_INSTANT_APP_ONLY = 0x01000000;
    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
     * Internal flag used to indicate that a system component has done their
     * homework and verified that they correctly handle packages and components
     * homework and verified that they correctly handle packages and components
+52 −27
Original line number Original line Diff line number Diff line
@@ -4271,7 +4271,7 @@ public class PackageParser {
        boolean visibleToEphemeral =
        boolean visibleToEphemeral =
                sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
                sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
        if (visibleToEphemeral) {
        if (visibleToEphemeral) {
            a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
            a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
            owner.visibleToInstantApps = true;
            owner.visibleToInstantApps = true;
        }
        }


@@ -4313,9 +4313,17 @@ public class PackageParser {
                    a.intents.add(intent);
                    a.intents.add(intent);
                }
                }
                // adjust activity flags when we implicitly expose it via a browsable filter
                // 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()) {
                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
                if (LOG_UNSAFE_BROADCASTS && receiver
                        && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
                        && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
@@ -4346,9 +4354,17 @@ public class PackageParser {
                    owner.preferredActivityFilters.add(intent);
                    owner.preferredActivityFilters.add(intent);
                }
                }
                // adjust activity flags when we implicitly expose it via a browsable filter
                // 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()) {
                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")) {
            } else if (parser.getName().equals("meta-data")) {
                if ((a.metaData = parseMetaData(res, parser, a.metaData,
                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
                // we don't have an attribute [or it's false], but, we have meta-data
                if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                    visibleToEphemeral = true; // set in case there are more intent filters
                    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;
                    owner.visibleToInstantApps = true;
                    // cycle through any filters already seen
                    // cycle through any filters already seen
                    for (int i = a.intents.size() - 1; i >= 0; --i) {
                    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) {
                    if (owner.preferredActivityFilters != null) {
                        for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
                        for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
                            owner.preferredActivityFilters.get(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
        // TODO add visibleToInstantApps attribute to activity alias
        final boolean visibleToEphemeral =
        final boolean visibleToEphemeral =
                ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0);
                ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);


        sa.recycle();
        sa.recycle();


@@ -4673,13 +4691,20 @@ public class PackageParser {
                            + mArchiveSourcePath + " "
                            + mArchiveSourcePath + " "
                            + parser.getPositionDescription());
                            + parser.getPositionDescription());
                } else {
                } else {
                    intent.setVisibleToInstantApp(
                            visibleToEphemeral || isImplicitlyExposedIntent(intent));
                    a.intents.add(intent);
                    a.intents.add(intent);
                }
                }
                // adjust activity flags when we implicitly expose it via a browsable filter
                // 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()) {
                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")) {
            } else if (parser.getName().equals("meta-data")) {
                if ((a.metaData=parseMetaData(res, parser, a.metaData,
                if ((a.metaData=parseMetaData(res, parser, a.metaData,
@@ -4822,7 +4847,7 @@ public class PackageParser {
        final boolean visibleToEphemeral =
        final boolean visibleToEphemeral =
                sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
                sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
        if (visibleToEphemeral) {
        if (visibleToEphemeral) {
            p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
            p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
            owner.visibleToInstantApps = true;
            owner.visibleToInstantApps = true;
        }
        }


@@ -4874,12 +4899,11 @@ public class PackageParser {
                        intent, outError)) {
                        intent, outError)) {
                    return false;
                    return false;
                }
                }
                outInfo.intents.add(intent);
                if (visibleToEphemeral) {
                // adjust provider flags when we implicitly expose it via a browsable filter
                    intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
                    outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                if (intent.isVisibleToInstantApp()) {
                    outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                }
                }
                outInfo.intents.add(intent);


            } else if (parser.getName().equals("meta-data")) {
            } else if (parser.getName().equals("meta-data")) {
                if ((outInfo.metaData=parseMetaData(res, parser,
                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
                // we don't have an attribute [or it's false], but, we have meta-data
                if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                    visibleToEphemeral = true; // set in case there are more intent filters
                    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;
                    owner.visibleToInstantApps = true;
                    // cycle through any filters already seen
                    // cycle through any filters already seen
                    for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
                    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 =
        boolean visibleToEphemeral =
                sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
                sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
        if (visibleToEphemeral) {
        if (visibleToEphemeral) {
            s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
            s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
            owner.visibleToInstantApps = true;
            owner.visibleToInstantApps = true;
        }
        }


@@ -5180,10 +5205,9 @@ public class PackageParser {
                        intent, outError)) {
                        intent, outError)) {
                    return null;
                    return null;
                }
                }
                // adjust activity flags when we implicitly expose it via a browsable filter
                if (visibleToEphemeral) {
                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
                    intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                if (intent.isVisibleToInstantApp()) {
                    s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                    s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                }
                }
                s.intents.add(intent);
                s.intents.add(intent);
            } else if (parser.getName().equals("meta-data")) {
            } 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
                // we don't have an attribute [or it's false], but, we have meta-data
                if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                    visibleToEphemeral = true; // set in case there are more intent filters
                    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;
                    owner.visibleToInstantApps = true;
                    // cycle through any filters already seen
                    // cycle through any filters already seen
                    for (int i = s.intents.size() - 1; i >= 0; --i) {
                    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 {
            } else {
+1 −1
Original line number Original line Diff line number Diff line
@@ -79,7 +79,7 @@ public final class ProviderInfo extends ComponentInfo
     * Bit in {@link #flags} indicating if the provider is visible to ephemeral applications.
     * Bit in {@link #flags} indicating if the provider is visible to ephemeral applications.
     * @hide
     * @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
     * Bit in {@link #flags}: If set, a single instance of the provider will
Loading