OSDN Git Service

Add component ordering
authorTodd Kennedy <toddke@google.com>
Thu, 22 Feb 2018 22:15:18 +0000 (14:15 -0800)
committerTodd Kennedy <toddke@google.com>
Wed, 28 Feb 2018 17:16:07 +0000 (09:16 -0800)
When multiple activities match the same Intent, allow app developers
to reorder matched results within their own application. This is not
a replacement for priority which reorders matched results between
applications.

Change-Id: I12ee987622e12e40d6b5b48f616cc362d01381de
Fixes: 64582537
Test: atest -it CtsAppSecurityHostTestCases:PackageResolutionHostTest

core/java/android/content/IntentFilter.java
core/java/android/content/pm/PackageParser.java
core/res/res/values/attrs_manifest.xml

index a957aed..cec3bad 100644 (file)
@@ -1872,9 +1872,10 @@ public class IntentFilter implements Parcelable {
                 du.println(sb.toString());
             }
         }
-        if (mPriority != 0 || mHasPartialTypes) {
+        if (mPriority != 0 || mOrder != 0 || mHasPartialTypes) {
             sb.setLength(0);
             sb.append(prefix); sb.append("mPriority="); sb.append(mPriority);
+                    sb.append(", mOrder="); sb.append(mOrder);
                     sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
             du.println(sb.toString());
         }
@@ -1951,6 +1952,7 @@ public class IntentFilter implements Parcelable {
         dest.writeInt(mHasPartialTypes ? 1 : 0);
         dest.writeInt(getAutoVerify() ? 1 : 0);
         dest.writeInt(mInstantAppVisibility);
+        dest.writeInt(mOrder);
     }
 
     /**
@@ -2020,6 +2022,7 @@ public class IntentFilter implements Parcelable {
         mHasPartialTypes = source.readInt() > 0;
         setAutoVerify(source.readInt() > 0);
         setVisibilityToInstantApp(source.readInt());
+        mOrder = source.readInt();
     }
 
     private final boolean findMimeType(String type) {
index dda4167..cc7fa6a 100644 (file)
@@ -3638,7 +3638,9 @@ public class PackageParser {
         // getting added to the wrong package.
         final CachedComponentArgs cachedArgs = new CachedComponentArgs();
         int type;
-
+        boolean hasActivityOrder = false;
+        boolean hasReceiverOrder = false;
+        boolean hasServiceOrder = false;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -3654,6 +3656,7 @@ public class PackageParser {
                     return false;
                 }
 
+                hasActivityOrder |= (a.order != 0);
                 owner.activities.add(a);
 
             } else if (tagName.equals("receiver")) {
@@ -3664,6 +3667,7 @@ public class PackageParser {
                     return false;
                 }
 
+                hasReceiverOrder |= (a.order != 0);
                 owner.receivers.add(a);
 
             } else if (tagName.equals("service")) {
@@ -3673,6 +3677,7 @@ public class PackageParser {
                     return false;
                 }
 
+                hasServiceOrder |= (s.order != 0);
                 owner.services.add(s);
 
             } else if (tagName.equals("provider")) {
@@ -3691,6 +3696,7 @@ public class PackageParser {
                     return false;
                 }
 
+                hasActivityOrder |= (a.order != 0);
                 owner.activities.add(a);
 
             } else if (parser.getName().equals("meta-data")) {
@@ -3824,6 +3830,15 @@ public class PackageParser {
             }
         }
 
+        if (hasActivityOrder) {
+            Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
+        }
+        if (hasReceiverOrder) {
+            Collections.sort(owner.receivers,  (r1, r2) -> Integer.compare(r2.order, r1.order));
+        }
+        if (hasServiceOrder) {
+            Collections.sort(owner.services,  (s1, s2) -> Integer.compare(s2.order, s1.order));
+        }
         // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
         // every activity info has had a chance to set it from its attributes.
         setMaxAspectRatio(owner);
@@ -4365,6 +4380,7 @@ public class PackageParser {
                             + mArchiveSourcePath + " "
                             + parser.getPositionDescription());
                 } else {
+                    a.order = Math.max(intent.getOrder(), a.order);
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
@@ -4742,6 +4758,7 @@ public class PackageParser {
                             + mArchiveSourcePath + " "
                             + parser.getPositionDescription());
                 } else {
+                    a.order = Math.max(intent.getOrder(), a.order);
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
@@ -4949,6 +4966,7 @@ public class PackageParser {
                     intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                 }
+                outInfo.order = Math.max(intent.getOrder(), outInfo.order);
                 outInfo.intents.add(intent);
 
             } else if (parser.getName().equals("meta-data")) {
@@ -5238,6 +5256,7 @@ public class PackageParser {
                     intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                 }
+                s.order = Math.max(intent.getOrder(), s.order);
                 s.intents.add(intent);
             } else if (parser.getName().equals("meta-data")) {
                 if ((s.metaData=parseMetaData(res, parser, s.metaData,
@@ -5463,6 +5482,10 @@ public class PackageParser {
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
         outInfo.setPriority(priority);
 
+        int order = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
+        outInfo.setOrder(order);
+
         TypedValue v = sa.peekValue(
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
@@ -7047,6 +7070,8 @@ public class PackageParser {
 
         public Bundle metaData;
         public Package owner;
+        /** The order of this component in relation to its peers */
+        public int order;
 
         ComponentName componentName;
         String componentShortName;
@@ -7565,6 +7590,7 @@ public class PackageParser {
 
             for (ActivityIntentInfo aii : intents) {
                 aii.activity = this;
+                order = Math.max(aii.getOrder(), order);
             }
 
             if (info.permission != null) {
@@ -7654,6 +7680,7 @@ public class PackageParser {
 
             for (ServiceIntentInfo aii : intents) {
                 aii.service = this;
+                order = Math.max(aii.getOrder(), order);
             }
 
             if (info.permission != null) {
index 287f296..5baa40c 100644 (file)
         <attr name="logo" />
         <attr name="priority" />
         <attr name="autoVerify" />
+        <!-- Within an application, multiple intent filters may match a particular
+             intent. This allows the app author to specify the order filters should
+             be considered. We don't want to use priority because that is global
+             across applications.
+             <p>Only use if you really need to forcibly set the order in which
+             filters are evaluated. It is preferred to target an activity with a
+             directed intent instead.
+             <p>The value is a single integer, with higher numbers considered to
+             be better. If not specified, the default order is 0. -->
+        <attr name="order" />
     </declare-styleable>
 
     <!-- Attributes that can be supplied in an AndroidManifest.xml