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
302c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brownimport android.net.Uri;
312c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brownimport android.util.FastImmutableArraySet;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
33cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackbornimport android.util.PrintWriterPrinter;
348a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.LogPrinter;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
379ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackbornimport android.util.StringBuilderPrinter;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
456c418d585e0a91054b168fde3130188afd006c98Dianne Hackbornpublic abstract class IntentResolver<F extends IntentFilter, R extends Object> {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static String TAG = "IntentResolver";
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private static boolean DEBUG = false;
4843a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato    final private static boolean localLOGV = DEBUG || false;
4952c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn    final private static boolean VALIDATE = false;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addFilter(F f) {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (localLOGV) {
538a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Adding filter: " + f);
548a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "    Building Lookup Maps:");
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilters.add(f);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numS = register_intent_filter(f, f.schemesIterator(),
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSchemeToFilter, "      Scheme: ");
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numT = register_mime_types(f, "      Type: ");
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numS == 0 && numT == 0) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register_intent_filter(f, f.actionsIterator(),
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mActionToFilter, "      Action: ");
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numT != 0) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            register_intent_filter(f, f.actionsIterator(),
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTypedActionToFilter, "      TypedAction: ");
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
709ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
7152c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn        if (VALIDATE) {
7252c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            mOldResolver.addFilter(f);
7352c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            verifyDataStructures(f);
7452c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn        }
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeFilter(F f) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeFilterInternal(f);
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilters.remove(f);
809ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
8152c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn        if (VALIDATE) {
8252c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            mOldResolver.removeFilter(f);
8352c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            verifyDataStructures(f);
8452c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn        }
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void removeFilterInternal(F f) {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (localLOGV) {
898a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Removing filter: " + f);
908a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
918a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "    Cleaning Lookup Maps:");
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numS = unregister_intent_filter(f, f.schemesIterator(),
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSchemeToFilter, "      Scheme: ");
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numT = unregister_mime_types(f, "      Type: ");
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numS == 0 && numT == 0) {
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unregister_intent_filter(f, f.actionsIterator(),
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mActionToFilter, "      Action: ");
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numT != 0) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unregister_intent_filter(f, f.actionsIterator(),
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTypedActionToFilter, "      TypedAction: ");
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
107d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    boolean dumpMap(PrintWriter out, String titlePrefix, String title,
1089ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            String prefix, Map<String, F[]> map, String packageName,
109cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn            boolean printFilter) {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String eprefix = prefix + "  ";
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String fprefix = prefix + "    ";
112d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        boolean printedSomething = false;
113cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        Printer printer = null;
1149ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        for (Map.Entry<String, F[]> e : map.entrySet()) {
1159ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            F[] a = e.getValue();
1169ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            final int N = a.length;
117d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            boolean printedHeader = false;
1189ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            F filter;
1199ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            for (int i=0; i<N && (filter=a[i]) != null; i++) {
120d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                if (packageName != null && !packageName.equals(packageForFilter(filter))) {
121d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    continue;
122d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                }
123d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                if (title != null) {
124d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    out.print(titlePrefix); out.println(title);
125d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    title = null;
126d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                }
127d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                if (!printedHeader) {
128d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    out.print(eprefix); out.print(e.getKey()); out.println(":");
129d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                    printedHeader = true;
130d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                }
131d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                printedSomething = true;
132d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                dumpFilter(out, fprefix, filter);
133cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                if (printFilter) {
134cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                    if (printer == null) {
135cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        printer = new PrintWriterPrinter(out);
136cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                    }
137cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                    filter.dump(printer, fprefix + "  ");
138cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
141d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        return printedSomething;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
144cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn    public boolean dump(PrintWriter out, String title, String prefix, String packageName,
145cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn            boolean printFilter) {
1461d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        String innerPrefix = prefix + "  ";
147d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        String sepPrefix = "\n" + prefix;
148d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        String curPrefix = title + "\n" + prefix;
149d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Full MIME Types:", innerPrefix,
150cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                mTypeToFilter, packageName, printFilter)) {
151d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
152d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
153d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Base MIME Types:", innerPrefix,
154cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                mBaseTypeToFilter, packageName, printFilter)) {
155d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
156d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
157d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Wild MIME Types:", innerPrefix,
158cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                mWildTypeToFilter, packageName, printFilter)) {
159d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
160d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
161d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Schemes:", innerPrefix,
162cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                mSchemeToFilter, packageName, printFilter)) {
163d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
164d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
165d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "Non-Data Actions:", innerPrefix,
166cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                mActionToFilter, packageName, printFilter)) {
167d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
168d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
169d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        if (dumpMap(out, curPrefix, "MIME Typed Actions:", innerPrefix,
170cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                mTypedActionToFilter, packageName, printFilter)) {
171d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn            curPrefix = sepPrefix;
172d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        }
173d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn        return curPrefix == sepPrefix;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class IteratorWrapper implements Iterator<F> {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Iterator<F> mI;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private F mCur;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IteratorWrapper(Iterator<F> it) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mI = it;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean hasNext() {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mI.hasNext();
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public F next() {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (mCur = mI.next());
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void remove() {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCur != null) {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeFilterInternal(mCur);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mI.remove();
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns an iterator allowing filters to be removed.
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Iterator<F> filterIterator() {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new IteratorWrapper(mFilters.iterator());
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a read-only set of the filters.
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Set<F> filterSet() {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Collections.unmodifiableSet(mFilters);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
215eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda    public List<R> queryIntentFromList(Intent intent, String resolvedType,
2169ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            boolean defaultOnly, ArrayList<F[]> listCut, int userId) {
217eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        ArrayList<R> resultList = new ArrayList<R>();
218eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
219eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        final boolean debug = localLOGV ||
220eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
221eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
2222c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
223eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        final String scheme = intent.getScheme();
224eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        int N = listCut.size();
225eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        for (int i = 0; i < N; ++i) {
2262c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            buildResolveList(intent, categories, debug, defaultOnly,
227483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    resolvedType, scheme, listCut.get(i), resultList, userId);
228eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        }
229eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        sortResults(resultList);
230eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda        return resultList;
231eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda    }
232eae850cefe7e149f396c9e8ca1f34ec02b20a3f0Mihai Preda
233483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
234483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            int userId) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String scheme = intent.getScheme();
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<R> finalList = new ArrayList<R>();
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean debug = localLOGV ||
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2428a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (debug) Slog.v(
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TAG, "Resolving type " + resolvedType + " scheme " + scheme
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + " of intent " + intent);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F[] firstTypeCut = null;
2479ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F[] secondTypeCut = null;
2489ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F[] thirdTypeCut = null;
2499ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F[] schemeCut = null;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent includes a MIME type, then we want to collect all of
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the filters that match that MIME type.
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (resolvedType != null) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int slashpos = resolvedType.indexOf('/');
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final String baseType = resolvedType.substring(0, slashpos);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!baseType.equals("*")) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (resolvedType.length() != slashpos+2
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            || resolvedType.charAt(slashpos+1) != '*') {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Not a wild card, so we can just look for all filters that
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // completely match or wildcards whose base type matches.
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        firstTypeCut = mTypeToFilter.get(resolvedType);
2638a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        secondTypeCut = mWildTypeToFilter.get(baseType);
2658a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We can match anything with our base type.
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        firstTypeCut = mBaseTypeToFilter.get(baseType);
2698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        secondTypeCut = mWildTypeToFilter.get(baseType);
2718a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Any */* types always apply, but we only need to do this
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if the intent type was not already */*.
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    thirdTypeCut = mWildTypeToFilter.get("*");
2768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (debug) Slog.v(TAG, "Third type cut: " + thirdTypeCut);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (intent.getAction() != null) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // The intent specified any type ({@literal *}/*).  This
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // can be a whole heck of a lot of things, so as a first
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // cut let's use the action instead.
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
2828a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (debug) Slog.v(TAG, "Typed Action list: " + firstTypeCut);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent includes a data URI, then we want to collect all of
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the filters that match its scheme (we will further refine matches
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // on the authority and path by directly matching each resulting filter).
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (scheme != null) {
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            schemeCut = mSchemeToFilter.get(scheme);
2928a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (debug) Slog.v(TAG, "Scheme list: " + schemeCut);
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the intent does not specify any data -- either a MIME type or
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // a URI -- then we will only be looking for matches against empty
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // data.
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (resolvedType == null && scheme == null && intent.getAction() != null) {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            firstTypeCut = mActionToFilter.get(intent.getAction());
3008a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (debug) Slog.v(TAG, "Action list: " + firstTypeCut);
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3032c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (firstTypeCut != null) {
3052c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            buildResolveList(intent, categories, debug, defaultOnly,
306483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    resolvedType, scheme, firstTypeCut, finalList, userId);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (secondTypeCut != null) {
3092c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            buildResolveList(intent, categories, debug, defaultOnly,
310483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    resolvedType, scheme, secondTypeCut, finalList, userId);
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thirdTypeCut != null) {
3132c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            buildResolveList(intent, categories, debug, defaultOnly,
314483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    resolvedType, scheme, thirdTypeCut, finalList, userId);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (schemeCut != null) {
3172c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            buildResolveList(intent, categories, debug, defaultOnly,
318483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    resolvedType, scheme, schemeCut, finalList, userId);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sortResults(finalList);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32252c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn        if (VALIDATE) {
32352c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId);
32452c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            if (oldList.size() != finalList.size()) {
32552c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn                ValidationFailure here = new ValidationFailure();
32652c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn                here.fillInStackTrace();
32752c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn                Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size()
32852c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn                        + "; old implementation is " + oldList.size(), here);
32952c62344c585662d6b441a08c2a69a5732255a6fDianne Hackborn            }
3309ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
3319ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (debug) {
3338a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Final result list:");
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (R r : finalList) {
3358a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.v(TAG, "  " + r);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return finalList;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control whether the given filter is allowed to go into the result
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * list.  Mainly intended to prevent adding multiple filters for the
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same target object.
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean allowFilterResult(F filter, List<R> dest) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
350e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn    /**
351e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn     * Returns whether the object associated with the given filter is
352e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn     * "stopped," that is whether it should not be included in the result
353e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn     * if the intent requests to excluded stopped objects.
354e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn     */
355483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani    protected boolean isFilterStopped(F filter, int userId) {
356e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn        return false;
357e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn    }
358e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn
3596c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    /**
3606c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn     * Return the package that owns this filter.  This must be implemented to
3616c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn     * provide correct filtering of Intents that have specified a package name
3626c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn     * they are to be delivered to.
3636c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn     */
3646c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    protected abstract String packageForFilter(F filter);
3659ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
3669ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    protected abstract F[] newArray(int size);
3679ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
3686c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    @SuppressWarnings("unchecked")
369483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani    protected R newResult(F filter, int match, int userId) {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (R)filter;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3736c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    @SuppressWarnings("unchecked")
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void sortResults(List<R> results) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Collections.sort(results, mResolvePrioritySorter);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3781d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
3791d442e0d990b581357f33f5463c7c5cb49b551e8Dianne Hackborn        out.print(prefix); out.println(filter);
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final void addFilter(HashMap<String, F[]> map, String name, F filter) {
3839ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F[] array = map.get(name);
3849ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        if (array == null) {
3859ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            array = newArray(2);
3869ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            map.put(name,  array);
3879ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            array[0] = filter;
3889ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        } else {
3899ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            final int N = array.length;
3909ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            int i = N;
3919ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            while (i > 0 && array[i-1] == null) {
3929ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                i--;
3939ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
3949ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            if (i < N) {
3959ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                array[i] = filter;
3969ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            } else {
3979ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                F[] newa = newArray((N*3)/2);
3989ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                System.arraycopy(array, 0, newa, 0, N);
3999ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                newa[N] = filter;
4009ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                map.put(name, newa);
4019ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
4029ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
4039ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    }
4049ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int register_mime_types(F filter, String prefix) {
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Iterator<String> i = filter.typesIterator();
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
413502e9a47c64d819a7aa45251bcf7cb5dd77a310bKenny Root            String name = i.next();
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4158a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String baseName = name;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int slashpos = name.indexOf('/');
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                baseName = name.substring(0, slashpos).intern();
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                name = name + "/*";
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4249ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            addFilter(mTypeToFilter, name, filter);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
4279ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                addFilter(mBaseTypeToFilter, baseName, filter);
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4299ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                addFilter(mWildTypeToFilter, baseName, filter);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int unregister_mime_types(F filter, String prefix) {
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Iterator<String> i = filter.typesIterator();
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
444502e9a47c64d819a7aa45251bcf7cb5dd77a310bKenny Root            String name = i.next();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4468a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String baseName = name;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int slashpos = name.indexOf('/');
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                baseName = name.substring(0, slashpos).intern();
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                name = name + "/*";
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            remove_all_objects(mTypeToFilter, name, filter);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (slashpos > 0) {
4589ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                remove_all_objects(mBaseTypeToFilter, baseName, filter);
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4609ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                remove_all_objects(mWildTypeToFilter, baseName, filter);
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int register_intent_filter(F filter, Iterator<String> i,
4679ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            HashMap<String, F[]> dest, String prefix) {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = i.next();
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
4779ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            addFilter(dest, name, filter);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int unregister_intent_filter(F filter, Iterator<String> i,
4839ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            HashMap<String, F[]> dest, String prefix) {
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i == null) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int num = 0;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (i.hasNext()) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = i.next();
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            num++;
4928a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.v(TAG, prefix + name);
4939ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            remove_all_objects(dest, name, filter);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return num;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final void remove_all_objects(HashMap<String, F[]> map, String name,
4999ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            Object object) {
5009ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F[] array = map.get(name);
5019ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        if (array != null) {
5029ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            int LAST = array.length-1;
5039ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            while (LAST >= 0 && array[LAST] == null) {
5049ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                LAST--;
5059ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
5069ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            for (int idx=LAST; idx>=0; idx--) {
5079ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                if (array[idx] == object) {
5089ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    final int remain = LAST - idx;
5099ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    if (remain > 0) {
5109ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        System.arraycopy(array, idx+1, array, idx, remain);
5119ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    }
5129ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    array[LAST] = null;
5139ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    LAST--;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5169ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            if (LAST < 0) {
5179ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                map.remove(name);
5189ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            } else if (LAST < (array.length/2)) {
5199ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                F[] newa = newArray(LAST+2);
5209ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                System.arraycopy(array, 0, newa, 0, LAST+1);
5219ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                map.put(name, newa);
5229ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5262c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown    private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) {
5272c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        final Set<String> categories = intent.getCategories();
5282c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        if (categories == null) {
5292c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            return null;
5302c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        }
5312c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        return new FastImmutableArraySet<String>(categories.toArray(new String[categories.size()]));
5322c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown    }
5332c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown
5342c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown    private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
5352c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            boolean debug, boolean defaultOnly,
5369ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
5372c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        final String action = intent.getAction();
5382c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown        final Uri data = intent.getData();
5396c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        final String packageName = intent.getPackage();
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
541e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn        final boolean excludingStopped = intent.isExcludingStopped();
542e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn
5439ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        final int N = src != null ? src.length : 0;
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasNonDefaults = false;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i;
5469ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        F filter;
5479ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        for (i=0; i<N && (filter=src[i]) != null; i++) {
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int match;
5498a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (debug) Slog.v(TAG, "Matching against filter " + filter);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
551483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani            if (excludingStopped && isFilterStopped(filter, userId)) {
552e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn                if (debug) {
553e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn                    Slog.v(TAG, "  Filter's target is stopped; skipping");
554e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn                }
555e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn                continue;
556e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn            }
557e7f972122db87dc54e41ed1a6e417534d43bca3aDianne Hackborn
5586c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn            // Is delivery being limited to filters owned by a particular package?
5596c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn            if (packageName != null && !packageName.equals(packageForFilter(filter))) {
5606c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                if (debug) {
5616c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
5626c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                }
5636c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                continue;
5646c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn            }
5656c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Do we already have this one?
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!allowFilterResult(filter, dest)) {
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) {
5698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.v(TAG, "  Filter's target already added");
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5742c376fc46cd01b12e003a7bf83d82f527f6efaf1Jeff Brown            match = filter.match(action, resolvedType, scheme, data, categories, TAG);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (match >= 0) {
5768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Integer.toHexString(match));
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
579483f3b06ea84440a082e21b68ec2c2e54046f5a6Amith Yamasani                    final R oneResult = newResult(filter, match, userId);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (oneResult != null) {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        dest.add(oneResult);
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasNonDefaults = true;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (debug) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String reason;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (match) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        default: reason = "unknown reason"; break;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5968a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.v(TAG, "  Filter did not match: " + reason);
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dest.size() == 0 && hasNonDefaults) {
6028a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT");
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Sorts a List of IntentFilter objects into descending priority order.
6076c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    @SuppressWarnings("rawtypes")
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Comparator mResolvePrioritySorter = new Comparator() {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int compare(Object o1, Object o2) {
610502e9a47c64d819a7aa45251bcf7cb5dd77a310bKenny Root            final int q1 = ((IntentFilter) o1).getPriority();
611502e9a47c64d819a7aa45251bcf7cb5dd77a310bKenny Root            final int q2 = ((IntentFilter) o2).getPriority();
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    static class ValidationFailure extends RuntimeException {
6179ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    }
6189ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
6199ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private void verifyDataStructures(IntentFilter src) {
6209ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        compareMaps(src, "mTypeToFilter", mTypeToFilter, mOldResolver.mTypeToFilter);
6219ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        compareMaps(src, "mBaseTypeToFilter", mBaseTypeToFilter, mOldResolver.mBaseTypeToFilter);
6229ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        compareMaps(src, "mWildTypeToFilter", mWildTypeToFilter, mOldResolver.mWildTypeToFilter);
6239ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        compareMaps(src, "mSchemeToFilter", mSchemeToFilter, mOldResolver.mSchemeToFilter);
6249ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        compareMaps(src, "mActionToFilter", mActionToFilter, mOldResolver.mActionToFilter);
6259ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        compareMaps(src, "mTypedActionToFilter", mTypedActionToFilter, mOldResolver.mTypedActionToFilter);
6269ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    }
6279ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
6289ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private void compareMaps(IntentFilter src, String name, HashMap<String, F[]> cur,
6299ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            HashMap<String, ArrayList<F>> old) {
6309ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        if (cur.size() != old.size()) {
6319ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            StringBuilder missing = new StringBuilder(128);
6329ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) {
6339ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                final F[] curArray = cur.get(e.getKey());
6349ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                if (curArray == null) {
6359ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    if (missing.length() > 0) {
6369ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        missing.append(' ');
6379ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    }
6389ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    missing.append(e.getKey());
6399ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                }
6409ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
6419ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            StringBuilder extra = new StringBuilder(128);
6429ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            for (Map.Entry<String, F[]> e : cur.entrySet()) {
6439ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                if (old.get(e.getKey()) == null) {
6449ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    if (extra.length() > 0) {
6459ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        extra.append(' ');
6469ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    }
6479ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    extra.append(e.getKey());
6489ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                }
6499ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
6509ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            StringBuilder srcStr = new StringBuilder(1024);
6519ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            StringBuilderPrinter printer = new StringBuilderPrinter(srcStr);
6529ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            src.dump(printer, "");
6539ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            ValidationFailure here = new ValidationFailure();
6549ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            here.fillInStackTrace();
6559ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            Log.wtf(TAG, "New map " + name + " size is " + cur.size()
6569ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    + "; old implementation is " + old.size()
6579ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    + "; missing: " + missing.toString()
6589ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    + "; extra: " + extra.toString()
6599ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    + "; src: " + srcStr.toString(), here);
6609ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            return;
6619ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
6629ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) {
6639ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            final F[] curArray = cur.get(e.getKey());
6649ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            int curLen = curArray != null ? curArray.length : 0;
6659ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            if (curLen == 0) {
6669ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                ValidationFailure here = new ValidationFailure();
6679ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                here.fillInStackTrace();
6689ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                Log.wtf(TAG, "New map " + name + " doesn't contain expected key "
6699ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        + e.getKey() + " (array=" + curArray + ")");
6709ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                return;
6719ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
6729ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            while (curLen > 0 && curArray[curLen-1] == null) {
6739ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                curLen--;
6749ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
6759ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            final ArrayList<F> oldArray = e.getValue();
6769ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            final int oldLen = oldArray.size();
6779ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            if (curLen != oldLen) {
6789ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                ValidationFailure here = new ValidationFailure();
6799ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                here.fillInStackTrace();
6809ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                Log.wtf(TAG, "New map " + name + " entry " + e.getKey() + " size is "
6819ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        + curLen + "; old implementation is " + oldLen, here);
6829ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                return;
6839ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
6849ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            for (int i=0; i<oldLen; i++) {
6859ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                F f = oldArray.get(i);
6869ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                boolean found = false;
6879ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                for (int j=0; j<curLen; j++) {
6889ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    if (curArray[j] == f) {
6899ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        found = true;
6909ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                        break;
6919ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    }
6929ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                }
6939ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                if (!found) {
6949ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    ValidationFailure here = new ValidationFailure();
6959ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    here.fillInStackTrace();
6969ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    Log.wtf(TAG, "New map " + name + " entry + " + e.getKey()
6979ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                            + " doesn't contain expected filter " + f, here);
6989ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                }
6999ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
7009ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            for (int i=0; i<curLen; i++) {
7019ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                if (curArray[i] == null) {
7029ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    ValidationFailure here = new ValidationFailure();
7039ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    here.fillInStackTrace();
7049ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    Log.wtf(TAG, "New map " + name + " entry + " + e.getKey()
7059ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                            + " has unexpected null at " + i + "; array: " + curArray, here);
7069ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                    break;
7079ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn                }
7089ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            }
7099ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
7109ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    }
7119ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
7129ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final IntentResolverOld<F, R> mOldResolver = new IntentResolverOld<F, R>() {
7139ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        @Override protected String packageForFilter(F filter) {
7149ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            return IntentResolver.this.packageForFilter(filter);
7159ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
7169ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        @Override protected boolean allowFilterResult(F filter, List<R> dest) {
7179ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            return IntentResolver.this.allowFilterResult(filter, dest);
7189ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
7199ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        @Override protected boolean isFilterStopped(F filter, int userId) {
7209ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            return IntentResolver.this.isFilterStopped(filter, userId);
7219ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
7229ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        @Override protected R newResult(F filter, int match, int userId) {
7239ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            return IntentResolver.this.newResult(filter, match, userId);
7249ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
7259ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        @Override protected void sortResults(List<R> results) {
7269ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn            IntentResolver.this.sortResults(results);
7279ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn        }
7289ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    };
7299ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All filters that have been registered.
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashSet<F> mFilters = new HashSet<F>();
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the MIME types that have been registered, such as "image/jpeg",
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "image/*", or "{@literal *}/*".
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7399ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final HashMap<String, F[]> mTypeToFilter = new HashMap<String, F[]>();
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The base names of all of all fully qualified MIME types that have been
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * registered, such as "image" or "*".  Wild card MIME types such as
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "image/*" will not be here.
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7469ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final HashMap<String, F[]> mBaseTypeToFilter = new HashMap<String, F[]>();
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The base names of all of the MIME types with a sub-type wildcard that
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have been registered.  For example, a filter with "image/*" will be
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * included here as "image" but one with "image/jpeg" will not be
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * included here.  This also includes the "*" for the "{@literal *}/*"
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * MIME type.
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7559ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final HashMap<String, F[]> mWildTypeToFilter = new HashMap<String, F[]>();
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the URI schemes (such as http) that have been registered.
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7609ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final HashMap<String, F[]> mSchemeToFilter = new HashMap<String, F[]>();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the actions that have been registered, but only those that did
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not specify data.
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7669ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final HashMap<String, F[]> mActionToFilter = new HashMap<String, F[]>();
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All of the actions that have been registered and specified a MIME type.
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7719ec6cdde9f8f22356dcc9f811d99ebf813194721Dianne Hackborn    private final HashMap<String, F[]> mTypedActionToFilter = new HashMap<String, F[]>();
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
773