IntentResolver.java revision eae850cefe7e149f396c9e8ca1f34ec02b20a3f0
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
191d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackbornimport java.io.PrintWriter;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Comparator;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.LogPrinter;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class IntentResolver<F extends IntentFilter, R extends Object> {
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static String TAG = "IntentResolver";
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static boolean DEBUG = false;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static boolean localLOGV = DEBUG || Config.LOGV;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addFilter(F f) {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (localLOGV) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "Adding filter: " + f);
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "    Building Lookup Maps:");
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilters.add(f);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numS = register_intent_filter(f, f.schemesIterator(),
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSchemeToFilter, "      Scheme: ");
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numT = register_mime_types(f, "      Type: ");
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numS == 0 && numT == 0) {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register_intent_filter(f, f.actionsIterator(),
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mActionToFilter, "      Action: ");
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numT != 0) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register_intent_filter(f, f.actionsIterator(),
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTypedActionToFilter, "      TypedAction: ");
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeFilter(F f) {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeFilterInternal(f);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilters.remove(f);
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void removeFilterInternal(F f) {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (localLOGV) {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "Removing filter: " + f);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "    Cleaning Lookup Maps:");
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numS = unregister_intent_filter(f, f.schemesIterator(),
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSchemeToFilter, "      Scheme: ");
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numT = unregister_mime_types(f, "      Type: ");
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numS == 0 && numT == 0) {
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unregister_intent_filter(f, f.actionsIterator(),
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mActionToFilter, "      Action: ");
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numT != 0) {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unregister_intent_filter(f, f.actionsIterator(),
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTypedActionToFilter, "      TypedAction: ");
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
931d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn    void dumpMap(PrintWriter out, String prefix, Map<String, ArrayList<F>> map) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String eprefix = prefix + "  ";
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String fprefix = prefix + "    ";
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
971d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn            out.print(eprefix); out.print(e.getKey()); out.println(":");
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<F> a = e.getValue();
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = a.size();
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dumpFilter(out, fprefix, a.get(i));
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1061d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn    public void dump(PrintWriter out, String prefix) {
1071d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        String innerPrefix = prefix + "  ";
1081d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println("Full MIME Types:");
1091d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        dumpMap(out, innerPrefix, mTypeToFilter);
1101d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.println(" ");
1111d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println("Base MIME Types:");
1121d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        dumpMap(out, innerPrefix, mBaseTypeToFilter);
1131d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.println(" ");
1141d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println("Wild MIME Types:");
1151d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        dumpMap(out, innerPrefix, mWildTypeToFilter);
1161d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.println(" ");
1171d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println("Schemes:");
1181d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        dumpMap(out, innerPrefix, mSchemeToFilter);
1191d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.println(" ");
1201d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println("Non-Data Actions:");
1211d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        dumpMap(out, innerPrefix, mActionToFilter);
1221d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.println(" ");
1231d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println("MIME Typed Actions:");
1241d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        dumpMap(out, innerPrefix, mTypedActionToFilter);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class IteratorWrapper implements Iterator<F> {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Iterator<F> mI;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private F mCur;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IteratorWrapper(Iterator<F> it) {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mI = it;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean hasNext() {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mI.hasNext();
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public F next() {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (mCur = mI.next());
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void remove() {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCur != null) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeFilterInternal(mCur);
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mI.remove();
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns an iterator allowing filters to be removed.
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Iterator<F> filterIterator() {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new IteratorWrapper(mFilters.iterator());
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a read-only set of the filters.
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Set<F> filterSet() {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Collections.unmodifiableSet(mFilters);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
166eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda    public List<R> queryIntentFromList(Intent intent, String resolvedType,
167eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda            boolean defaultOnly, ArrayList<ArrayList<F>> listCut) {
168eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        ArrayList<R> resultList = new ArrayList<R>();
169eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
170eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        final boolean debug = localLOGV ||
171eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
172eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
173eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        final String scheme = intent.getScheme();
174eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        int N = listCut.size();
175eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        for (int i = 0; i < N; ++i) {
176eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda            buildResolveList(intent, debug, defaultOnly,
177eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda                             resolvedType, scheme, listCut.get(i), resultList);
178eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        }
179eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        sortResults(resultList);
180eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        return resultList;
181eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda    }
182eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<R> queryIntent(ContentResolver resolver, Intent intent,
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String resolvedType, boolean defaultOnly) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String scheme = intent.getScheme();
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<R> finalList = new ArrayList<R>();
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean debug = localLOGV ||
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (debug) Log.v(
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TAG, "Resolving type " + resolvedType + " scheme " + scheme
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + " of intent " + intent);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> firstTypeCut = null;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> secondTypeCut = null;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> thirdTypeCut = null;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> schemeCut = null;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent includes a MIME type, then we want to collect all of
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the filters that match that MIME type.
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (resolvedType != null) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int slashpos = resolvedType.indexOf('/');
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String baseType = resolvedType.substring(0, slashpos);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!baseType.equals("*")) {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (resolvedType.length() != slashpos+2
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            || resolvedType.charAt(slashpos+1) != '*') {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Not a wild card, so we can just look for all filters that
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // completely match or wildcards whose base type matches.
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        firstTypeCut = mTypeToFilter.get(resolvedType);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (debug) Log.v(TAG, "First type cut: " + firstTypeCut);
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        secondTypeCut = mWildTypeToFilter.get(baseType);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (debug) Log.v(TAG, "Second type cut: " + secondTypeCut);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We can match anything with our base type.
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        firstTypeCut = mBaseTypeToFilter.get(baseType);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (debug) Log.v(TAG, "First type cut: " + firstTypeCut);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        secondTypeCut = mWildTypeToFilter.get(baseType);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (debug) Log.v(TAG, "Second type cut: " + secondTypeCut);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Any */* types always apply, but we only need to do this
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if the intent type was not already */*.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    thirdTypeCut = mWildTypeToFilter.get("*");
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (debug) Log.v(TAG, "Third type cut: " + thirdTypeCut);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (intent.getAction() != null) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // The intent specified any type ({@literal *}/*).  This
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // can be a whole heck of a lot of things, so as a first
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // cut let's use the action instead.
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (debug) Log.v(TAG, "Typed Action list: " + firstTypeCut);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent includes a data URI, then we want to collect all of
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the filters that match its scheme (we will further refine matches
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // on the authority and path by directly matching each resulting filter).
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (scheme != null) {
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            schemeCut = mSchemeToFilter.get(scheme);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (debug) Log.v(TAG, "Scheme list: " + schemeCut);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent does not specify any data -- either a MIME type or
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // a URI -- then we will only be looking for matches against empty
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // data.
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (resolvedType == null && scheme == null && intent.getAction() != null) {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            firstTypeCut = mActionToFilter.get(intent.getAction());
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (debug) Log.v(TAG, "Action list: " + firstTypeCut);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (firstTypeCut != null) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, firstTypeCut, finalList);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (secondTypeCut != null) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, secondTypeCut, finalList);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thirdTypeCut != null) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, thirdTypeCut, finalList);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (schemeCut != null) {
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, schemeCut, finalList);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sortResults(finalList);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (debug) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "Final result list:");
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (R r : finalList) {
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.v(TAG, "  " + r);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return finalList;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control whether the given filter is allowed to go into the result
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * list.  Mainly intended to prevent adding multiple filters for the
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same target object.
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean allowFilterResult(F filter, List<R> dest) {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected R newResult(F filter, int match) {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (R)filter;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void sortResults(List<R> results) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Collections.sort(results, mResolvePrioritySorter);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2971d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
2981d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println(filter);
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int register_mime_types(F filter, String prefix) {
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Iterator<String> i = filter.typesIterator();
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = (String)i.next();
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (localLOGV) Log.v(TAG, prefix + name);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String baseName = name;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int slashpos = name.indexOf('/');
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                baseName = name.substring(0, slashpos).intern();
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                name = name + "/*";
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<F> array = mTypeToFilter.get(name);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array == null) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.v(TAG, "Creating new array for " + name);
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = new ArrayList<F>();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTypeToFilter.put(name, array);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            array.add(filter);
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = mBaseTypeToFilter.get(baseName);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (array == null) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    //Log.v(TAG, "Creating new array for " + name);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = new ArrayList<F>();
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mBaseTypeToFilter.put(baseName, array);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array.add(filter);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = mWildTypeToFilter.get(baseName);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (array == null) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    //Log.v(TAG, "Creating new array for " + name);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = new ArrayList<F>();
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mWildTypeToFilter.put(baseName, array);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array.add(filter);
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int unregister_mime_types(F filter, String prefix) {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Iterator<String> i = filter.typesIterator();
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = (String)i.next();
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (localLOGV) Log.v(TAG, prefix + name);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String baseName = name;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int slashpos = name.indexOf('/');
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                baseName = name.substring(0, slashpos).intern();
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                name = name + "/*";
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!remove_all_objects(mTypeToFilter.get(name), filter)) {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTypeToFilter.remove(name);
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mBaseTypeToFilter.remove(baseName);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mWildTypeToFilter.remove(baseName);
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int register_intent_filter(F filter, Iterator<String> i,
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashMap<String, ArrayList<F>> dest, String prefix) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = i.next();
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (localLOGV) Log.v(TAG, prefix + name);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<F> array = dest.get(name);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array == null) {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.v(TAG, "Creating new array for " + name);
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = new ArrayList<F>();
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dest.put(name, array);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            array.add(filter);
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int unregister_intent_filter(F filter, Iterator<String> i,
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashMap<String, ArrayList<F>> dest, String prefix) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = i.next();
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (localLOGV) Log.v(TAG, prefix + name);
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!remove_all_objects(dest.get(name), filter)) {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dest.remove(name);
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final boolean remove_all_objects(List<F> list, Object object) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (list != null) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = list.size();
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int idx=0; idx<N; idx++) {
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (list.get(idx) == object) {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list.remove(idx);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    idx--;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    N--;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return N > 0;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void buildResolveList(Intent intent, boolean debug, boolean defaultOnly,
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String resolvedType, String scheme, List<F> src, List<R> dest) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Set<String> categories = intent.getCategories();
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = src != null ? src.size() : 0;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasNonDefaults = false;
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (i=0; i<N; i++) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            F filter = src.get(i);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int match;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (debug) Log.v(TAG, "Matching against filter " + filter);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Do we already have this one?
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!allowFilterResult(filter, dest)) {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.v(TAG, "  Filter's target already added");
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            match = filter.match(
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.getAction(), resolvedType, scheme, intent.getData(), categories, TAG);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (match >= 0) {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) Log.v(TAG, "  Filter matched!  match=0x" +
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Integer.toHexString(match));
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final R oneResult = newResult(filter, match);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (oneResult != null) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        dest.add(oneResult);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasNonDefaults = true;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String reason;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (match) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        default: reason = "unknown reason"; break;
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.v(TAG, "  Filter did not match: " + reason);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dest.size() == 0 && hasNonDefaults) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT");
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Sorts a List of IntentFilter objects into descending priority order.
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Comparator mResolvePrioritySorter = new Comparator() {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int compare(Object o1, Object o2) {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float q1 = ((IntentFilter)o1).getPriority();
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float q2 = ((IntentFilter)o2).getPriority();
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All filters that have been registered.
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashSet<F> mFilters = new HashSet<F>();
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the MIME types that have been registered, such as "image/jpeg",
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "image/*", or "{@literal *}/*".
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mTypeToFilter
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The base names of all of all fully qualified MIME types that have been
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * registered, such as "image" or "*".  Wild card MIME types such as
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "image/*" will not be here.
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mBaseTypeToFilter
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The base names of all of the MIME types with a sub-type wildcard that
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have been registered.  For example, a filter with "image/*" will be
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * included here as "image" but one with "image/jpeg" will not be
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * included here.  This also includes the "*" for the "{@literal *}/*"
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * MIME type.
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mWildTypeToFilter
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the URI schemes (such as http) that have been registered.
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mSchemeToFilter
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the actions that have been registered, but only those that did
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not specify data.
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mActionToFilter
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the actions that have been registered and specified a MIME type.
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mTypedActionToFilter
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
553