IntentResolver.java revision f2ac2761276e4972f6463d6818c9f5798bdc9a4d
14774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall/*
2518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * Copyright (C) 2006 The Android Open Source Project
3518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian *
44774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
54774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * you may not use this file except in compliance with the License.
64774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * You may obtain a copy of the License at
7518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian *
84774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
9518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian *
104774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * Unless required by applicable law or agreed to in writing, software
114774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
124774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * See the License for the specific language governing permissions and
14518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * limitations under the License.
15518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian */
16518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
171c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennispackage com.android.server;
181c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis
19518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.io.PrintWriter;
20518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.ArrayList;
21518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.Arrays;
22518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.Collections;
23518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.Comparator;
24518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.HashSet;
25518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.Iterator;
26518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.List;
27518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.Map;
28518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport java.util.Set;
29518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
30518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.net.Uri;
317db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopianimport android.util.FastImmutableArraySet;
32518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.util.ArrayMap;
33518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.util.Log;
34518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.util.PrintWriterPrinter;
35518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.util.Slog;
36518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.util.LogPrinter;
37518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.util.Printer;
381c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis
39518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.content.Intent;
40518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport android.content.IntentFilter;
41518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianimport com.android.internal.util.FastPrintWriter;
420469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
43518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian/**
44518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * {@hide}
45518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian */
46518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianpublic abstract class IntentResolver<F extends IntentFilter, R extends Object> {
47518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    final private static String TAG = "IntentResolver";
48518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    final private static boolean DEBUG = false;
49ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    final private static boolean localLOGV = DEBUG || false;
50518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
51518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    public void addFilter(F f) {
52518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (localLOGV) {
53518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            Slog.v(TAG, "Adding filter: " + f);
54518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
55e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            Slog.v(TAG, "    Building Lookup Maps:");
56e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
57518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
58518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        mFilters.add(f);
59518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int numS = register_intent_filter(f, f.schemesIterator(),
60518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mSchemeToFilter, "      Scheme: ");
61518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int numT = register_mime_types(f, "      Type: ");
62e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (numS == 0 && numT == 0) {
63e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            register_intent_filter(f, f.actionsIterator(),
64e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                    mActionToFilter, "      Action: ");
65e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
66e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (numT != 0) {
67e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            register_intent_filter(f, f.actionsIterator(),
68e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                    mTypedActionToFilter, "      TypedAction: ");
69e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
70e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian    }
71e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian
72e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian    private boolean filterEquals(IntentFilter f1, IntentFilter f2) {
73e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        int s1 = f1.countActions();
74e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        int s2 = f2.countActions();
75e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (s1 != s2) {
76e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            return false;
77e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
78e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        for (int i=0; i<s1; i++) {
79e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            if (!f2.hasAction(f1.getAction(i))) {
80e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                return false;
81e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            }
82e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
83e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s1 = f1.countCategories();
84e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s2 = f2.countCategories();
85e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (s1 != s2) {
862bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            return false;
87e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
88e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        for (int i=0; i<s1; i++) {
89e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            if (!f2.hasCategory(f1.getCategory(i))) {
90e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                return false;
91e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            }
92e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
93e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s1 = f1.countDataTypes();
94e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s2 = f2.countDataTypes();
95e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (s1 != s2) {
96e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            return false;
97e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
98e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        for (int i=0; i<s1; i++) {
99e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            if (!f2.hasExactDataType(f1.getDataType(i))) {
100e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                return false;
101e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            }
102e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
103e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s1 = f1.countDataSchemes();
104e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s2 = f2.countDataSchemes();
105518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (s1 != s2) {
106518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return false;
107518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
108518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        for (int i=0; i<s1; i++) {
109e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            if (!f2.hasDataScheme(f1.getDataScheme(i))) {
110e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                return false;
111518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
112518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
113518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        s1 = f1.countDataAuthorities();
114518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        s2 = f2.countDataAuthorities();
115e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (s1 != s2) {
116e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            return false;
117e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
118e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        for (int i=0; i<s1; i++) {
119e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            if (!f2.hasDataAuthority(f1.getDataAuthority(i))) {
120e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                return false;
121e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            }
122e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
123e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s1 = f1.countDataPaths();
124e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s2 = f2.countDataPaths();
125e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (s1 != s2) {
126e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            return false;
127e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
128e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        for (int i=0; i<s1; i++) {
1291c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang            if (!f2.hasDataPath(f1.getDataPath(i))) {
1301c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang                return false;
1311c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang            }
1321c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang        }
133e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        s1 = f1.countDataSchemeSpecificParts();
1342bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian        s2 = f2.countDataSchemeSpecificParts();
1352bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian        if (s1 != s2) {
1362bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            return false;
137e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        }
138e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        for (int i=0; i<s1; i++) {
139e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            if (!f2.hasDataSchemeSpecificPart(f1.getDataSchemeSpecificPart(i))) {
140e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                return false;
141518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
142518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
143e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        return true;
144e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian    }
145e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian
146e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian    private ArrayList<F> collectFilters(F[] array, IntentFilter matching) {
147e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        ArrayList<F> res = null;
148e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian        if (array != null) {
149e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            for (int i=0; i<array.length; i++) {
150e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                F cur = array[i];
151e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                if (cur == null) {
152e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                    break;
153e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                }
154e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                if (filterEquals(cur, matching)) {
155518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (res == null) {
156518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        res = new ArrayList<>();
157518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
158518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    res.add(cur);
159518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
160518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
161518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
162518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return res;
163518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
164518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
165518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    public ArrayList<F> findFilters(IntentFilter matching) {
166518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (matching.countDataSchemes() == 1) {
167518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // Fast case.
168518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return collectFilters(mSchemeToFilter.get(matching.getDataScheme(0)), matching);
169518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        } else if (matching.countDataTypes() != 0 && matching.countActions() == 1) {
170518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // Another fast case.
171518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return collectFilters(mTypedActionToFilter.get(matching.getAction(0)), matching);
172518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        } else if (matching.countDataTypes() == 0 && matching.countDataSchemes() == 0
173518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                && matching.countActions() == 1) {
174518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // Last fast case.
175a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy            return collectFilters(mActionToFilter.get(matching.getAction(0)), matching);
176a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        } else {
177518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            ArrayList<F> res = null;
178e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian            for (F cur : mFilters) {
179518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (filterEquals(cur, matching)) {
180518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (res == null) {
181e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian                        res = new ArrayList<>();
182518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
183518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    res.add(cur);
184518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
185518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
186518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return res;
187518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
188518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
189518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
190518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    public void removeFilter(F f) {
191518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        removeFilterInternal(f);
192518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        mFilters.remove(f);
193518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
194518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
195518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    void removeFilterInternal(F f) {
196518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (localLOGV) {
197518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            Slog.v(TAG, "Removing filter: " + f);
198518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
199518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            Slog.v(TAG, "    Cleaning Lookup Maps:");
200518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
201518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
202518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int numS = unregister_intent_filter(f, f.schemesIterator(),
203518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mSchemeToFilter, "      Scheme: ");
204518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int numT = unregister_mime_types(f, "      Type: ");
205518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (numS == 0 && numT == 0) {
206518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            unregister_intent_filter(f, f.actionsIterator(),
207518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    mActionToFilter, "      Action: ");
208518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
209518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (numT != 0) {
210518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            unregister_intent_filter(f, f.actionsIterator(),
211518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    mTypedActionToFilter, "      TypedAction: ");
212518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
213518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
214b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
215518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    boolean dumpMap(PrintWriter out, String titlePrefix, String title,
216518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            String prefix, Map<String, F[]> map, String packageName,
217518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            boolean printFilter) {
218518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        String eprefix = prefix + "  ";
219518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        String fprefix = prefix + "    ";
220518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        boolean printedSomething = false;
221518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        Printer printer = null;
222518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        for (Map.Entry<String, F[]> e : map.entrySet()) {
223518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            F[] a = e.getValue();
224518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            final int N = a.length;
225518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            boolean printedHeader = false;
226518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            F filter;
227518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            for (int i=0; i<N && (filter=a[i]) != null; i++) {
228518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (packageName != null && !isPackageForFilter(packageName, filter)) {
229518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    continue;
230b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                }
231518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (title != null) {
232518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    out.print(titlePrefix); out.println(title);
233518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    title = null;
2344774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall                }
235518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (!printedHeader) {
236518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    out.print(eprefix); out.print(e.getKey()); out.println(":");
237518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    printedHeader = true;
238518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
239518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                printedSomething = true;
240518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                dumpFilter(out, fprefix, filter);
241518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (printFilter) {
242518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (printer == null) {
243518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        printer = new PrintWriterPrinter(out);
244518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
245518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    filter.dump(printer, fprefix + "  ");
246518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
247518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
248b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        }
249518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return printedSomething;
250518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
2517773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian
2527773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    public boolean dump(PrintWriter out, String title, String prefix, String packageName,
253518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            boolean printFilter) {
254518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        String innerPrefix = prefix + "  ";
2557773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        String sepPrefix = "\n" + prefix;
2567773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        String curPrefix = title + "\n" + prefix;
2577773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        if (dumpMap(out, curPrefix, "Full MIME Types:", innerPrefix,
2587773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian                mTypeToFilter, packageName, printFilter)) {
2597773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian            curPrefix = sepPrefix;
2607773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        }
2617773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        if (dumpMap(out, curPrefix, "Base MIME Types:", innerPrefix,
262518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mBaseTypeToFilter, packageName, printFilter)) {
2637773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian            curPrefix = sepPrefix;
2647773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        }
265518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (dumpMap(out, curPrefix, "Wild MIME Types:", innerPrefix,
266518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mWildTypeToFilter, packageName, printFilter)) {
267518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            curPrefix = sepPrefix;
268518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
269518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (dumpMap(out, curPrefix, "Schemes:", innerPrefix,
270518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mSchemeToFilter, packageName, printFilter)) {
271518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            curPrefix = sepPrefix;
272518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
273b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        if (dumpMap(out, curPrefix, "Non-Data Actions:", innerPrefix,
274518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mActionToFilter, packageName, printFilter)) {
275518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            curPrefix = sepPrefix;
276518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
277518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (dumpMap(out, curPrefix, "MIME Typed Actions:", innerPrefix,
278518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                mTypedActionToFilter, packageName, printFilter)) {
279518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            curPrefix = sepPrefix;
280518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
281518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return curPrefix == sepPrefix;
282518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
283ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian
284ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    private class IteratorWrapper implements Iterator<F> {
2851cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        private final Iterator<F> mI;
2861cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        private F mCur;
2871cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
2881cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        IteratorWrapper(Iterator<F> it) {
2891cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            mI = it;
2901cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        }
2911cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
2921cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        public boolean hasNext() {
2931cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            return mI.hasNext();
294be3c3e4ecad501eecfe1f7a424a792f0f7f3f307Romain Guy        }
2951cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
2961cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        public F next() {
2971cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            return (mCur = mI.next());
2981cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        }
299be3c3e4ecad501eecfe1f7a424a792f0f7f3f307Romain Guy
3001cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        public void remove() {
3011cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            if (mCur != null) {
3021cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy                removeFilterInternal(mCur);
3031cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            }
3041cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            mI.remove();
3051cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        }
3061cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
3071cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    }
3081cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
3091cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    /**
3101cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy     * Returns an iterator allowing filters to be removed.
3111cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy     */
3121cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    public Iterator<F> filterIterator() {
3131cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        return new IteratorWrapper(mFilters.iterator());
3141cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    }
3154774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall
3161cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    /**
3171cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy     * Returns a read-only set of the filters.
3181cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy     */
3191cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    public Set<F> filterSet() {
3201cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        return Collections.unmodifiableSet(mFilters);
3211cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    }
3221cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
3231cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy    public List<R> queryIntentFromList(Intent intent, String resolvedType,
3241cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            boolean defaultOnly, ArrayList<F[]> listCut, int userId) {
3251cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        ArrayList<R> resultList = new ArrayList<R>();
3261cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
3271cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        final boolean debug = localLOGV ||
3281cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
3291cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy
3301cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
3311cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        final String scheme = intent.getScheme();
3321cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        int N = listCut.size();
3331cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        for (int i = 0; i < N; ++i) {
3341cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy            buildResolveList(intent, categories, debug, defaultOnly,
3351cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy                    resolvedType, scheme, listCut.get(i), resultList, userId);
3361cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        }
3371cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy        sortResults(resultList);
3387773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        return resultList;
3397773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    }
340518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
341518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
342518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            int userId) {
343518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        String scheme = intent.getScheme();
344518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
345518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        ArrayList<R> finalList = new ArrayList<R>();
346518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
347518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final boolean debug = localLOGV ||
348518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
349b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
350b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        if (debug) Slog.v(
351b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            TAG, "Resolving type=" + resolvedType + " scheme=" + scheme
3524774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall            + " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent);
353518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
3547773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        F[] firstTypeCut = null;
355518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        F[] secondTypeCut = null;
356518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        F[] thirdTypeCut = null;
357518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        F[] schemeCut = null;
358518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
359518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        // If the intent includes a MIME type, then we want to collect all of
360518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        // the filters that match that MIME type.
361518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (resolvedType != null) {
362518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            int slashpos = resolvedType.indexOf('/');
363518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (slashpos > 0) {
364518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                final String baseType = resolvedType.substring(0, slashpos);
365518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (!baseType.equals("*")) {
366518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (resolvedType.length() != slashpos+2
367b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                            || resolvedType.charAt(slashpos+1) != '*') {
368b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                        // Not a wild card, so we can just look for all filters that
369b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                        // completely match or wildcards whose base type matches.
370ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian                        firstTypeCut = mTypeToFilter.get(resolvedType);
371518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut));
372518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        secondTypeCut = mWildTypeToFilter.get(baseType);
37381a63350527cafce6929309533c58586878f10b5Mathias Agopian                        if (debug) Slog.v(TAG, "Second type cut: "
374e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block                                + Arrays.toString(secondTypeCut));
37581a63350527cafce6929309533c58586878f10b5Mathias Agopian                    } else {
37681a63350527cafce6929309533c58586878f10b5Mathias Agopian                        // We can match anything with our base type.
37781a63350527cafce6929309533c58586878f10b5Mathias Agopian                        firstTypeCut = mBaseTypeToFilter.get(baseType);
37881a63350527cafce6929309533c58586878f10b5Mathias Agopian                        if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut));
379518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        secondTypeCut = mWildTypeToFilter.get(baseType);
380518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        if (debug) Slog.v(TAG, "Second type cut: "
3817773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian                                + Arrays.toString(secondTypeCut));
382518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
383bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis                    // Any */* types always apply, but we only need to do this
384bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis                    // if the intent type was not already */*.
385e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block                    thirdTypeCut = mWildTypeToFilter.get("*");
386bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis                    if (debug) Slog.v(TAG, "Third type cut: " + Arrays.toString(thirdTypeCut));
38781a63350527cafce6929309533c58586878f10b5Mathias Agopian                } else if (intent.getAction() != null) {
388bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis                    // The intent specified any type ({@literal *}/*).  This
389bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis                    // can be a whole heck of a lot of things, so as a first
390518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    // cut let's use the action instead.
391518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
392518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (debug) Slog.v(TAG, "Typed Action list: " + Arrays.toString(firstTypeCut));
39359769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis                }
39459769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis            }
39559769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis        }
39659769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
39759769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis        // If the intent includes a data URI, then we want to collect all of
398518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        // the filters that match its scheme (we will further refine matches
3997773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        // on the authority and path by directly matching each resulting filter).
400518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (scheme != null) {
401b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            schemeCut = mSchemeToFilter.get(scheme);
402b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            if (debug) Slog.v(TAG, "Scheme list: " + Arrays.toString(schemeCut));
403518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
404518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
40581a63350527cafce6929309533c58586878f10b5Mathias Agopian        // If the intent does not specify any data -- either a MIME type or
40681a63350527cafce6929309533c58586878f10b5Mathias Agopian        // a URI -- then we will only be looking for matches against empty
40781a63350527cafce6929309533c58586878f10b5Mathias Agopian        // data.
40881a63350527cafce6929309533c58586878f10b5Mathias Agopian        if (resolvedType == null && scheme == null && intent.getAction() != null) {
409518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            firstTypeCut = mActionToFilter.get(intent.getAction());
410518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (debug) Slog.v(TAG, "Action list: " + Arrays.toString(firstTypeCut));
411518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
412518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
413518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
414518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (firstTypeCut != null) {
415518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            buildResolveList(intent, categories, debug, defaultOnly,
416518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    resolvedType, scheme, firstTypeCut, finalList, userId);
417518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
418518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (secondTypeCut != null) {
419b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            buildResolveList(intent, categories, debug, defaultOnly,
420b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                    resolvedType, scheme, secondTypeCut, finalList, userId);
421b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        }
422518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (thirdTypeCut != null) {
4237773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian            buildResolveList(intent, categories, debug, defaultOnly,
424518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    resolvedType, scheme, thirdTypeCut, finalList, userId);
425b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        }
426b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        if (schemeCut != null) {
427518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            buildResolveList(intent, categories, debug, defaultOnly,
428518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    resolvedType, scheme, schemeCut, finalList, userId);
429518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
430518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        sortResults(finalList);
431518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
432518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (debug) {
433518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            Slog.v(TAG, "Final result list:");
434518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            for (int i=0; i<finalList.size(); i++) {
435518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                Slog.v(TAG, "  " + finalList.get(i));
436518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
437518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
438b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        return finalList;
439b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    }
440b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
441518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
4427773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian     * Control whether the given filter is allowed to go into the result
443518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * list.  Mainly intended to prevent adding multiple filters for the
444b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall     * same target object.
445b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall     */
446518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    protected boolean allowFilterResult(F filter, List<R> dest) {
447518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return true;
448518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
449518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
450518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
4514774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall     * Returns whether the object associated with the given filter is
452518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * "stopped," that is whether it should not be included in the result
453518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * if the intent requests to excluded stopped objects.
454518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     */
455518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    protected boolean isFilterStopped(F filter, int userId) {
456b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        return false;
457518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
458518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
459b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    /**
4605b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian     * Returns whether this filter is owned by this package. This must be
4615b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian     * implemented to provide correct filtering of Intents that have
462518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * specified a package name they are to be delivered to.
463518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     */
464ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    protected abstract boolean isPackageForFilter(String packageName, F filter);
465518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
466518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    protected abstract F[] newArray(int size);
467518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
468518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    @SuppressWarnings("unchecked")
469518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    protected R newResult(F filter, int match, int userId) {
470518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return (R)filter;
471518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
472518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
473518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    @SuppressWarnings("unchecked")
474518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    protected void sortResults(List<R> results) {
475518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        Collections.sort(results, mResolvePrioritySorter);
476b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    }
477518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
478518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
479b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        out.print(prefix); out.println(filter);
4805b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    }
4815b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian
482518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private final void addFilter(ArrayMap<String, F[]> map, String name, F filter) {
483518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        F[] array = map.get(name);
4847773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        if (array == null) {
4857773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian            array = newArray(2);
486518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            map.put(name,  array);
487518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            array[0] = filter;
488e8696a40e09b24b634214684d18526187b316a2fJamie Gennis        } else {
4891c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis            final int N = array.length;
490e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            int i = N;
491e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            while (i > 0 && array[i-1] == null) {
492b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                i--;
493e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            }
494e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            if (i < N) {
495e8696a40e09b24b634214684d18526187b316a2fJamie Gennis                array[i] = filter;
496e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            } else {
497b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                F[] newa = newArray((N*3)/2);
498e8696a40e09b24b634214684d18526187b316a2fJamie Gennis                System.arraycopy(array, 0, newa, 0, N);
499e8696a40e09b24b634214684d18526187b316a2fJamie Gennis                newa[N] = filter;
500e8696a40e09b24b634214684d18526187b316a2fJamie Gennis                map.put(name, newa);
501e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            }
502e8696a40e09b24b634214684d18526187b316a2fJamie Gennis        }
503e8696a40e09b24b634214684d18526187b316a2fJamie Gennis    }
504e8696a40e09b24b634214684d18526187b316a2fJamie Gennis
505e8696a40e09b24b634214684d18526187b316a2fJamie Gennis    private final int register_mime_types(F filter, String prefix) {
506e8696a40e09b24b634214684d18526187b316a2fJamie Gennis        final Iterator<String> i = filter.typesIterator();
507e8696a40e09b24b634214684d18526187b316a2fJamie Gennis        if (i == null) {
508e8696a40e09b24b634214684d18526187b316a2fJamie Gennis            return 0;
509518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
510518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
511518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int num = 0;
512518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        while (i.hasNext()) {
513518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            String name = i.next();
514518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            num++;
515518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (localLOGV) Slog.v(TAG, prefix + name);
516518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            String baseName = name;
517518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            final int slashpos = name.indexOf('/');
518b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            if (slashpos > 0) {
519b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall                baseName = name.substring(0, slashpos).intern();
520b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            } else {
521518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                name = name + "/*";
522518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
523518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
524518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            addFilter(mTypeToFilter, name, filter);
525518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
5267773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian            if (slashpos > 0) {
527518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                addFilter(mBaseTypeToFilter, baseName, filter);
528518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            } else {
529518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                addFilter(mWildTypeToFilter, baseName, filter);
530518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
531518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
532518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
533518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return num;
534518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
535518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
5367773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    private final int unregister_mime_types(F filter, String prefix) {
5374774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall        final Iterator<String> i = filter.typesIterator();
5387773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        if (i == null) {
539518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return 0;
540518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
541518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
542518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int num = 0;
543b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        while (i.hasNext()) {
544b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            String name = i.next();
5450469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            num++;
546a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy            if (localLOGV) Slog.v(TAG, prefix + name);
5470469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            String baseName = name;
5480469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            final int slashpos = name.indexOf('/');
549518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (slashpos > 0) {
550500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian                baseName = name.substring(0, slashpos).intern();
551500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian            } else {
552500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian                name = name + "/*";
553500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian            }
554500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian
555500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian            remove_all_objects(mTypeToFilter, name, filter);
556518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
557518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (slashpos > 0) {
558518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                remove_all_objects(mBaseTypeToFilter, baseName, filter);
559518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            } else {
560518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                remove_all_objects(mWildTypeToFilter, baseName, filter);
561518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
562518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
563518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return num;
564518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
565b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
5665b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    private final int register_intent_filter(F filter, Iterator<String> i,
5675b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian            ArrayMap<String, F[]> dest, String prefix) {
568518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (i == null) {
569b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            return 0;
5705b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian        }
5715b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian
5724774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall        int num = 0;
573518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        while (i.hasNext()) {
574ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            String name = i.next();
575518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            num++;
576518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (localLOGV) Slog.v(TAG, prefix + name);
577518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            addFilter(dest, name, filter);
578518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
579518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return num;
580518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
581518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
582518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private final int unregister_intent_filter(F filter, Iterator<String> i,
583518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            ArrayMap<String, F[]> dest, String prefix) {
584518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (i == null) {
585518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return 0;
586b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        }
587518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
588518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        int num = 0;
5895b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian        while (i.hasNext()) {
5905b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian            String name = i.next();
5915b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian            num++;
592518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (localLOGV) Slog.v(TAG, prefix + name);
593518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            remove_all_objects(dest, name, filter);
594518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
595518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return num;
596518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
597518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
598b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    private final void remove_all_objects(ArrayMap<String, F[]> map, String name,
599b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            Object object) {
600b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall        F[] array = map.get(name);
601518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (array != null) {
602518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            int LAST = array.length-1;
6035b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian            while (LAST >= 0 && array[LAST] == null) {
604518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                LAST--;
605518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
606518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            for (int idx=LAST; idx>=0; idx--) {
607518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (array[idx] == object) {
608518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    final int remain = LAST - idx;
609518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (remain > 0) {
610518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        System.arraycopy(array, idx+1, array, idx, remain);
611518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
612518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    array[LAST] = null;
613518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    LAST--;
614518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
615518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
616518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (LAST < 0) {
617518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                map.remove(name);
618518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            } else if (LAST < (array.length/2)) {
619518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                F[] newa = newArray(LAST+2);
6204774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall                System.arraycopy(array, 0, newa, 0, LAST+1);
621518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                map.put(name, newa);
622518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
623518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
624518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
625518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
626518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) {
627518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final Set<String> categories = intent.getCategories();
628518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (categories == null) {
629518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return null;
630518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
631518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return new FastImmutableArraySet<String>(categories.toArray(new String[categories.size()]));
632518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
633518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
634518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
635518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            boolean debug, boolean defaultOnly,
636518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
637518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final String action = intent.getAction();
638518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final Uri data = intent.getData();
639518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final String packageName = intent.getPackage();
640518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
641518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final boolean excludingStopped = intent.isExcludingStopped();
642518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
643518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final Printer logPrinter;
644518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final PrintWriter logPrintWriter;
645518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (debug) {
646518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            logPrinter = new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM);
647518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            logPrintWriter = new FastPrintWriter(logPrinter);
648518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        } else {
649518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            logPrinter = null;
650b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            logPrintWriter = null;
651fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        }
652fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian
653518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        final int N = src != null ? src.length : 0;
654518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        boolean hasNonDefaults = false;
655fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        int i;
656518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        F filter;
657518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        for (i=0; i<N && (filter=src[i]) != null; i++) {
6580469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            int match;
659a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy            if (debug) Slog.v(TAG, "Matching against filter " + filter);
66093a826f78f6313db791e6fc880439189897651b3Siva Velusamy
6610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            if (excludingStopped && isFilterStopped(filter, userId)) {
662518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (debug) {
663518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    Slog.v(TAG, "  Filter's target is stopped; skipping");
664518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
665518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                continue;
666518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
667518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
668518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // Is delivery being limited to filters owned by a particular package?
6695fecea776a5f093c21ac1a0ad3552b847d4be23eMathias Agopian            if (packageName != null && !isPackageForFilter(packageName, filter)) {
670e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block                if (debug) {
6715fecea776a5f093c21ac1a0ad3552b847d4be23eMathias Agopian                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
672518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
673518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                continue;
674518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
675518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
676518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // Do we already have this one?
677518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            if (!allowFilterResult(filter, dest)) {
678518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (debug) {
679518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    Slog.v(TAG, "  Filter's target already added");
680518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
681518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                continue;
682b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            }
683518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
684518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            match = filter.match(action, resolvedType, scheme, data, categories, TAG);
685b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall            if (match >= 0) {
686518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
687518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        Integer.toHexString(match) + " hasDefault="
688518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        + filter.hasCategory(Intent.CATEGORY_DEFAULT));
6897773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian                if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
6907773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian                    final R oneResult = newResult(filter, match, userId);
691518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    if (oneResult != null) {
692518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        dest.add(oneResult);
693518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        if (debug) {
694518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                            dumpFilter(logPrintWriter, "    ", filter);
695518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                            logPrintWriter.flush();
696518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                            filter.dump(logPrinter, "    ");
697518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        }
698518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
699518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                } else {
700518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    hasNonDefaults = true;
701518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
702518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            } else {
703518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                if (debug) {
704518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    String reason;
705518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    switch (match) {
706518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
707518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
708518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
709518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
710518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                        default: reason = "unknown reason"; break;
711518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    }
712518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    Slog.v(TAG, "  Filter did not match: " + reason);
713518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                }
714518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
715518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
716518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
717518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (hasNonDefaults) {
7184774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall            if (dest.size() == 0) {
719518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                Slog.w(TAG, "resolveIntent failed: found match, but none with CATEGORY_DEFAULT");
720518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            } else if (dest.size() > 1) {
721518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                Slog.w(TAG, "resolveIntent: multiple matches, only some with CATEGORY_DEFAULT");
722518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            }
723518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
724518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
725518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
726518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // Sorts a List of IntentFilter objects into descending priority order.
727518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    @SuppressWarnings("rawtypes")
728518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private static final Comparator mResolvePrioritySorter = new Comparator() {
729518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        public int compare(Object o1, Object o2) {
730518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            final int q1 = ((IntentFilter) o1).getPriority();
731518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            final int q2 = ((IntentFilter) o2).getPriority();
732518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
733518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
734518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    };
735518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
736518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
737518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * All filters that have been registered.
738518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     */
739518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private final HashSet<F> mFilters = new HashSet<F>();
740518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
741518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
742518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * All of the MIME types that have been registered, such as "image/jpeg",
743518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * "image/*", or "{@literal *}/*".
744518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     */
745ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    private final ArrayMap<String, F[]> mTypeToFilter = new ArrayMap<String, F[]>();
746ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian
747ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    /**
748ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * The base names of all of all fully qualified MIME types that have been
749ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * registered, such as "image" or "*".  Wild card MIME types such as
750518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * "image/*" will not be here.
751518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     */
752518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private final ArrayMap<String, F[]> mBaseTypeToFilter = new ArrayMap<String, F[]>();
753518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
754518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
755518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * The base names of all of the MIME types with a sub-type wildcard that
756ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * have been registered.  For example, a filter with "image/*" will be
757ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * included here as "image" but one with "image/jpeg" will not be
758ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * included here.  This also includes the "*" for the "{@literal *}/*"
759ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * MIME type.
760ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     */
761518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private final ArrayMap<String, F[]> mWildTypeToFilter = new ArrayMap<String, F[]>();
762518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
763518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
764518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * All of the URI schemes (such as http) that have been registered.
765ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     */
766ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    private final ArrayMap<String, F[]> mSchemeToFilter = new ArrayMap<String, F[]>();
767ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian
768ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    /**
769518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * All of the actions that have been registered, but only those that did
770ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     * not specify data.
771ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian     */
772ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();
773ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian
774518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    /**
775518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     * All of the actions that have been registered and specified a MIME type.
776518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian     */
777518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    private final ArrayMap<String, F[]> mTypedActionToFilter = new ArrayMap<String, F[]>();
778518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
779518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian