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

Commit 7b068fa9 authored by Todd Kennedy's avatar Todd Kennedy Committed by android-build-merger
Browse files

DO NOT MERGE Fix intent filter priorities am: eeb970ad am: cd24c4eb

am: bd770bc9

* commit 'bd770bc9':
  DO NOT MERGE Fix intent filter priorities

Change-Id: I7c17baf18e2d25c95fb5b8fa45f5cc7b5936723b
parents 1c7f5bb4 bd770bc9
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -883,6 +883,15 @@ public class IntentFilter implements Parcelable {
            return true;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof AuthorityEntry) {
                final AuthorityEntry other = (AuthorityEntry)obj;
                return match(other);
            }
            return false;
        }

        /**
         * Determine whether this AuthorityEntry matches the given data Uri.
         * <em>Note that this comparison is case-sensitive, unlike formal
@@ -917,7 +926,7 @@ public class IntentFilter implements Parcelable {
            }
            return MATCH_CATEGORY_HOST;
        }
    };
    }

    /**
     * Add a new Intent data "scheme specific part" to match against.  The filter must
+256 −18
Original line number Diff line number Diff line
@@ -297,6 +297,7 @@ public class PackageManagerService extends IPackageManager.Stub {
    private static final boolean DEBUG_PACKAGE_SCANNING = false;
    private static final boolean DEBUG_VERIFY = false;
    private static final boolean DEBUG_DEXOPT = false;
    private static final boolean DEBUG_FILTERS = false;
    private static final boolean DEBUG_ABI_SELECTION = false;
    static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
@@ -8744,6 +8745,255 @@ public class PackageManagerService extends IPackageManager.Stub {
            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
        }
        /**
         * Finds a privileged activity that matches the specified activity names.
         */
        private PackageParser.Activity findMatchingActivity(
                List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
            for (PackageParser.Activity sysActivity : activityList) {
                if (sysActivity.info.name.equals(activityInfo.name)) {
                    return sysActivity;
                }
                if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
                    return sysActivity;
                }
                if (sysActivity.info.targetActivity != null) {
                    if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
                        return sysActivity;
                    }
                    if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
                        return sysActivity;
                    }
                }
            }
            return null;
        }
        public class IterGenerator<E> {
            public Iterator<E> generate(ActivityIntentInfo info) {
                return null;
            }
        }
        public class ActionIterGenerator extends IterGenerator<String> {
            @Override
            public Iterator<String> generate(ActivityIntentInfo info) {
                return info.actionsIterator();
            }
        }
        public class CategoriesIterGenerator extends IterGenerator<String> {
            @Override
            public Iterator<String> generate(ActivityIntentInfo info) {
                return info.categoriesIterator();
            }
        }
        public class SchemesIterGenerator extends IterGenerator<String> {
            @Override
            public Iterator<String> generate(ActivityIntentInfo info) {
                return info.schemesIterator();
            }
        }
        public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
            @Override
            public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
                return info.authoritiesIterator();
            }
        }
        /**
         * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
         * MODIFIED. Do not pass in a list that should not be changed.
         */
        private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
                IterGenerator<T> generator, Iterator<T> searchIterator) {
            // loop through the set of actions; every one must be found in the intent filter
            while (searchIterator.hasNext()) {
                // we must have at least one filter in the list to consider a match
                if (intentList.size() == 0) {
                    break;
                }
                final T searchAction = searchIterator.next();
                // loop through the set of intent filters
                final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
                while (intentIter.hasNext()) {
                    final ActivityIntentInfo intentInfo = intentIter.next();
                    boolean selectionFound = false;
                    // loop through the intent filter's selection criteria; at least one
                    // of them must match the searched criteria
                    final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
                    while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
                        final T intentSelection = intentSelectionIter.next();
                        if (intentSelection != null && intentSelection.equals(searchAction)) {
                            selectionFound = true;
                            break;
                        }
                    }
                    // the selection criteria wasn't found in this filter's set; this filter
                    // is not a potential match
                    if (!selectionFound) {
                        intentIter.remove();
                    }
                }
            }
        }
        /**
         * Adjusts the priority of the given intent filter according to policy.
         * <p>
         * <ul>
         * <li>The priority for unbundled updates to system applications is capped to the
         *      priority defined on the system partition</li>
         * </ul>
         */
        private void adjustPriority(
                List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) {
            // nothing to do; priority is fine as-is
            if (intent.getPriority() <= 0) {
                return;
            }
            final ActivityInfo activityInfo = intent.activity.info;
            final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
            final boolean systemApp = applicationInfo.isSystemApp();
            if (!systemApp) {
                // non-system applications can never define a priority >0
                Slog.w(TAG, "Non-system app; cap priority to 0;"
                        + " package: " + applicationInfo.packageName
                        + " activity: " + intent.activity.className
                        + " origPrio: " + intent.getPriority());
                intent.setPriority(0);
                return;
            }
            if (systemActivities == null) {
                // the system package is not disabled; we're parsing the system partition
                // apps on the system image get whatever priority they request
                return;
            }
            // system app unbundled update ... try to find the same activity
            final PackageParser.Activity foundActivity =
                    findMatchingActivity(systemActivities, activityInfo);
            if (foundActivity == null) {
                // this is a new activity; it cannot obtain >0 priority
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "New activity; cap priority to 0;"
                            + " package: " + applicationInfo.packageName
                            + " activity: " + intent.activity.className
                            + " origPrio: " + intent.getPriority());
                }
                intent.setPriority(0);
                return;
            }
            // found activity, now check for filter equivalence
            // a shallow copy is enough; we modify the list, not its contents
            final List<ActivityIntentInfo> intentListCopy =
                    new ArrayList<>(foundActivity.intents);
            final List<ActivityIntentInfo> foundFilters = findFilters(intent);
            // find matching action subsets
            final Iterator<String> actionsIterator = intent.actionsIterator();
            if (actionsIterator != null) {
                getIntentListSubset(
                        intentListCopy, new ActionIterGenerator(), actionsIterator);
                if (intentListCopy.size() == 0) {
                    // no more intents to match; we're not equivalent
                    if (DEBUG_FILTERS) {
                        Slog.i(TAG, "Mismatched action; cap priority to 0;"
                                + " package: " + applicationInfo.packageName
                                + " activity: " + intent.activity.className
                                + " origPrio: " + intent.getPriority());
                    }
                    intent.setPriority(0);
                    return;
                }
            }
            // find matching category subsets
            final Iterator<String> categoriesIterator = intent.categoriesIterator();
            if (categoriesIterator != null) {
                getIntentListSubset(intentListCopy, new CategoriesIterGenerator(),
                        categoriesIterator);
                if (intentListCopy.size() == 0) {
                    // no more intents to match; we're not equivalent
                    if (DEBUG_FILTERS) {
                        Slog.i(TAG, "Mismatched category; cap priority to 0;"
                                + " package: " + applicationInfo.packageName
                                + " activity: " + intent.activity.className
                                + " origPrio: " + intent.getPriority());
                    }
                    intent.setPriority(0);
                    return;
                }
            }
            // find matching schemes subsets
            final Iterator<String> schemesIterator = intent.schemesIterator();
            if (schemesIterator != null) {
                getIntentListSubset(intentListCopy, new SchemesIterGenerator(),
                        schemesIterator);
                if (intentListCopy.size() == 0) {
                    // no more intents to match; we're not equivalent
                    if (DEBUG_FILTERS) {
                        Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
                                + " package: " + applicationInfo.packageName
                                + " activity: " + intent.activity.className
                                + " origPrio: " + intent.getPriority());
                    }
                    intent.setPriority(0);
                    return;
                }
            }
            // find matching authorities subsets
            final Iterator<IntentFilter.AuthorityEntry>
                    authoritiesIterator = intent.authoritiesIterator();
            if (authoritiesIterator != null) {
                getIntentListSubset(intentListCopy,
                        new AuthoritiesIterGenerator(),
                        authoritiesIterator);
                if (intentListCopy.size() == 0) {
                    // no more intents to match; we're not equivalent
                    if (DEBUG_FILTERS) {
                        Slog.i(TAG, "Mismatched authority; cap priority to 0;"
                                + " package: " + applicationInfo.packageName
                                + " activity: " + intent.activity.className
                                + " origPrio: " + intent.getPriority());
                    }
                    intent.setPriority(0);
                    return;
                }
            }
            // we found matching filter(s); app gets the max priority of all intents
            int cappedPriority = 0;
            for (int i = intentListCopy.size() - 1; i >= 0; --i) {
                cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
            }
            if (intent.getPriority() > cappedPriority) {
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Found matching filter(s);"
                            + " cap priority to " + cappedPriority + ";"
                            + " package: " + applicationInfo.packageName
                            + " activity: " + intent.activity.className
                            + " origPrio: " + intent.getPriority());
                }
                intent.setPriority(cappedPriority);
                return;
            }
            // all this for nothing; the requested priority was <= what was on the system
        }
        public final void addActivity(PackageParser.Activity a, String type) {
            final boolean systemApp = a.info.applicationInfo.isSystemApp();
            mActivities.put(a.getComponentName(), a);
@@ -8756,10 +9006,12 @@ public class PackageManagerService extends IPackageManager.Stub {
            final int NI = a.intents.size();
            for (int j=0; j<NI; j++) {
                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
                if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
                    intent.setPriority(0);
                    Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
                            + a.className + " with priority > 0, forcing to 0");
                if ("activity".equals(type)) {
                    final PackageSetting ps =
                            mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
                    final List<PackageParser.Activity> systemActivities =
                            ps != null && ps.pkg != null ? ps.pkg.activities : null;
                    adjustPriority(systemActivities, intent);
                }
                if (DEBUG_SHOW_INFO) {
                    Log.v(TAG, "    IntentFilter:");
@@ -8913,18 +9165,6 @@ public class PackageManagerService extends IPackageManager.Stub {
            out.println();
        }
//        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
//            final Iterator<ResolveInfo> i = resolveInfoList.iterator();
//            final List<ResolveInfo> retList = Lists.newArrayList();
//            while (i.hasNext()) {
//                final ResolveInfo resolveInfo = i.next();
//                if (isEnabledLP(resolveInfo.activityInfo)) {
//                    retList.add(resolveInfo);
//                }
//            }
//            return retList;
//        }
        // Keys are String (activity class name), values are Activity.
        private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
                = new ArrayMap<ComponentName, PackageParser.Activity>();
@@ -10974,8 +11214,6 @@ public class PackageManagerService extends IPackageManager.Stub {
         * Called after the source arguments are copied. This is used mostly for
         * MoveParams when it needs to read the source file to put it in the
         * destination.
         *
         * @return
         */
        int doPostCopy(int uid) {
            return PackageManager.INSTALL_SUCCEEDED;