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

Commit 5cf6663c authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Add new facility for apps to declared their preferred intents."

parents 9a3552bf b09491f2
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -733,10 +733,15 @@ public class IntentFilter implements Parcelable {
     * @see #addDataScheme
     */
    public final void addDataSchemeSpecificPart(String ssp, int type) {
        addDataSchemeSpecificPart(new PatternMatcher(ssp, type));
    }

    /** @hide */
    public final void addDataSchemeSpecificPart(PatternMatcher ssp) {
        if (mDataSchemeSpecificParts == null) {
            mDataSchemeSpecificParts = new ArrayList<PatternMatcher>();
        }
        mDataSchemeSpecificParts.add(new PatternMatcher(ssp, type));
        mDataSchemeSpecificParts.add(ssp);
    }

    /**
@@ -806,10 +811,15 @@ public class IntentFilter implements Parcelable {
     * @see #addDataScheme
     */
    public final void addDataAuthority(String host, String port) {
        if (port != null) port = port.intern();
        addDataAuthority(new AuthorityEntry(host.intern(), port));
    }

    /** @hide */
    public final void addDataAuthority(AuthorityEntry ent) {
        if (mDataAuthorities == null) mDataAuthorities =
                new ArrayList<AuthorityEntry>();
        if (port != null) port = port.intern();
        mDataAuthorities.add(new AuthorityEntry(host.intern(), port));
        mDataAuthorities.add(ent);
    }

    /**
@@ -874,8 +884,13 @@ public class IntentFilter implements Parcelable {
     * @see #addDataAuthority
     */
    public final void addDataPath(String path, int type) {
        addDataPath(new PatternMatcher(path.intern(), type));
    }

    /** @hide */
    public final void addDataPath(PatternMatcher path) {
        if (mDataPaths == null) mDataPaths = new ArrayList<PatternMatcher>();
        mDataPaths.add(new PatternMatcher(path.intern(), type));
        mDataPaths.add(path);
    }

    /**
+31 −9
Original line number Diff line number Diff line
@@ -45,9 +45,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
@@ -2440,7 +2437,7 @@ public class PackageParser {

            if (parser.getName().equals("intent-filter")) {
                ActivityIntentInfo intent = new ActivityIntentInfo(a);
                if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
                    return null;
                }
                if (intent.countActions() == 0) {
@@ -2450,6 +2447,21 @@ public class PackageParser {
                } else {
                    a.intents.add(intent);
                }
            } else if (!receiver && parser.getName().equals("preferred")) {
                ActivityIntentInfo intent = new ActivityIntentInfo(a);
                if (!parseIntent(res, parser, attrs, false, intent, outError)) {
                    return null;
                }
                if (intent.countActions() == 0) {
                    Slog.w(TAG, "No actions in preferred at "
                            + mArchiveSourcePath + " "
                            + parser.getPositionDescription());
                } else {
                    if (owner.preferredActivityFilters == null) {
                        owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
                    }
                    owner.preferredActivityFilters.add(intent);
                }
            } else if (parser.getName().equals("meta-data")) {
                if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
                        outError)) == null) {
@@ -2613,7 +2625,7 @@ public class PackageParser {

            if (parser.getName().equals("intent-filter")) {
                ActivityIntentInfo intent = new ActivityIntentInfo(a);
                if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
                    return null;
                }
                if (intent.countActions() == 0) {
@@ -3037,7 +3049,7 @@ public class PackageParser {

            if (parser.getName().equals("intent-filter")) {
                ServiceIntentInfo intent = new ServiceIntentInfo(s);
                if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
                    return null;
                }

@@ -3234,9 +3246,8 @@ public class PackageParser {
    private static final String ANDROID_RESOURCES
            = "http://schemas.android.com/apk/res/android";

    private boolean parseIntent(Resources res,
            XmlPullParser parser, AttributeSet attrs, int flags,
            IntentInfo outInfo, String[] outError, boolean isActivity)
    private boolean parseIntent(Resources res, XmlPullParser parser, AttributeSet attrs,
            boolean allowGlobs, IntentInfo outInfo, String[] outError)
            throws XmlPullParserException, IOException {

        TypedArray sa = res.obtainAttributes(attrs,
@@ -3327,6 +3338,10 @@ public class PackageParser {
                str = sa.getNonConfigurationString(
                        com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
                if (str != null) {
                    if (!allowGlobs) {
                        outError[0] = "sspPattern not allowed here; ssp must be literal";
                        return false;
                    }
                    outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
                }

@@ -3353,6 +3368,10 @@ public class PackageParser {
                str = sa.getNonConfigurationString(
                        com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
                if (str != null) {
                    if (!allowGlobs) {
                        outError[0] = "pathPattern not allowed here; path must be literal";
                        return false;
                    }
                    outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
                }

@@ -3414,6 +3433,8 @@ public class PackageParser {
        public ArrayList<String> usesOptionalLibraries = null;
        public String[] usesLibraryFiles = null;

        public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;

        public ArrayList<String> mOriginalPackages = null;
        public String mRealPackage = null;
        public ArrayList<String> mAdoptPermissions = null;
@@ -4020,6 +4041,7 @@ public class PackageParser {
        public CharSequence nonLocalizedLabel;
        public int icon;
        public int logo;
        public int preferred;
    }

    public final static class ActivityIntentInfo extends IntentInfo {
+176 −82
Original line number Diff line number Diff line
@@ -1830,6 +1830,20 @@ final class Settings {
    }

    void readDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
        // First pull data from any pre-installed apps.
        for (PackageSetting ps : mPackages.values()) {
            if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
                    && ps.pkg.preferredActivityFilters != null) {
                ArrayList<PackageParser.ActivityIntentInfo> intents
                        = ps.pkg.preferredActivityFilters;
                for (int i=0; i<intents.size(); i++) {
                    PackageParser.ActivityIntentInfo aii = intents.get(i);
                    applyDefaultPreferredActivityLPw(service, aii, new ComponentName(
                            ps.name, aii.activity.className), userId);
                }
            }
        }

        // Read preferred apps from .../etc/preferred-apps directory.
        File preferredDir = new File(Environment.getRootDirectory(), "etc/preferred-apps");
        if (!preferredDir.exists() || !preferredDir.isDirectory()) {
@@ -1889,21 +1903,8 @@ final class Settings {
        }
    }

    private void readDefaultPreferredActivitiesLPw(PackageManagerService service,
            XmlPullParser parser, int userId)
            throws XmlPullParserException, IOException {
        int outerDepth = parser.getDepth();
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }

            String tagName = parser.getName();
            if (tagName.equals(TAG_ITEM)) {
                PreferredActivity tmpPa = new PreferredActivity(parser);
                if (tmpPa.mPref.getParseError() == null) {
    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
            IntentFilter tmpPa, ComponentName cn, int userId) {
        // The initial preferences only specify the target activity
        // component and intent-filter, not the set of matches.  So we
        // now need to query for the matches to build the correct
@@ -1912,7 +1913,6 @@ final class Settings {
            Log.d(TAG, "Processing preferred:");
            tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), "  ");
        }
                    final ComponentName cn = tmpPa.mPref.mComponent;
        Intent intent = new Intent();
        int flags = 0;
        intent.setAction(tmpPa.getAction(0));
@@ -1924,28 +1924,83 @@ final class Settings {
                intent.addCategory(cat);
            }
        }
                    if (tmpPa.countDataSchemes() > 0) {

        boolean doNonData = true;

        for (int ischeme=0; ischeme<tmpPa.countDataSchemes(); ischeme++) {
            boolean doScheme = true;
            String scheme = tmpPa.getDataScheme(ischeme);
            for (int issp=0; issp<tmpPa.countDataSchemeSpecificParts(); issp++) {
                Uri.Builder builder = new Uri.Builder();
                        builder.scheme(tmpPa.getDataScheme(0));
                        if (tmpPa.countDataSchemeSpecificParts() > 0) {
                            PatternMatcher path = tmpPa.getDataSchemeSpecificPart(0);
                            builder.opaquePart(path.getPath());
                        } else {
                            if (tmpPa.countDataAuthorities() > 0) {
                                IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(0);
                builder.scheme(scheme);
                PatternMatcher ssp = tmpPa.getDataSchemeSpecificPart(issp);
                builder.opaquePart(ssp.getPath());
                Intent finalIntent = new Intent(intent);
                finalIntent.setData(builder.build());
                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
                        scheme, ssp, null, null, null, userId);
                doScheme = false;
            }
            for (int iauth=0; iauth<tmpPa.countDataAuthorities(); iauth++) {
                boolean doAuth = true;
                IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(iauth);
                for (int ipath=0; ipath<tmpPa.countDataPaths(); ipath++) {
                    Uri.Builder builder = new Uri.Builder();
                    builder.scheme(scheme);
                    if (auth.getHost() != null) {
                        builder.authority(auth.getHost());
                    }
                            }
                            if (tmpPa.countDataPaths() > 0) {
                                PatternMatcher path = tmpPa.getDataPath(0);
                    PatternMatcher path = tmpPa.getDataPath(ipath);
                    builder.path(path.getPath());
                    Intent finalIntent = new Intent(intent);
                    finalIntent.setData(builder.build());
                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
                            scheme, null, auth, path, null, userId);
                    doAuth = doScheme = false;
                }
                if (doAuth) {
                    Uri.Builder builder = new Uri.Builder();
                    builder.scheme(scheme);
                    if (auth.getHost() != null) {
                        builder.authority(auth.getHost());
                    }
                    Intent finalIntent = new Intent(intent);
                    finalIntent.setData(builder.build());
                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
                            scheme, null, auth, null, null, userId);
                    doScheme = false;
                }
            }
            if (doScheme) {
                Uri.Builder builder = new Uri.Builder();
                builder.scheme(scheme);
                Intent finalIntent = new Intent(intent);
                finalIntent.setData(builder.build());
                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
                        scheme, null, null, null, null, userId);
            }
            doNonData = false;
        }

        for (int idata=0; idata<tmpPa.countDataTypes(); idata++) {
            Intent finalIntent = new Intent(intent);
            String mimeType = tmpPa.getDataType(idata);
            finalIntent.setType(mimeType);
            applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
                    null, null, null, null, mimeType, userId);
            doNonData = false;
        }

        if (doNonData) {
            applyDefaultPreferredActivityLPw(service, intent, flags, cn,
                    null, null, null, null, null, userId);
        }
                        intent.setData(builder.build());
                    } else if (tmpPa.countDataTypes() > 0) {
                        intent.setType(tmpPa.getDataType(0));
    }

    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
            Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
            IntentFilter.AuthorityEntry auth, PatternMatcher path, String mimeType,
            int userId) {
        List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
                intent.getType(), flags, 0);
        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
@@ -1978,14 +2033,53 @@ final class Settings {
                }
            }
            if (haveAct && !haveNonSys) {
                            PreferredActivity pa = new PreferredActivity(tmpPa, match, set,
                                    tmpPa.mPref.mComponent);
                IntentFilter filter = new IntentFilter();
                if (intent.getAction() != null) {
                    filter.addAction(intent.getAction());
                }
                for (String cat : intent.getCategories()) {
                    filter.addCategory(cat);
                }
                if ((flags&PackageManager.MATCH_DEFAULT_ONLY) != 0) {
                    filter.addCategory(Intent.CATEGORY_DEFAULT);
                }
                if (scheme != null) {
                    filter.addDataScheme(scheme);
                }
                if (ssp != null) {
                    filter.addDataSchemeSpecificPart(ssp.getPath(), ssp.getType());
                }
                if (auth != null) {
                    filter.addDataAuthority(auth);
                }
                if (path != null) {
                    filter.addDataPath(path);
                }
                PreferredActivity pa = new PreferredActivity(filter, match, set, cn);
                editPreferredActivitiesLPw(userId).addFilter(pa);
            } else if (!haveNonSys) {
                            Slog.w(TAG, "No component found for default preferred activity "
                                    + tmpPa.mPref.mComponent);
                Slog.w(TAG, "No component found for default preferred activity " + cn);
            }
        }
    }

    private void readDefaultPreferredActivitiesLPw(PackageManagerService service,
            XmlPullParser parser, int userId)
            throws XmlPullParserException, IOException {
        int outerDepth = parser.getDepth();
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }

            String tagName = parser.getName();
            if (tagName.equals(TAG_ITEM)) {
                PreferredActivity tmpPa = new PreferredActivity(parser);
                if (tmpPa.mPref.getParseError() == null) {
                    applyDefaultPreferredActivityLPw(service, tmpPa, tmpPa.mPref.mComponent,
                            userId);
                } else {
                    PackageManagerService.reportSettingsProblem(Log.WARN,
                            "Error in package manager settings: <preferred-activity> "