diff options
Diffstat (limited to 'services/java/com/android/server/IntentResolver.java')
-rw-r--r-- | services/java/com/android/server/IntentResolver.java | 660 |
1 files changed, 0 insertions, 660 deletions
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java deleted file mode 100644 index 64b0487..0000000 --- a/services/java/com/android/server/IntentResolver.java +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import android.net.Uri; -import android.util.FastImmutableArraySet; -import android.util.ArrayMap; -import android.util.Log; -import android.util.PrintWriterPrinter; -import android.util.Slog; -import android.util.LogPrinter; -import android.util.Printer; - -import android.content.Intent; -import android.content.IntentFilter; -import com.android.internal.util.FastPrintWriter; - -/** - * {@hide} - */ -public abstract class IntentResolver<F extends IntentFilter, R extends Object> { - final private static String TAG = "IntentResolver"; - final private static boolean DEBUG = false; - final private static boolean localLOGV = DEBUG || false; - - public void addFilter(F f) { - if (localLOGV) { - Slog.v(TAG, "Adding filter: " + f); - f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); - Slog.v(TAG, " Building Lookup Maps:"); - } - - mFilters.add(f); - int numS = register_intent_filter(f, f.schemesIterator(), - mSchemeToFilter, " Scheme: "); - int numT = register_mime_types(f, " Type: "); - if (numS == 0 && numT == 0) { - register_intent_filter(f, f.actionsIterator(), - mActionToFilter, " Action: "); - } - if (numT != 0) { - register_intent_filter(f, f.actionsIterator(), - mTypedActionToFilter, " TypedAction: "); - } - } - - public void removeFilter(F f) { - removeFilterInternal(f); - mFilters.remove(f); - } - - void removeFilterInternal(F f) { - if (localLOGV) { - Slog.v(TAG, "Removing filter: " + f); - f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); - Slog.v(TAG, " Cleaning Lookup Maps:"); - } - - int numS = unregister_intent_filter(f, f.schemesIterator(), - mSchemeToFilter, " Scheme: "); - int numT = unregister_mime_types(f, " Type: "); - if (numS == 0 && numT == 0) { - unregister_intent_filter(f, f.actionsIterator(), - mActionToFilter, " Action: "); - } - if (numT != 0) { - unregister_intent_filter(f, f.actionsIterator(), - mTypedActionToFilter, " TypedAction: "); - } - } - - boolean dumpMap(PrintWriter out, String titlePrefix, String title, - String prefix, Map<String, F[]> map, String packageName, - boolean printFilter) { - String eprefix = prefix + " "; - String fprefix = prefix + " "; - boolean printedSomething = false; - Printer printer = null; - for (Map.Entry<String, F[]> e : map.entrySet()) { - F[] a = e.getValue(); - final int N = a.length; - boolean printedHeader = false; - F filter; - for (int i=0; i<N && (filter=a[i]) != null; i++) { - if (packageName != null && !isPackageForFilter(packageName, filter)) { - continue; - } - if (title != null) { - out.print(titlePrefix); out.println(title); - title = null; - } - if (!printedHeader) { - out.print(eprefix); out.print(e.getKey()); out.println(":"); - printedHeader = true; - } - printedSomething = true; - dumpFilter(out, fprefix, filter); - if (printFilter) { - if (printer == null) { - printer = new PrintWriterPrinter(out); - } - filter.dump(printer, fprefix + " "); - } - } - } - return printedSomething; - } - - public boolean dump(PrintWriter out, String title, String prefix, String packageName, - boolean printFilter) { - String innerPrefix = prefix + " "; - String sepPrefix = "\n" + prefix; - String curPrefix = title + "\n" + prefix; - if (dumpMap(out, curPrefix, "Full MIME Types:", innerPrefix, - mTypeToFilter, packageName, printFilter)) { - curPrefix = sepPrefix; - } - if (dumpMap(out, curPrefix, "Base MIME Types:", innerPrefix, - mBaseTypeToFilter, packageName, printFilter)) { - curPrefix = sepPrefix; - } - if (dumpMap(out, curPrefix, "Wild MIME Types:", innerPrefix, - mWildTypeToFilter, packageName, printFilter)) { - curPrefix = sepPrefix; - } - if (dumpMap(out, curPrefix, "Schemes:", innerPrefix, - mSchemeToFilter, packageName, printFilter)) { - curPrefix = sepPrefix; - } - if (dumpMap(out, curPrefix, "Non-Data Actions:", innerPrefix, - mActionToFilter, packageName, printFilter)) { - curPrefix = sepPrefix; - } - if (dumpMap(out, curPrefix, "MIME Typed Actions:", innerPrefix, - mTypedActionToFilter, packageName, printFilter)) { - curPrefix = sepPrefix; - } - return curPrefix == sepPrefix; - } - - private class IteratorWrapper implements Iterator<F> { - private final Iterator<F> mI; - private F mCur; - - IteratorWrapper(Iterator<F> it) { - mI = it; - } - - public boolean hasNext() { - return mI.hasNext(); - } - - public F next() { - return (mCur = mI.next()); - } - - public void remove() { - if (mCur != null) { - removeFilterInternal(mCur); - } - mI.remove(); - } - - } - - /** - * Returns an iterator allowing filters to be removed. - */ - public Iterator<F> filterIterator() { - return new IteratorWrapper(mFilters.iterator()); - } - - /** - * Returns a read-only set of the filters. - */ - public Set<F> filterSet() { - return Collections.unmodifiableSet(mFilters); - } - - public List<R> queryIntentFromList(Intent intent, String resolvedType, - boolean defaultOnly, ArrayList<F[]> listCut, int userId) { - ArrayList<R> resultList = new ArrayList<R>(); - - final boolean debug = localLOGV || - ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); - - FastImmutableArraySet<String> categories = getFastIntentCategories(intent); - final String scheme = intent.getScheme(); - int N = listCut.size(); - for (int i = 0; i < N; ++i) { - buildResolveList(intent, categories, debug, defaultOnly, - resolvedType, scheme, listCut.get(i), resultList, userId); - } - sortResults(resultList); - return resultList; - } - - public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, - int userId) { - String scheme = intent.getScheme(); - - ArrayList<R> finalList = new ArrayList<R>(); - - final boolean debug = localLOGV || - ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); - - if (debug) Slog.v( - TAG, "Resolving type=" + resolvedType + " scheme=" + scheme - + " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent); - - F[] firstTypeCut = null; - F[] secondTypeCut = null; - F[] thirdTypeCut = null; - F[] schemeCut = null; - - // If the intent includes a MIME type, then we want to collect all of - // the filters that match that MIME type. - if (resolvedType != null) { - int slashpos = resolvedType.indexOf('/'); - if (slashpos > 0) { - final String baseType = resolvedType.substring(0, slashpos); - if (!baseType.equals("*")) { - if (resolvedType.length() != slashpos+2 - || resolvedType.charAt(slashpos+1) != '*') { - // Not a wild card, so we can just look for all filters that - // completely match or wildcards whose base type matches. - firstTypeCut = mTypeToFilter.get(resolvedType); - if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut)); - secondTypeCut = mWildTypeToFilter.get(baseType); - if (debug) Slog.v(TAG, "Second type cut: " - + Arrays.toString(secondTypeCut)); - } else { - // We can match anything with our base type. - firstTypeCut = mBaseTypeToFilter.get(baseType); - if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut)); - secondTypeCut = mWildTypeToFilter.get(baseType); - if (debug) Slog.v(TAG, "Second type cut: " - + Arrays.toString(secondTypeCut)); - } - // Any */* types always apply, but we only need to do this - // if the intent type was not already */*. - thirdTypeCut = mWildTypeToFilter.get("*"); - if (debug) Slog.v(TAG, "Third type cut: " + Arrays.toString(thirdTypeCut)); - } else if (intent.getAction() != null) { - // The intent specified any type ({@literal *}/*). This - // can be a whole heck of a lot of things, so as a first - // cut let's use the action instead. - firstTypeCut = mTypedActionToFilter.get(intent.getAction()); - if (debug) Slog.v(TAG, "Typed Action list: " + Arrays.toString(firstTypeCut)); - } - } - } - - // If the intent includes a data URI, then we want to collect all of - // the filters that match its scheme (we will further refine matches - // on the authority and path by directly matching each resulting filter). - if (scheme != null) { - schemeCut = mSchemeToFilter.get(scheme); - if (debug) Slog.v(TAG, "Scheme list: " + Arrays.toString(schemeCut)); - } - - // If the intent does not specify any data -- either a MIME type or - // a URI -- then we will only be looking for matches against empty - // data. - if (resolvedType == null && scheme == null && intent.getAction() != null) { - firstTypeCut = mActionToFilter.get(intent.getAction()); - if (debug) Slog.v(TAG, "Action list: " + Arrays.toString(firstTypeCut)); - } - - FastImmutableArraySet<String> categories = getFastIntentCategories(intent); - if (firstTypeCut != null) { - buildResolveList(intent, categories, debug, defaultOnly, - resolvedType, scheme, firstTypeCut, finalList, userId); - } - if (secondTypeCut != null) { - buildResolveList(intent, categories, debug, defaultOnly, - resolvedType, scheme, secondTypeCut, finalList, userId); - } - if (thirdTypeCut != null) { - buildResolveList(intent, categories, debug, defaultOnly, - resolvedType, scheme, thirdTypeCut, finalList, userId); - } - if (schemeCut != null) { - buildResolveList(intent, categories, debug, defaultOnly, - resolvedType, scheme, schemeCut, finalList, userId); - } - sortResults(finalList); - - if (debug) { - Slog.v(TAG, "Final result list:"); - for (int i=0; i<finalList.size(); i++) { - Slog.v(TAG, " " + finalList.get(i)); - } - } - return finalList; - } - - /** - * Control whether the given filter is allowed to go into the result - * list. Mainly intended to prevent adding multiple filters for the - * same target object. - */ - protected boolean allowFilterResult(F filter, List<R> dest) { - return true; - } - - /** - * Returns whether the object associated with the given filter is - * "stopped," that is whether it should not be included in the result - * if the intent requests to excluded stopped objects. - */ - protected boolean isFilterStopped(F filter, int userId) { - return false; - } - - /** - * Returns whether this filter is owned by this package. This must be - * implemented to provide correct filtering of Intents that have - * specified a package name they are to be delivered to. - */ - protected abstract boolean isPackageForFilter(String packageName, F filter); - - protected abstract F[] newArray(int size); - - @SuppressWarnings("unchecked") - protected R newResult(F filter, int match, int userId) { - return (R)filter; - } - - @SuppressWarnings("unchecked") - protected void sortResults(List<R> results) { - Collections.sort(results, mResolvePrioritySorter); - } - - protected void dumpFilter(PrintWriter out, String prefix, F filter) { - out.print(prefix); out.println(filter); - } - - private final void addFilter(ArrayMap<String, F[]> map, String name, F filter) { - F[] array = map.get(name); - if (array == null) { - array = newArray(2); - map.put(name, array); - array[0] = filter; - } else { - final int N = array.length; - int i = N; - while (i > 0 && array[i-1] == null) { - i--; - } - if (i < N) { - array[i] = filter; - } else { - F[] newa = newArray((N*3)/2); - System.arraycopy(array, 0, newa, 0, N); - newa[N] = filter; - map.put(name, newa); - } - } - } - - private final int register_mime_types(F filter, String prefix) { - final Iterator<String> i = filter.typesIterator(); - if (i == null) { - return 0; - } - - int num = 0; - while (i.hasNext()) { - String name = i.next(); - num++; - if (localLOGV) Slog.v(TAG, prefix + name); - String baseName = name; - final int slashpos = name.indexOf('/'); - if (slashpos > 0) { - baseName = name.substring(0, slashpos).intern(); - } else { - name = name + "/*"; - } - - addFilter(mTypeToFilter, name, filter); - - if (slashpos > 0) { - addFilter(mBaseTypeToFilter, baseName, filter); - } else { - addFilter(mWildTypeToFilter, baseName, filter); - } - } - - return num; - } - - private final int unregister_mime_types(F filter, String prefix) { - final Iterator<String> i = filter.typesIterator(); - if (i == null) { - return 0; - } - - int num = 0; - while (i.hasNext()) { - String name = i.next(); - num++; - if (localLOGV) Slog.v(TAG, prefix + name); - String baseName = name; - final int slashpos = name.indexOf('/'); - if (slashpos > 0) { - baseName = name.substring(0, slashpos).intern(); - } else { - name = name + "/*"; - } - - remove_all_objects(mTypeToFilter, name, filter); - - if (slashpos > 0) { - remove_all_objects(mBaseTypeToFilter, baseName, filter); - } else { - remove_all_objects(mWildTypeToFilter, baseName, filter); - } - } - return num; - } - - private final int register_intent_filter(F filter, Iterator<String> i, - ArrayMap<String, F[]> dest, String prefix) { - if (i == null) { - return 0; - } - - int num = 0; - while (i.hasNext()) { - String name = i.next(); - num++; - if (localLOGV) Slog.v(TAG, prefix + name); - addFilter(dest, name, filter); - } - return num; - } - - private final int unregister_intent_filter(F filter, Iterator<String> i, - ArrayMap<String, F[]> dest, String prefix) { - if (i == null) { - return 0; - } - - int num = 0; - while (i.hasNext()) { - String name = i.next(); - num++; - if (localLOGV) Slog.v(TAG, prefix + name); - remove_all_objects(dest, name, filter); - } - return num; - } - - private final void remove_all_objects(ArrayMap<String, F[]> map, String name, - Object object) { - F[] array = map.get(name); - if (array != null) { - int LAST = array.length-1; - while (LAST >= 0 && array[LAST] == null) { - LAST--; - } - for (int idx=LAST; idx>=0; idx--) { - if (array[idx] == object) { - final int remain = LAST - idx; - if (remain > 0) { - System.arraycopy(array, idx+1, array, idx, remain); - } - array[LAST] = null; - LAST--; - } - } - if (LAST < 0) { - map.remove(name); - } else if (LAST < (array.length/2)) { - F[] newa = newArray(LAST+2); - System.arraycopy(array, 0, newa, 0, LAST+1); - map.put(name, newa); - } - } - } - - private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) { - final Set<String> categories = intent.getCategories(); - if (categories == null) { - return null; - } - return new FastImmutableArraySet<String>(categories.toArray(new String[categories.size()])); - } - - private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories, - boolean debug, boolean defaultOnly, - String resolvedType, String scheme, F[] src, List<R> dest, int userId) { - final String action = intent.getAction(); - final Uri data = intent.getData(); - final String packageName = intent.getPackage(); - - final boolean excludingStopped = intent.isExcludingStopped(); - - final Printer logPrinter; - final PrintWriter logPrintWriter; - if (debug) { - logPrinter = new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM); - logPrintWriter = new FastPrintWriter(logPrinter); - } else { - logPrinter = null; - logPrintWriter = null; - } - - final int N = src != null ? src.length : 0; - boolean hasNonDefaults = false; - int i; - F filter; - for (i=0; i<N && (filter=src[i]) != null; i++) { - int match; - if (debug) Slog.v(TAG, "Matching against filter " + filter); - - if (excludingStopped && isFilterStopped(filter, userId)) { - if (debug) { - Slog.v(TAG, " Filter's target is stopped; skipping"); - } - continue; - } - - // Is delivery being limited to filters owned by a particular package? - if (packageName != null && !isPackageForFilter(packageName, filter)) { - if (debug) { - Slog.v(TAG, " Filter is not from package " + packageName + "; skipping"); - } - continue; - } - - // Do we already have this one? - if (!allowFilterResult(filter, dest)) { - if (debug) { - Slog.v(TAG, " Filter's target already added"); - } - continue; - } - - match = filter.match(action, resolvedType, scheme, data, categories, TAG); - if (match >= 0) { - if (debug) Slog.v(TAG, " Filter matched! match=0x" + - Integer.toHexString(match) + " hasDefault=" - + filter.hasCategory(Intent.CATEGORY_DEFAULT)); - if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) { - final R oneResult = newResult(filter, match, userId); - if (oneResult != null) { - dest.add(oneResult); - if (debug) { - dumpFilter(logPrintWriter, " ", filter); - logPrintWriter.flush(); - filter.dump(logPrinter, " "); - } - } - } else { - hasNonDefaults = true; - } - } else { - if (debug) { - String reason; - switch (match) { - case IntentFilter.NO_MATCH_ACTION: reason = "action"; break; - case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break; - case IntentFilter.NO_MATCH_DATA: reason = "data"; break; - case IntentFilter.NO_MATCH_TYPE: reason = "type"; break; - default: reason = "unknown reason"; break; - } - Slog.v(TAG, " Filter did not match: " + reason); - } - } - } - - if (hasNonDefaults) { - if (dest.size() == 0) { - Slog.w(TAG, "resolveIntent failed: found match, but none with CATEGORY_DEFAULT"); - } else if (dest.size() > 1) { - Slog.w(TAG, "resolveIntent: multiple matches, only some with CATEGORY_DEFAULT"); - } - } - } - - // Sorts a List of IntentFilter objects into descending priority order. - @SuppressWarnings("rawtypes") - private static final Comparator mResolvePrioritySorter = new Comparator() { - public int compare(Object o1, Object o2) { - final int q1 = ((IntentFilter) o1).getPriority(); - final int q2 = ((IntentFilter) o2).getPriority(); - return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); - } - }; - - /** - * All filters that have been registered. - */ - private final HashSet<F> mFilters = new HashSet<F>(); - - /** - * All of the MIME types that have been registered, such as "image/jpeg", - * "image/*", or "{@literal *}/*". - */ - private final ArrayMap<String, F[]> mTypeToFilter = new ArrayMap<String, F[]>(); - - /** - * The base names of all of all fully qualified MIME types that have been - * registered, such as "image" or "*". Wild card MIME types such as - * "image/*" will not be here. - */ - private final ArrayMap<String, F[]> mBaseTypeToFilter = new ArrayMap<String, F[]>(); - - /** - * The base names of all of the MIME types with a sub-type wildcard that - * have been registered. For example, a filter with "image/*" will be - * included here as "image" but one with "image/jpeg" will not be - * included here. This also includes the "*" for the "{@literal *}/*" - * MIME type. - */ - private final ArrayMap<String, F[]> mWildTypeToFilter = new ArrayMap<String, F[]>(); - - /** - * All of the URI schemes (such as http) that have been registered. - */ - private final ArrayMap<String, F[]> mSchemeToFilter = new ArrayMap<String, F[]>(); - - /** - * All of the actions that have been registered, but only those that did - * not specify data. - */ - private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>(); - - /** - * All of the actions that have been registered and specified a MIME type. - */ - private final ArrayMap<String, F[]> mTypedActionToFilter = new ArrayMap<String, F[]>(); -} |