IntentResolver.java revision 1d442e0d990b581357f33f5463c7c5cb49b551e8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (C) 2006 The Android Open Source Project
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Licensed under the Apache License, Version 2.0 (the "License");
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * you may not use this file except in compliance with the License.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * You may obtain a copy of the License at
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *      http://www.apache.org/licenses/LICENSE-2.0
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unless required by applicable law or agreed to in writing, software
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * distributed under the License is distributed on an "AS IS" BASIS,
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See the License for the specific language governing permissions and
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * limitations under the License.
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpackage com.android.server;
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.io.PrintWriter;
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.ArrayList;
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.Collections;
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.Comparator;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.HashMap;
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.HashSet;
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.Iterator;
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.List;
271e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtimport java.util.Map;
281e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtimport java.util.Set;
291e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.util.Log;
311e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtimport android.util.LogPrinter;
321e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtimport android.util.Printer;
331e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt
341e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtimport android.util.Config;
351e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtimport android.content.ContentResolver;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.content.Intent;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.content.IntentFilter;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * {@hide}
41cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt */
42cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtpublic class IntentResolver<F extends IntentFilter, R extends Object> {
43cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    final private static String TAG = "IntentResolver";
44cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    final private static boolean DEBUG = false;
45cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    final private static boolean localLOGV = DEBUG || Config.LOGV;
46cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
47cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    public void addFilter(F f) {
48cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        if (localLOGV) {
49cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            Log.v(TAG, "Adding filter: " + f);
5004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            f.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
511e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt            Log.v(TAG, "    Building Lookup Maps:");
521e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt        }
531e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt
541e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt        mFilters.add(f);
551e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt        int numS = register_intent_filter(f, f.schemesIterator(),
561e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt                mSchemeToFilter, "      Scheme: ");
571e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt        int numT = register_mime_types(f, "      Type: ");
581e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt        if (numS == 0 && numT == 0) {
591e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt            register_intent_filter(f, f.actionsIterator(),
601e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt                    mActionToFilter, "      Action: ");
6104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        }
6204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        if (numT != 0) {
6304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            register_intent_filter(f, f.actionsIterator(),
6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt                    mTypedActionToFilter, "      TypedAction: ");
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public void removeFilter(F f) {
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        removeFilterInternal(f);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        mFilters.remove(f);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    void removeFilterInternal(F f) {
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (localLOGV) {
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            Log.v(TAG, "Removing filter: " + f);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            f.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            Log.v(TAG, "    Cleaning Lookup Maps:");
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        int numS = unregister_intent_filter(f, f.schemesIterator(),
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                mSchemeToFilter, "      Scheme: ");
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        int numT = unregister_mime_types(f, "      Type: ");
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (numS == 0 && numT == 0) {
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            unregister_intent_filter(f, f.actionsIterator(),
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    mActionToFilter, "      Action: ");
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (numT != 0) {
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            unregister_intent_filter(f, f.actionsIterator(),
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    mTypedActionToFilter, "      TypedAction: ");
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    void dumpMap(PrintWriter out, String prefix, Map<String, ArrayList<F>> map) {
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        String eprefix = prefix + "  ";
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        String fprefix = prefix + "    ";
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            out.print(eprefix); out.print(e.getKey()); out.println(":");
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            ArrayList<F> a = e.getValue();
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            final int N = a.size();
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            for (int i=0; i<N; i++) {
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                dumpFilter(out, fprefix, a.get(i));
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public void dump(PrintWriter out, String prefix) {
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        String innerPrefix = prefix + "  ";
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println("Full MIME Types:");
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        dumpMap(out, innerPrefix, mTypeToFilter);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.println(" ");
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println("Base MIME Types:");
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        dumpMap(out, innerPrefix, mBaseTypeToFilter);
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.println(" ");
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println("Wild MIME Types:");
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        dumpMap(out, innerPrefix, mWildTypeToFilter);
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.println(" ");
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println("Schemes:");
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        dumpMap(out, innerPrefix, mSchemeToFilter);
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.println(" ");
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println("Non-Data Actions:");
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        dumpMap(out, innerPrefix, mActionToFilter);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.println(" ");
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println("MIME Typed Actions:");
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        dumpMap(out, innerPrefix, mTypedActionToFilter);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private class IteratorWrapper implements Iterator<F> {
12868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt        private final Iterator<F> mI;
12968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt        private F mCur;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        IteratorWrapper(Iterator<F> it) {
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            mI = it;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        public boolean hasNext() {
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return mI.hasNext();
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        public F next() {
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return (mCur = mI.next());
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        public void remove() {
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (mCur != null) {
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                removeFilterInternal(mCur);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            mI.remove();
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    /**
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     * Returns an iterator allowing filters to be removed.
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     */
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public Iterator<F> filterIterator() {
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return new IteratorWrapper(mFilters.iterator());
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    /**
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     * Returns a read-only set of the filters.
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     */
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public Set<F> filterSet() {
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return Collections.unmodifiableSet(mFilters);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public List<R> queryIntent(ContentResolver resolver, Intent intent,
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String resolvedType, boolean defaultOnly) {
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        String scheme = intent.getScheme();
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        ArrayList<R> finalList = new ArrayList<R>();
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        final boolean debug = localLOGV ||
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (debug) Log.v(
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            TAG, "Resolving type " + resolvedType + " scheme " + scheme
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            + " of intent " + intent);
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        ArrayList<F> firstTypeCut = null;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        ArrayList<F> secondTypeCut = null;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        ArrayList<F> thirdTypeCut = null;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        ArrayList<F> schemeCut = null;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // If the intent includes a MIME type, then we want to collect all of
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // the filters that match that MIME type.
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (resolvedType != null) {
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            int slashpos = resolvedType.indexOf('/');
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (slashpos > 0) {
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                final String baseType = resolvedType.substring(0, slashpos);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (!baseType.equals("*")) {
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    if (resolvedType.length() != slashpos+2
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                            || resolvedType.charAt(slashpos+1) != '*') {
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        // Not a wild card, so we can just look for all filters that
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        // completely match or wildcards whose base type matches.
19568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt                        firstTypeCut = mTypeToFilter.get(resolvedType);
19668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt                        if (debug) Log.v(TAG, "First type cut: " + firstTypeCut);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        secondTypeCut = mWildTypeToFilter.get(baseType);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        if (debug) Log.v(TAG, "Second type cut: " + secondTypeCut);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    } else {
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        // We can match anything with our base type.
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        firstTypeCut = mBaseTypeToFilter.get(baseType);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        if (debug) Log.v(TAG, "First type cut: " + firstTypeCut);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        secondTypeCut = mWildTypeToFilter.get(baseType);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        if (debug) Log.v(TAG, "Second type cut: " + secondTypeCut);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    }
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    // Any */* types always apply, but we only need to do this
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    // if the intent type was not already */*.
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    thirdTypeCut = mWildTypeToFilter.get("*");
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    if (debug) Log.v(TAG, "Third type cut: " + thirdTypeCut);
210fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt                } else if (intent.getAction() != null) {
211fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt                    // The intent specified any type ({@literal *}/*).  This
212fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt                    // can be a whole heck of a lot of things, so as a first
213fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt                    // cut let's use the action instead.
214fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
21568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt                    if (debug) Log.v(TAG, "Typed Action list: " + firstTypeCut);
21668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt                }
21768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt            }
21868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt        }
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // If the intent includes a data URI, then we want to collect all of
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // the filters that match its scheme (we will further refine matches
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // on the authority and path by directly matching each resulting filter).
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (scheme != null) {
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            schemeCut = mSchemeToFilter.get(scheme);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (debug) Log.v(TAG, "Scheme list: " + schemeCut);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // If the intent does not specify any data -- either a MIME type or
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // a URI -- then we will only be looking for matches against empty
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // data.
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (resolvedType == null && scheme == null && intent.getAction() != null) {
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            firstTypeCut = mActionToFilter.get(intent.getAction());
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (debug) Log.v(TAG, "Action list: " + firstTypeCut);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (firstTypeCut != null) {
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            buildResolveList(intent, debug, defaultOnly,
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    resolvedType, scheme, firstTypeCut, finalList);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (secondTypeCut != null) {
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            buildResolveList(intent, debug, defaultOnly,
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    resolvedType, scheme, secondTypeCut, finalList);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (thirdTypeCut != null) {
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            buildResolveList(intent, debug, defaultOnly,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    resolvedType, scheme, thirdTypeCut, finalList);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (schemeCut != null) {
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            buildResolveList(intent, debug, defaultOnly,
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    resolvedType, scheme, schemeCut, finalList);
25168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt        }
25268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt        sortResults(finalList);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (debug) {
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            Log.v(TAG, "Final result list:");
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            for (R r : finalList) {
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                Log.v(TAG, "  " + r);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return finalList;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    /**
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     * Control whether the given filter is allowed to go into the result
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     * list.  Mainly intended to prevent adding multiple filters for the
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     * same target object.
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt     */
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    protected boolean allowFilterResult(F filter, List<R> dest) {
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return true;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    protected R newResult(F filter, int match) {
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return (R)filter;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    protected void sortResults(List<R> results) {
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        Collections.sort(results, mResolvePrioritySorter);
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        out.print(prefix); out.println(filter);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private final int register_mime_types(F filter, String prefix) {
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        final Iterator<String> i = filter.typesIterator();
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (i == null) {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return 0;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        int num = 0;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        while (i.hasNext()) {
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String name = (String)i.next();
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            num++;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (localLOGV) Log.v(TAG, prefix + name);
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String baseName = name;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            final int slashpos = name.indexOf('/');
2976cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt            if (slashpos > 0) {
2986cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt                baseName = name.substring(0, slashpos).intern();
2996cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt            } else {
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                name = name + "/*";
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            ArrayList<F> array = mTypeToFilter.get(name);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (array == null) {
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                //Log.v(TAG, "Creating new array for " + name);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                array = new ArrayList<F>();
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                mTypeToFilter.put(name, array);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            array.add(filter);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (slashpos > 0) {
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                array = mBaseTypeToFilter.get(baseName);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (array == null) {
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    //Log.v(TAG, "Creating new array for " + name);
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    array = new ArrayList<F>();
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    mBaseTypeToFilter.put(baseName, array);
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                }
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                array.add(filter);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            } else {
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                array = mWildTypeToFilter.get(baseName);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (array == null) {
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    //Log.v(TAG, "Creating new array for " + name);
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    array = new ArrayList<F>();
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    mWildTypeToFilter.put(baseName, array);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                }
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                array.add(filter);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return num;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private final int unregister_mime_types(F filter, String prefix) {
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        final Iterator<String> i = filter.typesIterator();
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (i == null) {
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return 0;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        int num = 0;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        while (i.hasNext()) {
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String name = (String)i.next();
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            num++;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (localLOGV) Log.v(TAG, prefix + name);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String baseName = name;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            final int slashpos = name.indexOf('/');
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (slashpos > 0) {
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                baseName = name.substring(0, slashpos).intern();
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            } else {
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                name = name + "/*";
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (!remove_all_objects(mTypeToFilter.get(name), filter)) {
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                mTypeToFilter.remove(name);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (slashpos > 0) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) {
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    mBaseTypeToFilter.remove(baseName);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                }
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            } else {
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) {
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    mWildTypeToFilter.remove(baseName);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                }
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return num;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private final int register_intent_filter(F filter, Iterator<String> i,
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            HashMap<String, ArrayList<F>> dest, String prefix) {
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (i == null) {
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return 0;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        int num = 0;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        while (i.hasNext()) {
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String name = i.next();
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            num++;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (localLOGV) Log.v(TAG, prefix + name);
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            ArrayList<F> array = dest.get(name);
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (array == null) {
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                //Log.v(TAG, "Creating new array for " + name);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                array = new ArrayList<F>();
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                dest.put(name, array);
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
38604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            array.add(filter);
38704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        }
38804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        return num;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private final int unregister_intent_filter(F filter, Iterator<String> i,
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            HashMap<String, ArrayList<F>> dest, String prefix) {
39304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        if (i == null) {
3945460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt            return 0;
3955460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt        }
39604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
39704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        int num = 0;
39804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        while (i.hasNext()) {
399cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            String name = i.next();
400cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            num++;
401cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            if (localLOGV) Log.v(TAG, prefix + name);
402cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            if (!remove_all_objects(dest.get(name), filter)) {
403cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                dest.remove(name);
404cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            }
405cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        }
406cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        return num;
40704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt    }
40804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
40904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt    private final boolean remove_all_objects(List<F> list, Object object) {
4105460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt        if (list != null) {
4115460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt            int N = list.size();
41204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            for (int idx=0; idx<N; idx++) {
41304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt                if (list.get(idx) == object) {
414cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                    list.remove(idx);
415cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                    idx--;
416cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                    N--;
417cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                }
418cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            }
41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            return N > 0;
42004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        }
42104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        return false;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private void buildResolveList(Intent intent, boolean debug, boolean defaultOnly,
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            String resolvedType, String scheme, List<F> src, List<R> dest) {
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        Set<String> categories = intent.getCategories();
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        final int N = src != null ? src.size() : 0;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        boolean hasNonDefaults = false;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        int i;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        for (i=0; i<N; i++) {
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            F filter = src.get(i);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            int match;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (debug) Log.v(TAG, "Matching against filter " + filter);
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            // Do we already have this one?
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (!allowFilterResult(filter, dest)) {
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (debug) {
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    Log.v(TAG, "  Filter's target already added");
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                }
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                continue;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            }
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            match = filter.match(
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    intent.getAction(), resolvedType, scheme, intent.getData(), categories, TAG);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            if (match >= 0) {
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (debug) Log.v(TAG, "  Filter matched!  match=0x" +
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        Integer.toHexString(match));
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    final R oneResult = newResult(filter, match);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    if (oneResult != null) {
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                        dest.add(oneResult);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                    }
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                } else {
4554b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                    hasNonDefaults = true;
4564b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                }
4574b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt            } else {
4584b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                if (debug) {
4594b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                    String reason;
4604b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                    switch (match) {
4614b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                        case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
4624b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                        case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
4634b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                        case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
4644b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                        case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
4654b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt                        default: reason = "unknown reason"; break;
466cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                    }
467cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                    Log.v(TAG, "  Filter did not match: " + reason);
468cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt                }
469cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            }
470cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        }
471cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
472cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        if (dest.size() == 0 && hasNonDefaults) {
473cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            Log.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT");
474cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        }
475cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    }
476cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
477cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    // Sorts a List of IntentFilter objects into descending priority order.
478cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    private static final Comparator mResolvePrioritySorter = new Comparator() {
479cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        public int compare(Object o1, Object o2) {
480cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            float q1 = ((IntentFilter)o1).getPriority();
481cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            float q2 = ((IntentFilter)o2).getPriority();
482cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt            return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
483cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt        }
484cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt    };
485cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
486    /**
487     * All filters that have been registered.
488     */
489    private final HashSet<F> mFilters = new HashSet<F>();
490
491    /**
492     * All of the MIME types that have been registered, such as "image/jpeg",
493     * "image/*", or "{@literal *}/*".
494     */
495    private final HashMap<String, ArrayList<F>> mTypeToFilter
496            = new HashMap<String, ArrayList<F>>();
497
498    /**
499     * The base names of all of all fully qualified MIME types that have been
500     * registered, such as "image" or "*".  Wild card MIME types such as
501     * "image/*" will not be here.
502     */
503    private final HashMap<String, ArrayList<F>> mBaseTypeToFilter
504            = new HashMap<String, ArrayList<F>>();
505
506    /**
507     * The base names of all of the MIME types with a sub-type wildcard that
508     * have been registered.  For example, a filter with "image/*" will be
509     * included here as "image" but one with "image/jpeg" will not be
510     * included here.  This also includes the "*" for the "{@literal *}/*"
511     * MIME type.
512     */
513    private final HashMap<String, ArrayList<F>> mWildTypeToFilter
514            = new HashMap<String, ArrayList<F>>();
515
516    /**
517     * All of the URI schemes (such as http) that have been registered.
518     */
519    private final HashMap<String, ArrayList<F>> mSchemeToFilter
520            = new HashMap<String, ArrayList<F>>();
521
522    /**
523     * All of the actions that have been registered, but only those that did
524     * not specify data.
525     */
526    private final HashMap<String, ArrayList<F>> mActionToFilter
527            = new HashMap<String, ArrayList<F>>();
528
529    /**
530     * All of the actions that have been registered and specified a MIME type.
531     */
532    private final HashMap<String, ArrayList<F>> mTypedActionToFilter
533            = new HashMap<String, ArrayList<F>>();
534}
535
536