Loading services/java/com/android/server/IntentResolver.java +209 −81 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.LogPrinter; import android.util.Printer; import android.util.StringBuilderPrinter; import android.content.Intent; import android.content.IntentFilter; Loading Loading @@ -65,11 +66,17 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { register_intent_filter(f, f.actionsIterator(), mTypedActionToFilter, " TypedAction: "); } mOldResolver.addFilter(f); verifyDataStructures(f); } public void removeFilter(F f) { removeFilterInternal(f); mFilters.remove(f); mOldResolver.removeFilter(f); verifyDataStructures(f); } void removeFilterInternal(F f) { Loading @@ -93,18 +100,18 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } boolean dumpMap(PrintWriter out, String titlePrefix, String title, String prefix, Map<String, ArrayList<F>> map, String packageName, 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, ArrayList<F>> e : map.entrySet()) { ArrayList<F> a = e.getValue(); final int N = a.size(); for (Map.Entry<String, F[]> e : map.entrySet()) { F[] a = e.getValue(); final int N = a.length; boolean printedHeader = false; for (int i=0; i<N; i++) { F filter = a.get(i); F filter; for (int i=0; i<N && (filter=a[i]) != null; i++) { if (packageName != null && !packageName.equals(packageForFilter(filter))) { continue; } Loading Loading @@ -201,7 +208,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) { boolean defaultOnly, ArrayList<F[]> listCut, int userId) { ArrayList<R> resultList = new ArrayList<R>(); final boolean debug = localLOGV || Loading Loading @@ -231,10 +238,10 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { TAG, "Resolving type " + resolvedType + " scheme " + scheme + " of intent " + intent); ArrayList<F> firstTypeCut = null; ArrayList<F> secondTypeCut = null; ArrayList<F> thirdTypeCut = null; ArrayList<F> schemeCut = null; 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. Loading Loading @@ -307,6 +314,14 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } sortResults(finalList); List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId); if (oldList.size() != finalList.size()) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size() + "; old implementation is " + oldList.size(), here); } if (debug) { Slog.v(TAG, "Final result list:"); for (R r : finalList) { Loading Loading @@ -341,6 +356,8 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { */ protected abstract String packageForFilter(F filter); protected abstract F[] newArray(int size); @SuppressWarnings("unchecked") protected R newResult(F filter, int match, int userId) { return (R)filter; Loading @@ -355,6 +372,29 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { out.print(prefix); out.println(filter); } private final void addFilter(HashMap<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) { Loading @@ -374,30 +414,12 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { name = name + "/*"; } ArrayList<F> array = mTypeToFilter.get(name); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mTypeToFilter.put(name, array); } array.add(filter); addFilter(mTypeToFilter, name, filter); if (slashpos > 0) { array = mBaseTypeToFilter.get(baseName); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mBaseTypeToFilter.put(baseName, array); } array.add(filter); addFilter(mBaseTypeToFilter, baseName, filter); } else { array = mWildTypeToFilter.get(baseName); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mWildTypeToFilter.put(baseName, array); } array.add(filter); addFilter(mWildTypeToFilter, baseName, filter); } } Loading @@ -423,25 +445,19 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { name = name + "/*"; } if (!remove_all_objects(mTypeToFilter.get(name), filter)) { mTypeToFilter.remove(name); } remove_all_objects(mTypeToFilter, name, filter); if (slashpos > 0) { if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) { mBaseTypeToFilter.remove(baseName); } remove_all_objects(mBaseTypeToFilter, baseName, filter); } else { if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) { mWildTypeToFilter.remove(baseName); } remove_all_objects(mWildTypeToFilter, baseName, filter); } } return num; } private final int register_intent_filter(F filter, Iterator<String> i, HashMap<String, ArrayList<F>> dest, String prefix) { HashMap<String, F[]> dest, String prefix) { if (i == null) { return 0; } Loading @@ -451,19 +467,13 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); ArrayList<F> array = dest.get(name); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); dest.put(name, array); } array.add(filter); addFilter(dest, name, filter); } return num; } private final int unregister_intent_filter(F filter, Iterator<String> i, HashMap<String, ArrayList<F>> dest, String prefix) { HashMap<String, F[]> dest, String prefix) { if (i == null) { return 0; } Loading @@ -473,26 +483,37 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); if (!remove_all_objects(dest.get(name), filter)) { dest.remove(name); } remove_all_objects(dest, name, filter); } return num; } private final boolean remove_all_objects(List<F> list, Object object) { if (list != null) { int N = list.size(); for (int idx=0; idx<N; idx++) { if (list.get(idx) == object) { list.remove(idx); idx--; N--; private final void remove_all_objects(HashMap<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); } return N > 0; } return false; } private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) { Loading @@ -505,18 +526,18 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories, boolean debug, boolean defaultOnly, String resolvedType, String scheme, List<F> src, List<R> dest, int userId) { 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 int N = src != null ? src.size() : 0; final int N = src != null ? src.length : 0; boolean hasNonDefaults = false; int i; for (i=0; i<N; i++) { F filter = src.get(i); F filter; for (i=0; i<N && (filter=src[i]) != null; i++) { int match; if (debug) Slog.v(TAG, "Matching against filter " + filter); Loading Loading @@ -585,6 +606,120 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } }; static class ValidationFailure extends RuntimeException { } private void verifyDataStructures(IntentFilter src) { compareMaps(src, "mTypeToFilter", mTypeToFilter, mOldResolver.mTypeToFilter); compareMaps(src, "mBaseTypeToFilter", mBaseTypeToFilter, mOldResolver.mBaseTypeToFilter); compareMaps(src, "mWildTypeToFilter", mWildTypeToFilter, mOldResolver.mWildTypeToFilter); compareMaps(src, "mSchemeToFilter", mSchemeToFilter, mOldResolver.mSchemeToFilter); compareMaps(src, "mActionToFilter", mActionToFilter, mOldResolver.mActionToFilter); compareMaps(src, "mTypedActionToFilter", mTypedActionToFilter, mOldResolver.mTypedActionToFilter); } private void compareMaps(IntentFilter src, String name, HashMap<String, F[]> cur, HashMap<String, ArrayList<F>> old) { if (cur.size() != old.size()) { StringBuilder missing = new StringBuilder(128); for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) { final F[] curArray = cur.get(e.getKey()); if (curArray == null) { if (missing.length() > 0) { missing.append(' '); } missing.append(e.getKey()); } } StringBuilder extra = new StringBuilder(128); for (Map.Entry<String, F[]> e : cur.entrySet()) { if (old.get(e.getKey()) == null) { if (extra.length() > 0) { extra.append(' '); } extra.append(e.getKey()); } } StringBuilder srcStr = new StringBuilder(1024); StringBuilderPrinter printer = new StringBuilderPrinter(srcStr); src.dump(printer, ""); ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " size is " + cur.size() + "; old implementation is " + old.size() + "; missing: " + missing.toString() + "; extra: " + extra.toString() + "; src: " + srcStr.toString(), here); return; } for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) { final F[] curArray = cur.get(e.getKey()); int curLen = curArray != null ? curArray.length : 0; if (curLen == 0) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " doesn't contain expected key " + e.getKey() + " (array=" + curArray + ")"); return; } while (curLen > 0 && curArray[curLen-1] == null) { curLen--; } final ArrayList<F> oldArray = e.getValue(); final int oldLen = oldArray.size(); if (curLen != oldLen) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " entry " + e.getKey() + " size is " + curLen + "; old implementation is " + oldLen, here); return; } for (int i=0; i<oldLen; i++) { F f = oldArray.get(i); boolean found = false; for (int j=0; j<curLen; j++) { if (curArray[j] == f) { found = true; break; } } if (!found) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " entry + " + e.getKey() + " doesn't contain expected filter " + f, here); } } for (int i=0; i<curLen; i++) { if (curArray[i] == null) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " entry + " + e.getKey() + " has unexpected null at " + i + "; array: " + curArray, here); break; } } } } private final IntentResolverOld<F, R> mOldResolver = new IntentResolverOld<F, R>() { @Override protected String packageForFilter(F filter) { return IntentResolver.this.packageForFilter(filter); } @Override protected boolean allowFilterResult(F filter, List<R> dest) { return IntentResolver.this.allowFilterResult(filter, dest); } @Override protected boolean isFilterStopped(F filter, int userId) { return IntentResolver.this.isFilterStopped(filter, userId); } @Override protected R newResult(F filter, int match, int userId) { return IntentResolver.this.newResult(filter, match, userId); } @Override protected void sortResults(List<R> results) { IntentResolver.this.sortResults(results); } }; /** * All filters that have been registered. */ Loading @@ -594,16 +729,14 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { * All of the MIME types that have been registered, such as "image/jpeg", * "image/*", or "{@literal *}/*". */ private final HashMap<String, ArrayList<F>> mTypeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mTypeToFilter = new HashMap<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 HashMap<String, ArrayList<F>> mBaseTypeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mBaseTypeToFilter = new HashMap<String, F[]>(); /** * The base names of all of the MIME types with a sub-type wildcard that Loading @@ -612,26 +745,21 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { * included here. This also includes the "*" for the "{@literal *}/*" * MIME type. */ private final HashMap<String, ArrayList<F>> mWildTypeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mWildTypeToFilter = new HashMap<String, F[]>(); /** * All of the URI schemes (such as http) that have been registered. */ private final HashMap<String, ArrayList<F>> mSchemeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mSchemeToFilter = new HashMap<String, F[]>(); /** * All of the actions that have been registered, but only those that did * not specify data. */ private final HashMap<String, ArrayList<F>> mActionToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mActionToFilter = new HashMap<String, F[]>(); /** * All of the actions that have been registered and specified a MIME type. */ private final HashMap<String, ArrayList<F>> mTypedActionToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mTypedActionToFilter = new HashMap<String, F[]>(); } services/java/com/android/server/IntentResolverOld.java 0 → 100644 +638 −0 File added.Preview size limit exceeded, changes collapsed. Show changes services/java/com/android/server/am/ActivityManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,11 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } @Override protected BroadcastFilter[] newArray(int size) { return new BroadcastFilter[size]; } @Override protected String packageForFilter(BroadcastFilter filter) { return filter.packageName; Loading services/java/com/android/server/pm/PackageManagerService.java +23 −6 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageStats; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; Loading Loading @@ -4737,14 +4738,17 @@ public class PackageManagerService extends IPackageManager.Stub { mFlags = flags; final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; final int N = packageActivities.size(); ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut = new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N); ArrayList<PackageParser.ActivityIntentInfo[]> listCut = new ArrayList<PackageParser.ActivityIntentInfo[]>(N); ArrayList<PackageParser.ActivityIntentInfo> intentFilters; for (int i = 0; i < N; ++i) { intentFilters = packageActivities.get(i).intents; if (intentFilters != null && intentFilters.size() > 0) { listCut.add(intentFilters); PackageParser.ActivityIntentInfo[] array = new PackageParser.ActivityIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } } return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); Loading Loading @@ -4811,6 +4815,11 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } @Override protected ActivityIntentInfo[] newArray(int size) { return new ActivityIntentInfo[size]; } @Override protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) return true; Loading Loading @@ -4925,14 +4934,17 @@ public class PackageManagerService extends IPackageManager.Stub { mFlags = flags; final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; final int N = packageServices.size(); ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut = new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N); ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<PackageParser.ServiceIntentInfo[]>(N); ArrayList<PackageParser.ServiceIntentInfo> intentFilters; for (int i = 0; i < N; ++i) { intentFilters = packageServices.get(i).intents; if (intentFilters != null && intentFilters.size() > 0) { listCut.add(intentFilters); PackageParser.ServiceIntentInfo[] array = new PackageParser.ServiceIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } } return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); Loading Loading @@ -4994,6 +5006,11 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } @Override protected PackageParser.ServiceIntentInfo[] newArray(int size) { return new PackageParser.ServiceIntentInfo[size]; } @Override protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) return true; Loading services/java/com/android/server/pm/Settings.java +4 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,10 @@ final class Settings { final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities = new IntentResolver<PreferredActivity, PreferredActivity>() { @Override protected PreferredActivity[] newArray(int size) { return new PreferredActivity[size]; } @Override protected String packageForFilter(PreferredActivity filter) { return filter.mPref.mComponent.getPackageName(); } Loading Loading
services/java/com/android/server/IntentResolver.java +209 −81 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.LogPrinter; import android.util.Printer; import android.util.StringBuilderPrinter; import android.content.Intent; import android.content.IntentFilter; Loading Loading @@ -65,11 +66,17 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { register_intent_filter(f, f.actionsIterator(), mTypedActionToFilter, " TypedAction: "); } mOldResolver.addFilter(f); verifyDataStructures(f); } public void removeFilter(F f) { removeFilterInternal(f); mFilters.remove(f); mOldResolver.removeFilter(f); verifyDataStructures(f); } void removeFilterInternal(F f) { Loading @@ -93,18 +100,18 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } boolean dumpMap(PrintWriter out, String titlePrefix, String title, String prefix, Map<String, ArrayList<F>> map, String packageName, 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, ArrayList<F>> e : map.entrySet()) { ArrayList<F> a = e.getValue(); final int N = a.size(); for (Map.Entry<String, F[]> e : map.entrySet()) { F[] a = e.getValue(); final int N = a.length; boolean printedHeader = false; for (int i=0; i<N; i++) { F filter = a.get(i); F filter; for (int i=0; i<N && (filter=a[i]) != null; i++) { if (packageName != null && !packageName.equals(packageForFilter(filter))) { continue; } Loading Loading @@ -201,7 +208,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) { boolean defaultOnly, ArrayList<F[]> listCut, int userId) { ArrayList<R> resultList = new ArrayList<R>(); final boolean debug = localLOGV || Loading Loading @@ -231,10 +238,10 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { TAG, "Resolving type " + resolvedType + " scheme " + scheme + " of intent " + intent); ArrayList<F> firstTypeCut = null; ArrayList<F> secondTypeCut = null; ArrayList<F> thirdTypeCut = null; ArrayList<F> schemeCut = null; 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. Loading Loading @@ -307,6 +314,14 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } sortResults(finalList); List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId); if (oldList.size() != finalList.size()) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size() + "; old implementation is " + oldList.size(), here); } if (debug) { Slog.v(TAG, "Final result list:"); for (R r : finalList) { Loading Loading @@ -341,6 +356,8 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { */ protected abstract String packageForFilter(F filter); protected abstract F[] newArray(int size); @SuppressWarnings("unchecked") protected R newResult(F filter, int match, int userId) { return (R)filter; Loading @@ -355,6 +372,29 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { out.print(prefix); out.println(filter); } private final void addFilter(HashMap<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) { Loading @@ -374,30 +414,12 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { name = name + "/*"; } ArrayList<F> array = mTypeToFilter.get(name); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mTypeToFilter.put(name, array); } array.add(filter); addFilter(mTypeToFilter, name, filter); if (slashpos > 0) { array = mBaseTypeToFilter.get(baseName); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mBaseTypeToFilter.put(baseName, array); } array.add(filter); addFilter(mBaseTypeToFilter, baseName, filter); } else { array = mWildTypeToFilter.get(baseName); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mWildTypeToFilter.put(baseName, array); } array.add(filter); addFilter(mWildTypeToFilter, baseName, filter); } } Loading @@ -423,25 +445,19 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { name = name + "/*"; } if (!remove_all_objects(mTypeToFilter.get(name), filter)) { mTypeToFilter.remove(name); } remove_all_objects(mTypeToFilter, name, filter); if (slashpos > 0) { if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) { mBaseTypeToFilter.remove(baseName); } remove_all_objects(mBaseTypeToFilter, baseName, filter); } else { if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) { mWildTypeToFilter.remove(baseName); } remove_all_objects(mWildTypeToFilter, baseName, filter); } } return num; } private final int register_intent_filter(F filter, Iterator<String> i, HashMap<String, ArrayList<F>> dest, String prefix) { HashMap<String, F[]> dest, String prefix) { if (i == null) { return 0; } Loading @@ -451,19 +467,13 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); ArrayList<F> array = dest.get(name); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); dest.put(name, array); } array.add(filter); addFilter(dest, name, filter); } return num; } private final int unregister_intent_filter(F filter, Iterator<String> i, HashMap<String, ArrayList<F>> dest, String prefix) { HashMap<String, F[]> dest, String prefix) { if (i == null) { return 0; } Loading @@ -473,26 +483,37 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); if (!remove_all_objects(dest.get(name), filter)) { dest.remove(name); } remove_all_objects(dest, name, filter); } return num; } private final boolean remove_all_objects(List<F> list, Object object) { if (list != null) { int N = list.size(); for (int idx=0; idx<N; idx++) { if (list.get(idx) == object) { list.remove(idx); idx--; N--; private final void remove_all_objects(HashMap<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); } return N > 0; } return false; } private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) { Loading @@ -505,18 +526,18 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories, boolean debug, boolean defaultOnly, String resolvedType, String scheme, List<F> src, List<R> dest, int userId) { 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 int N = src != null ? src.size() : 0; final int N = src != null ? src.length : 0; boolean hasNonDefaults = false; int i; for (i=0; i<N; i++) { F filter = src.get(i); F filter; for (i=0; i<N && (filter=src[i]) != null; i++) { int match; if (debug) Slog.v(TAG, "Matching against filter " + filter); Loading Loading @@ -585,6 +606,120 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { } }; static class ValidationFailure extends RuntimeException { } private void verifyDataStructures(IntentFilter src) { compareMaps(src, "mTypeToFilter", mTypeToFilter, mOldResolver.mTypeToFilter); compareMaps(src, "mBaseTypeToFilter", mBaseTypeToFilter, mOldResolver.mBaseTypeToFilter); compareMaps(src, "mWildTypeToFilter", mWildTypeToFilter, mOldResolver.mWildTypeToFilter); compareMaps(src, "mSchemeToFilter", mSchemeToFilter, mOldResolver.mSchemeToFilter); compareMaps(src, "mActionToFilter", mActionToFilter, mOldResolver.mActionToFilter); compareMaps(src, "mTypedActionToFilter", mTypedActionToFilter, mOldResolver.mTypedActionToFilter); } private void compareMaps(IntentFilter src, String name, HashMap<String, F[]> cur, HashMap<String, ArrayList<F>> old) { if (cur.size() != old.size()) { StringBuilder missing = new StringBuilder(128); for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) { final F[] curArray = cur.get(e.getKey()); if (curArray == null) { if (missing.length() > 0) { missing.append(' '); } missing.append(e.getKey()); } } StringBuilder extra = new StringBuilder(128); for (Map.Entry<String, F[]> e : cur.entrySet()) { if (old.get(e.getKey()) == null) { if (extra.length() > 0) { extra.append(' '); } extra.append(e.getKey()); } } StringBuilder srcStr = new StringBuilder(1024); StringBuilderPrinter printer = new StringBuilderPrinter(srcStr); src.dump(printer, ""); ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " size is " + cur.size() + "; old implementation is " + old.size() + "; missing: " + missing.toString() + "; extra: " + extra.toString() + "; src: " + srcStr.toString(), here); return; } for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) { final F[] curArray = cur.get(e.getKey()); int curLen = curArray != null ? curArray.length : 0; if (curLen == 0) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " doesn't contain expected key " + e.getKey() + " (array=" + curArray + ")"); return; } while (curLen > 0 && curArray[curLen-1] == null) { curLen--; } final ArrayList<F> oldArray = e.getValue(); final int oldLen = oldArray.size(); if (curLen != oldLen) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " entry " + e.getKey() + " size is " + curLen + "; old implementation is " + oldLen, here); return; } for (int i=0; i<oldLen; i++) { F f = oldArray.get(i); boolean found = false; for (int j=0; j<curLen; j++) { if (curArray[j] == f) { found = true; break; } } if (!found) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " entry + " + e.getKey() + " doesn't contain expected filter " + f, here); } } for (int i=0; i<curLen; i++) { if (curArray[i] == null) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "New map " + name + " entry + " + e.getKey() + " has unexpected null at " + i + "; array: " + curArray, here); break; } } } } private final IntentResolverOld<F, R> mOldResolver = new IntentResolverOld<F, R>() { @Override protected String packageForFilter(F filter) { return IntentResolver.this.packageForFilter(filter); } @Override protected boolean allowFilterResult(F filter, List<R> dest) { return IntentResolver.this.allowFilterResult(filter, dest); } @Override protected boolean isFilterStopped(F filter, int userId) { return IntentResolver.this.isFilterStopped(filter, userId); } @Override protected R newResult(F filter, int match, int userId) { return IntentResolver.this.newResult(filter, match, userId); } @Override protected void sortResults(List<R> results) { IntentResolver.this.sortResults(results); } }; /** * All filters that have been registered. */ Loading @@ -594,16 +729,14 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { * All of the MIME types that have been registered, such as "image/jpeg", * "image/*", or "{@literal *}/*". */ private final HashMap<String, ArrayList<F>> mTypeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mTypeToFilter = new HashMap<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 HashMap<String, ArrayList<F>> mBaseTypeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mBaseTypeToFilter = new HashMap<String, F[]>(); /** * The base names of all of the MIME types with a sub-type wildcard that Loading @@ -612,26 +745,21 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { * included here. This also includes the "*" for the "{@literal *}/*" * MIME type. */ private final HashMap<String, ArrayList<F>> mWildTypeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mWildTypeToFilter = new HashMap<String, F[]>(); /** * All of the URI schemes (such as http) that have been registered. */ private final HashMap<String, ArrayList<F>> mSchemeToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mSchemeToFilter = new HashMap<String, F[]>(); /** * All of the actions that have been registered, but only those that did * not specify data. */ private final HashMap<String, ArrayList<F>> mActionToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mActionToFilter = new HashMap<String, F[]>(); /** * All of the actions that have been registered and specified a MIME type. */ private final HashMap<String, ArrayList<F>> mTypedActionToFilter = new HashMap<String, ArrayList<F>>(); private final HashMap<String, F[]> mTypedActionToFilter = new HashMap<String, F[]>(); }
services/java/com/android/server/IntentResolverOld.java 0 → 100644 +638 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
services/java/com/android/server/am/ActivityManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,11 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } @Override protected BroadcastFilter[] newArray(int size) { return new BroadcastFilter[size]; } @Override protected String packageForFilter(BroadcastFilter filter) { return filter.packageName; Loading
services/java/com/android/server/pm/PackageManagerService.java +23 −6 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageStats; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; Loading Loading @@ -4737,14 +4738,17 @@ public class PackageManagerService extends IPackageManager.Stub { mFlags = flags; final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; final int N = packageActivities.size(); ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut = new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N); ArrayList<PackageParser.ActivityIntentInfo[]> listCut = new ArrayList<PackageParser.ActivityIntentInfo[]>(N); ArrayList<PackageParser.ActivityIntentInfo> intentFilters; for (int i = 0; i < N; ++i) { intentFilters = packageActivities.get(i).intents; if (intentFilters != null && intentFilters.size() > 0) { listCut.add(intentFilters); PackageParser.ActivityIntentInfo[] array = new PackageParser.ActivityIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } } return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); Loading Loading @@ -4811,6 +4815,11 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } @Override protected ActivityIntentInfo[] newArray(int size) { return new ActivityIntentInfo[size]; } @Override protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) return true; Loading Loading @@ -4925,14 +4934,17 @@ public class PackageManagerService extends IPackageManager.Stub { mFlags = flags; final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; final int N = packageServices.size(); ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut = new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N); ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<PackageParser.ServiceIntentInfo[]>(N); ArrayList<PackageParser.ServiceIntentInfo> intentFilters; for (int i = 0; i < N; ++i) { intentFilters = packageServices.get(i).intents; if (intentFilters != null && intentFilters.size() > 0) { listCut.add(intentFilters); PackageParser.ServiceIntentInfo[] array = new PackageParser.ServiceIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } } return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); Loading Loading @@ -4994,6 +5006,11 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } @Override protected PackageParser.ServiceIntentInfo[] newArray(int size) { return new PackageParser.ServiceIntentInfo[size]; } @Override protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) return true; Loading
services/java/com/android/server/pm/Settings.java +4 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,10 @@ final class Settings { final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities = new IntentResolver<PreferredActivity, PreferredActivity>() { @Override protected PreferredActivity[] newArray(int size) { return new PreferredActivity[size]; } @Override protected String packageForFilter(PreferredActivity filter) { return filter.mPref.mComponent.getPackageName(); } Loading