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

Commit a4ffb456 authored by Patrick Baumann's avatar Patrick Baumann
Browse files

Adds queries tag to manifest

This change adds support for a new <queries> tag as a child of the
<manifest> tag, allowing a package to declare the intents it intends to
use to query for other apps on device.

Bug: 136675067
Test: build and boot
Change-Id: Ic8b40cabddee4b6404c220901efeaae680661c0c
parent 1b23258c
Loading
Loading
Loading
Loading
+81 −1
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.FileUtils;
@@ -2445,6 +2446,8 @@ public class PackageParser {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return null;

            } else if (tagName.equals("queries")) {
                parseQueries(pkg, res, parser, flags, outError);
            } else {
                Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
                        + " at " + mArchiveSourcePath + " "
@@ -3538,6 +3541,9 @@ public class PackageParser {
            owner.mRequiredAccountType = requiredAccountType;
        }

        owner.mForceQueryable =
                sa.getBoolean(R.styleable.AndroidManifestApplication_forceQueryable, false);

        if (sa.getBoolean(
                com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
                false)) {
@@ -3953,7 +3959,6 @@ public class PackageParser {
                    ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
                }
                XmlUtils.skipCurrentTag(parser);

            } else {
                if (!RIGID_PARSER) {
                    Slog.w(TAG, "Unknown element under <application>: " + tagName
@@ -4000,6 +4005,67 @@ public class PackageParser {
        return true;
    }

    private boolean parseQueries(Package owner, Resources res, XmlResourceParser parser, int flags,
            String[] outError)
            throws IOException, XmlPullParserException {

        final 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;
            }
            if (parser.getName().equals("intent")) {
                QueriesIntentInfo intentInfo = new QueriesIntentInfo();
                if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
                        intentInfo, outError)) {
                    return false;
                }
                Intent intent = new Intent();
                if (intentInfo.countActions() != 1) {
                    outError[0] = "intent tags must contain exactly one action.";
                    return false;
                }
                intent.setAction(intentInfo.getAction(0));
                for (int i = 0, max = intentInfo.countCategories(); i < max; i++) {
                    intent.addCategory(intentInfo.getCategory(i));
                }
                Uri data = null;
                String dataType = null;
                if (intentInfo.countDataTypes() > 1) {
                    outError[0] = "intent tag may have at most one data type.";
                    return false;
                }
                if (intentInfo.countDataSchemes() > 1) {
                    outError[0] = "intent tag may have at most one data scheme.";
                    return false;
                }
                if (intentInfo.countDataTypes() == 1) {
                    data = Uri.fromParts(intentInfo.getDataType(0), "", null);
                }
                if (intentInfo.countDataSchemes() == 1) {
                    dataType = intentInfo.getDataScheme(0);
                }
                intent.setDataAndType(data, dataType);
                owner.mQueriesIntents = ArrayUtils.add(owner.mQueriesIntents, intent);
            } else if (parser.getName().equals("package")) {
                final TypedArray sa = res.obtainAttributes(parser,
                        com.android.internal.R.styleable.AndroidManifestQueriesPackage);
                final String packageName =
                        sa.getString(R.styleable.AndroidManifestQueriesPackage_name);
                if (TextUtils.isEmpty(packageName)) {
                    outError[0] = "Package name is missing from package tag.";
                    return false;
                }
                owner.mQueriesPackages =
                        ArrayUtils.add(owner.mQueriesPackages, packageName.intern());
            }
        }
        return true;
    }

    /**
     * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI
     */
