IntentResolver.java revision d4310ac944e5f3063bb23558ba25ccf76fec0968
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;
318a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.LogPrinter;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class IntentResolver<F extends IntentFilter, R extends Object> {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static String TAG = "IntentResolver";
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static boolean DEBUG = false;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static boolean localLOGV = DEBUG || Config.LOGV;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addFilter(F f) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (localLOGV) {
508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Adding filter: " + f);
518a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "    Building Lookup Maps:");
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilters.add(f);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numS = register_intent_filter(f, f.schemesIterator(),
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSchemeToFilter, "      Scheme: ");
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numT = register_mime_types(f, "      Type: ");
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numS == 0 && numT == 0) {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register_intent_filter(f, f.actionsIterator(),
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mActionToFilter, "      Action: ");
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numT != 0) {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register_intent_filter(f, f.actionsIterator(),
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTypedActionToFilter, "      TypedAction: ");
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeFilter(F f) {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeFilterInternal(f);
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilters.remove(f);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void removeFilterInternal(F f) {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (localLOGV) {
768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Removing filter: " + f);
778a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "    Cleaning Lookup Maps:");
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numS = unregister_intent_filter(f, f.schemesIterator(),
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSchemeToFilter, "      Scheme: ");
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numT = unregister_mime_types(f, "      Type: ");
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numS == 0 && numT == 0) {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unregister_intent_filter(f, f.actionsIterator(),
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mActionToFilter, "      Action: ");
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numT != 0) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unregister_intent_filter(f, f.actionsIterator(),
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTypedActionToFilter, "      TypedAction: ");
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
94d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    boolean dumpMap(PrintWriter out, String titlePrefix, String title,
95d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            String prefix, Map<String, ArrayList<F>> map, String packageName) {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String eprefix = prefix + "  ";
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String fprefix = prefix + "    ";
98d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        boolean printedSomething = false;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<F> a = e.getValue();
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = a.size();
102d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            boolean printedHeader = false;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
104d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                F filter = a.get(i);
105d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                if (packageName != null && !packageName.equals(packageForFilter(filter))) {
106d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    continue;
107d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                }
108d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                if (title != null) {
109d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    out.print(titlePrefix); out.println(title);
110d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    title = null;
111d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                }
112d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                if (!printedHeader) {
113d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    out.print(eprefix); out.print(e.getKey()); out.println(":");
114d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    printedHeader = true;
115d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                }
116d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                printedSomething = true;
117d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                dumpFilter(out, fprefix, filter);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
120d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        return printedSomething;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
123d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    public boolean dump(PrintWriter out, String title, String prefix, String packageName) {
1241d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        String innerPrefix = prefix + "  ";
125d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        String sepPrefix = "\n" + prefix;
126d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        String curPrefix = title + "\n" + prefix;
127d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Full MIME Types:", innerPrefix,
128d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                mTypeToFilter, packageName)) {
129d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
130d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
131d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Base MIME Types:", innerPrefix,
132d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                mBaseTypeToFilter, packageName)) {
133d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
134d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
135d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Wild MIME Types:", innerPrefix,
136d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                mWildTypeToFilter, packageName)) {
137d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
138d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
139d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Schemes:", innerPrefix,
140d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                mSchemeToFilter, packageName)) {
141d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
142d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
143d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Non-Data Actions:", innerPrefix,
144d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                mActionToFilter, packageName)) {
145d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
146d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
147d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "MIME Typed Actions:", innerPrefix,
148d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                mTypedActionToFilter, packageName)) {
149d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
150d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
151d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        return curPrefix == sepPrefix;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class IteratorWrapper implements Iterator<F> {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Iterator<F> mI;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private F mCur;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IteratorWrapper(Iterator<F> it) {
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mI = it;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean hasNext() {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mI.hasNext();
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public F next() {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (mCur = mI.next());
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void remove() {
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCur != null) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeFilterInternal(mCur);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mI.remove();
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns an iterator allowing filters to be removed.
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Iterator<F> filterIterator() {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new IteratorWrapper(mFilters.iterator());
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a read-only set of the filters.
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Set<F> filterSet() {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Collections.unmodifiableSet(mFilters);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
193eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda    public List<R> queryIntentFromList(Intent intent, String resolvedType,
194eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda            boolean defaultOnly, ArrayList<ArrayList<F>> listCut) {
195eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        ArrayList<R> resultList = new ArrayList<R>();
196eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
197eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        final boolean debug = localLOGV ||
198eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
199eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
200eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        final String scheme = intent.getScheme();
201eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        int N = listCut.size();
202eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        for (int i = 0; i < N; ++i) {
203eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda            buildResolveList(intent, debug, defaultOnly,
204eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda                             resolvedType, scheme, listCut.get(i), resultList);
205eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        }
206eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        sortResults(resultList);
207eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        return resultList;
208eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda    }
209eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
210074edef7c4fce50fc780e864068305f01965e3acMihai Preda    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String scheme = intent.getScheme();
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<R> finalList = new ArrayList<R>();
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean debug = localLOGV ||
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2188a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (debug) Slog.v(
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TAG, "Resolving type " + resolvedType + " scheme " + scheme
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + " of intent " + intent);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> firstTypeCut = null;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> secondTypeCut = null;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> thirdTypeCut = null;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<F> schemeCut = null;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent includes a MIME type, then we want to collect all of
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the filters that match that MIME type.
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (resolvedType != null) {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int slashpos = resolvedType.indexOf('/');
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String baseType = resolvedType.substring(0, slashpos);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!baseType.equals("*")) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (resolvedType.length() != slashpos+2
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            || resolvedType.charAt(slashpos+1) != '*') {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Not a wild card, so we can just look for all filters that
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // completely match or wildcards whose base type matches.
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        firstTypeCut = mTypeToFilter.get(resolvedType);
2398a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut);
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        secondTypeCut = mWildTypeToFilter.get(baseType);
2418a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We can match anything with our base type.
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        firstTypeCut = mBaseTypeToFilter.get(baseType);
2458a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        secondTypeCut = mWildTypeToFilter.get(baseType);
2478a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Any */* types always apply, but we only need to do this
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if the intent type was not already */*.
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    thirdTypeCut = mWildTypeToFilter.get("*");
2528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (debug) Slog.v(TAG, "Third type cut: " + thirdTypeCut);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (intent.getAction() != null) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // The intent specified any type ({@literal *}/*).  This
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // can be a whole heck of a lot of things, so as a first
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // cut let's use the action instead.
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
2588a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (debug) Slog.v(TAG, "Typed Action list: " + firstTypeCut);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent includes a data URI, then we want to collect all of
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the filters that match its scheme (we will further refine matches
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // on the authority and path by directly matching each resulting filter).
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (scheme != null) {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            schemeCut = mSchemeToFilter.get(scheme);
2688a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (debug) Slog.v(TAG, "Scheme list: " + schemeCut);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent does not specify any data -- either a MIME type or
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // a URI -- then we will only be looking for matches against empty
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // data.
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (resolvedType == null && scheme == null && intent.getAction() != null) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            firstTypeCut = mActionToFilter.get(intent.getAction());
2768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (debug) Slog.v(TAG, "Action list: " + firstTypeCut);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (firstTypeCut != null) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, firstTypeCut, finalList);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (secondTypeCut != null) {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, secondTypeCut, finalList);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thirdTypeCut != null) {
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, thirdTypeCut, finalList);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (schemeCut != null) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buildResolveList(intent, debug, defaultOnly,
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resolvedType, scheme, schemeCut, finalList);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sortResults(finalList);
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (debug) {
2988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Final result list:");
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (R r : finalList) {
3008a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.v(TAG, "  " + r);
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return finalList;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control whether the given filter is allowed to go into the result
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * list.  Mainly intended to prevent adding multiple filters for the
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same target object.
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean allowFilterResult(F filter, List<R> dest) {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
315d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    protected String packageForFilter(F filter) {
316d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        return null;
317d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    }
318d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected R newResult(F filter, int match) {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (R)filter;
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void sortResults(List<R> results) {
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Collections.sort(results, mResolvePrioritySorter);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3271d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
3281d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println(filter);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int register_mime_types(F filter, String prefix) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Iterator<String> i = filter.typesIterator();
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = (String)i.next();
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
3418a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String baseName = name;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int slashpos = name.indexOf('/');
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                baseName = name.substring(0, slashpos).intern();
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                name = name + "/*";
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<F> array = mTypeToFilter.get(name);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array == null) {
3528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                //Slog.v(TAG, "Creating new array for " + name);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = new ArrayList<F>();
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTypeToFilter.put(name, array);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            array.add(filter);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = mBaseTypeToFilter.get(baseName);
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (array == null) {
3618a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    //Slog.v(TAG, "Creating new array for " + name);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = new ArrayList<F>();
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mBaseTypeToFilter.put(baseName, array);
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array.add(filter);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = mWildTypeToFilter.get(baseName);
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (array == null) {
3698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    //Slog.v(TAG, "Creating new array for " + name);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = new ArrayList<F>();
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mWildTypeToFilter.put(baseName, array);
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array.add(filter);
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int unregister_mime_types(F filter, String prefix) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Iterator<String> i = filter.typesIterator();
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = (String)i.next();
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
3908a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String baseName = name;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int slashpos = name.indexOf('/');
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                baseName = name.substring(0, slashpos).intern();
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                name = name + "/*";
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!remove_all_objects(mTypeToFilter.get(name), filter)) {
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTypeToFilter.remove(name);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mBaseTypeToFilter.remove(baseName);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mWildTypeToFilter.remove(baseName);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int register_intent_filter(F filter, Iterator<String> i,
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashMap<String, ArrayList<F>> dest, String prefix) {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = i.next();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4268a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<F> array = dest.get(name);
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array == null) {
4298a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                //Slog.v(TAG, "Creating new array for " + name);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = new ArrayList<F>();
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dest.put(name, array);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            array.add(filter);
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int unregister_intent_filter(F filter, Iterator<String> i,
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashMap<String, ArrayList<F>> dest, String prefix) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = i.next();
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4488a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!remove_all_objects(dest.get(name), filter)) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dest.remove(name);
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final boolean remove_all_objects(List<F> list, Object object) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (list != null) {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = list.size();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int idx=0; idx<N; idx++) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (list.get(idx) == object) {
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list.remove(idx);
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    idx--;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    N--;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return N > 0;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void buildResolveList(Intent intent, boolean debug, boolean defaultOnly,
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String resolvedType, String scheme, List<F> src, List<R> dest) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Set<String> categories = intent.getCategories();
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = src != null ? src.size() : 0;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasNonDefaults = false;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (i=0; i<N; i++) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            F filter = src.get(i);
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int match;
4818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (debug) Slog.v(TAG, "Matching against filter " + filter);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Do we already have this one?
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!allowFilterResult(filter, dest)) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) {
4868a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.v(TAG, "  Filter's target already added");
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            match = filter.match(
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.getAction(), resolvedType, scheme, intent.getData(), categories, TAG);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (match >= 0) {
4948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Integer.toHexString(match));
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final R oneResult = newResult(filter, match);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (oneResult != null) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        dest.add(oneResult);
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasNonDefaults = true;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String reason;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (match) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        default: reason = "unknown reason"; break;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5148a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.v(TAG, "  Filter did not match: " + reason);
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dest.size() == 0 && hasNonDefaults) {
5208a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT");
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Sorts a List of IntentFilter objects into descending priority order.
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Comparator mResolvePrioritySorter = new Comparator() {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int compare(Object o1, Object o2) {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float q1 = ((IntentFilter)o1).getPriority();
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float q2 = ((IntentFilter)o2).getPriority();
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All filters that have been registered.
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashSet<F> mFilters = new HashSet<F>();
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the MIME types that have been registered, such as "image/jpeg",
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "image/*", or "{@literal *}/*".
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mTypeToFilter
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The base names of all of all fully qualified MIME types that have been
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * registered, such as "image" or "*".  Wild card MIME types such as
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "image/*" will not be here.
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mBaseTypeToFilter
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The base names of all of the MIME types with a sub-type wildcard that
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have been registered.  For example, a filter with "image/*" will be
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * included here as "image" but one with "image/jpeg" will not be
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * included here.  This also includes the "*" for the "{@literal *}/*"
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * MIME type.
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mWildTypeToFilter
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the URI schemes (such as http) that have been registered.
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mSchemeToFilter
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the actions that have been registered, but only those that did
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not specify data.
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mActionToFilter
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the actions that have been registered and specified a MIME type.
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String, ArrayList<F>> mTypedActionToFilter
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<String, ArrayList<F>>();
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
583