@@ -6514,6 +6580,9 @@ public class PackageParser {
        // The major version code declared for this package.
        public int mVersionCodeMajor;

        // Whether the package declares that it should be queryable by all normal apps on device.
        public boolean mForceQueryable;

        // Return long containing mVersionCode and mVersionCodeMajor.
        public long getLongVersionCode() {
            return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
@@ -6619,6 +6688,9 @@ public class PackageParser {
        /** Whether or not the package is a stub and must be replaced by the full version. */
        public boolean isStub;

        public ArrayList<String> mQueriesPackages;
        public ArrayList<Intent> mQueriesIntents;

        @UnsupportedAppUsage
        public Package(String packageName) {
            this.packageName = packageName;
@@ -7122,6 +7194,9 @@ public class PackageParser {
            use32bitAbi = (dest.readInt() == 1);
            restrictUpdateHash = dest.createByteArray();
            visibleToInstantApps = dest.readInt() == 1;
            mForceQueryable = dest.readBoolean();
            mQueriesIntents = dest.createTypedArrayList(Intent.CREATOR);
            mQueriesPackages = dest.createStringArrayList();
        }

        private static void internStringArrayList(List<String> list) {
@@ -7247,6 +7322,9 @@ public class PackageParser {
            dest.writeInt(use32bitAbi ? 1 : 0);
            dest.writeByteArray(restrictUpdateHash);
            dest.writeInt(visibleToInstantApps ? 1 : 0);
            dest.writeBoolean(mForceQueryable);
            dest.writeTypedList(mQueriesIntents);
            dest.writeList(mQueriesPackages);
        }


@@ -8257,6 +8335,8 @@ public class PackageParser {
        }
    }

    public static final class QueriesIntentInfo extends IntentInfo {}

    public final static class ActivityIntentInfo extends IntentInfo {
        @UnsupportedAppUsage
        public Activity activity;
+1 −0
Original line number Diff line number Diff line
@@ -4598,6 +4598,7 @@
                 android:supportsRtl="true"
                 android:theme="@style/Theme.DeviceDefault.Light.DarkActionBar"
                 android:defaultToDeviceProtectedStorage="true"
                 android:forceQueryable="true"
                 android:directBootAware="true">
        <activity android:name="com.android.internal.app.ChooserActivity"
                android:theme="@style/Theme.DeviceDefault.Resolver"
+14 −0
Original line number Diff line number Diff line
@@ -1743,6 +1743,13 @@
                 - {@code true} for apps with targetSdkVersion < 29.
             -->
        <attr name="requestLegacyExternalStorage" format="boolean" />

        <!-- If {@code true} this app declares that it should be visible to all other apps on
             device, regardless of what they declare via the {@code queries} tags in their
             manifest.

             The default value is {@code false}. -->
        <attr name="forceQueryable" format="boolean" />
    </declare-styleable>
    <!-- The <code>permission</code> tag declares a security permission that can be
         used to control access from other packages to specific components or
@@ -1977,6 +1984,12 @@
        <attr name="name" />
    </declare-styleable>

    <declare-styleable name="AndroidManifestQueries" parent="AndroidManifest" />
    <declare-styleable name="AndroidManifestQueriesPackage" parent="AndroidManifestQueries">
        <attr name="name" />
    </declare-styleable>
    <declare-styleable name="AndroidManifestQueriesIntent" parent="AndroidManifestQueries" />


    <!-- The <code>static-library</code> tag declares that this apk is providing itself
       as a static shared library for other applications to use. Any app can declare such
@@ -2477,6 +2490,7 @@
            <!-- High dynamic range color mode. -->
            <enum name="hdr" value="2" />
        </attr>
        <attr name="forceQueryable" format="boolean" />
    </declare-styleable>

    <!-- The <code>activity-alias</code> tag declares a new
+6 −0
Original line number Diff line number Diff line
@@ -1700,6 +1700,12 @@
        <!-- Add packages here -->
    </string-array>

    <string-array name="config_forceQueryablePackages" translatable="false">
        <item>com.android.settings</item>
        <!-- Add packages here -->
    </string-array>


    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
         specified -->
    <string name="default_wallpaper_component" translatable="false">@null</string>
+1 −0
Original line number Diff line number Diff line
@@ -786,6 +786,7 @@
  <java-symbol type="string" name="widget_default_class_name" />
  <java-symbol type="string" name="emergency_calls_only" />
  <java-symbol type="array" name="config_ephemeralResolverPackage" />
  <java-symbol type="array" name="config_forceQueryablePackages" />
  <java-symbol type="string" name="eventTypeAnniversary" />
  <java-symbol type="string" name="eventTypeBirthday" />
  <java-symbol type="string" name="eventTypeCustom" />
Loading