diff --git a/api/current.txt b/api/current.txt index 520d0fedc8e54..d4144a88fa534 100644 --- a/api/current.txt +++ b/api/current.txt @@ -954,6 +954,9 @@ package android { field public static final int spinnersShown = 16843595; // 0x101034b field public static final int splitMotionEvents = 16843503; // 0x10102ef field public static final int src = 16843033; // 0x1010119 + field public static final int ssp = 16843744; // 0x10103e0 + field public static final int sspPattern = 16843746; // 0x10103e2 + field public static final int sspPrefix = 16843745; // 0x10103e1 field public static final int stackFromBottom = 16843005; // 0x10100fd field public static final int starStyle = 16842882; // 0x1010082 field public static final int startColor = 16843165; // 0x101019d @@ -6322,6 +6325,7 @@ package android.content { method public final void addDataAuthority(java.lang.String, java.lang.String); method public final void addDataPath(java.lang.String, int); method public final void addDataScheme(java.lang.String); + method public final void addDataSchemeSpecificPart(java.lang.String, int); method public final void addDataType(java.lang.String) throws android.content.IntentFilter.MalformedMimeTypeException; method public final java.util.Iterator authoritiesIterator(); method public final java.util.Iterator categoriesIterator(); @@ -6329,6 +6333,7 @@ package android.content { method public final int countCategories(); method public final int countDataAuthorities(); method public final int countDataPaths(); + method public final int countDataSchemeSpecificParts(); method public final int countDataSchemes(); method public final int countDataTypes(); method public static android.content.IntentFilter create(java.lang.String, java.lang.String); @@ -6339,6 +6344,7 @@ package android.content { method public final android.content.IntentFilter.AuthorityEntry getDataAuthority(int); method public final android.os.PatternMatcher getDataPath(int); method public final java.lang.String getDataScheme(int); + method public final android.os.PatternMatcher getDataSchemeSpecificPart(int); method public final java.lang.String getDataType(int); method public final int getPriority(); method public final boolean hasAction(java.lang.String); @@ -6346,6 +6352,7 @@ package android.content { method public final boolean hasDataAuthority(android.net.Uri); method public final boolean hasDataPath(java.lang.String); method public final boolean hasDataScheme(java.lang.String); + method public final boolean hasDataSchemeSpecificPart(java.lang.String); method public final boolean hasDataType(java.lang.String); method public final int match(android.content.ContentResolver, android.content.Intent, boolean, java.lang.String); method public final int match(java.lang.String, java.lang.String, java.lang.String, android.net.Uri, java.util.Set, java.lang.String); @@ -6355,6 +6362,7 @@ package android.content { method public final int matchDataAuthority(android.net.Uri); method public final java.util.Iterator pathsIterator(); method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public final java.util.Iterator schemeSpecificPartsIterator(); method public final java.util.Iterator schemesIterator(); method public final void setPriority(int); method public final java.util.Iterator typesIterator(); @@ -6369,6 +6377,7 @@ package android.content { field public static final int MATCH_CATEGORY_PATH = 5242880; // 0x500000 field public static final int MATCH_CATEGORY_PORT = 4194304; // 0x400000 field public static final int MATCH_CATEGORY_SCHEME = 2097152; // 0x200000 + field public static final int MATCH_CATEGORY_SCHEME_SPECIFIC_PART = 5767168; // 0x580000 field public static final int MATCH_CATEGORY_TYPE = 6291456; // 0x600000 field public static final int NO_MATCH_ACTION = -3; // 0xfffffffd field public static final int NO_MATCH_CATEGORY = -4; // 0xfffffffc diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 5e65b59d01d44..4bdbf8656c21d 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -50,8 +50,8 @@ import java.util.Set; * action, data, and categories. For each of these * characteristics you can provide * multiple possible matching values (via {@link #addAction}, - * {@link #addDataType}, {@link #addDataScheme} {@link #addDataAuthority}, - * {@link #addDataPath}, and {@link #addCategory}, respectively). + * {@link #addDataType}, {@link #addDataScheme}, {@link #addDataSchemeSpecificPart}, + * {@link #addDataAuthority}, {@link #addDataPath}, and {@link #addCategory}, respectively). * For actions, the field * will not be tested if no values have been given (treating it as a wildcard); * if no data characteristics are specified, however, then the filter will @@ -106,8 +106,15 @@ import java.util.Set; * formal RFC schemes! You should thus always use lower case letters * for your schemes. * + *

Data Scheme Specific Part matches if any of the given values match + * the Intent's data scheme specific part and one of the data schemes in the filter + * has matched the Intent, or no scheme specific parts were supplied in the filter. + * The Intent scheme specific part is determined by calling + * {@link Intent#getData} and {@link android.net.Uri#getSchemeSpecificPart} on that URI. + * Note that scheme specific part matching is case sensitive. + * *

Data Authority matches if any of the given values match - * the Intent's data authority and one of the data scheme's in the filter + * the Intent's data authority and one of the data schemes in the filter * has matched the Intent, or no authories were supplied in the filter. * The Intent authority is determined by calling * {@link Intent#getData} and {@link android.net.Uri#getAuthority} on that URI. @@ -135,6 +142,7 @@ public class IntentFilter implements Parcelable { private static final String PORT_STR = "port"; private static final String HOST_STR = "host"; private static final String AUTH_STR = "auth"; + private static final String SSP_STR = "ssp"; private static final String SCHEME_STR = "scheme"; private static final String TYPE_STR = "type"; private static final String CAT_STR = "cat"; @@ -164,8 +172,8 @@ public class IntentFilter implements Parcelable { /** * The part of a match constant that describes the category of match * that occurred. May be either {@link #MATCH_CATEGORY_EMPTY}, - * {@link #MATCH_CATEGORY_SCHEME}, {@link #MATCH_CATEGORY_HOST}, - * {@link #MATCH_CATEGORY_PORT}, + * {@link #MATCH_CATEGORY_SCHEME}, {@link #MATCH_CATEGORY_SCHEME_SPECIFIC_PART}, + * {@link #MATCH_CATEGORY_HOST}, {@link #MATCH_CATEGORY_PORT}, * {@link #MATCH_CATEGORY_PATH}, or {@link #MATCH_CATEGORY_TYPE}. Higher * values indicate a better match. */ @@ -209,6 +217,11 @@ public class IntentFilter implements Parcelable { * authority, and path. */ public static final int MATCH_CATEGORY_PATH = 0x0500000; + /** + * The filter matched an intent with the same data URI scheme and + * scheme specific part. + */ + public static final int MATCH_CATEGORY_SCHEME_SPECIFIC_PART = 0x0580000; /** * The filter matched an intent with the same data MIME type. */ @@ -236,6 +249,7 @@ public class IntentFilter implements Parcelable { private final ArrayList mActions; private ArrayList mCategories = null; private ArrayList mDataSchemes = null; + private ArrayList mDataSchemeSpecificParts = null; private ArrayList mDataAuthorities = null; private ArrayList mDataPaths = null; private ArrayList mDataTypes = null; @@ -395,6 +409,9 @@ public class IntentFilter implements Parcelable { if (o.mDataSchemes != null) { mDataSchemes = new ArrayList(o.mDataSchemes); } + if (o.mDataSchemeSpecificParts != null) { + mDataSchemeSpecificParts = new ArrayList(o.mDataSchemeSpecificParts); + } if (o.mDataAuthorities != null) { mDataAuthorities = new ArrayList(o.mDataAuthorities); } @@ -698,6 +715,77 @@ public class IntentFilter implements Parcelable { } }; + /** + * Add a new Intent data "scheme specific part" to match against. The filter must + * include one or more schemes (via {@link #addDataScheme}) for the + * scheme specific part to be considered. If any scheme specific parts are + * included in the filter, then an Intent's data must match one of + * them. If no scheme specific parts are included, then only the scheme must match. + * + * @param ssp Either a raw string that must exactly match the scheme specific part + * path, or a simple pattern, depending on type. + * @param type Determines how ssp will be compared to + * determine a match: either {@link PatternMatcher#PATTERN_LITERAL}, + * {@link PatternMatcher#PATTERN_PREFIX}, or + * {@link PatternMatcher#PATTERN_SIMPLE_GLOB}. + * + * @see #matchData + * @see #addDataScheme + */ + public final void addDataSchemeSpecificPart(String ssp, int type) { + if (mDataSchemeSpecificParts == null) mDataSchemeSpecificParts = + new ArrayList(); + mDataSchemeSpecificParts.add(new PatternMatcher(ssp, type)); + } + + /** + * Return the number of data scheme specific parts in the filter. + */ + public final int countDataSchemeSpecificParts() { + return mDataSchemeSpecificParts != null ? mDataSchemeSpecificParts.size() : 0; + } + + /** + * Return a data scheme specific part in the filter. + */ + public final PatternMatcher getDataSchemeSpecificPart(int index) { + return mDataSchemeSpecificParts.get(index); + } + + /** + * Is the given data scheme specific part included in the filter? Note that if the + * filter does not include any scheme specific parts, false will always be + * returned. + * + * @param data The scheme specific part that is being looked for. + * + * @return Returns true if the data string matches a scheme specific part listed in the + * filter. + */ + public final boolean hasDataSchemeSpecificPart(String data) { + if (mDataSchemeSpecificParts == null) { + return false; + } + final int numDataSchemeSpecificParts = mDataSchemeSpecificParts.size(); + if (numDataSchemeSpecificParts <= 0) { + return false; + } + for (int i = 0; i < numDataSchemeSpecificParts; i++) { + final PatternMatcher pe = mDataSchemeSpecificParts.get(i); + if (pe.match(data)) { + return true; + } + } + return false; + } + + /** + * Return an iterator over the filter's data scheme specific parts. + */ + public final Iterator schemeSpecificPartsIterator() { + return mDataSchemeSpecificParts != null ? mDataSchemeSpecificParts.iterator() : null; + } + /** * Add a new Intent data authority to match against. The filter must * include one or more schemes (via {@link #addDataScheme}) for the @@ -900,8 +988,6 @@ public class IntentFilter implements Parcelable { public final int matchData(String type, String scheme, Uri data) { final ArrayList types = mDataTypes; final ArrayList schemes = mDataSchemes; - final ArrayList authorities = mDataAuthorities; - final ArrayList paths = mDataPaths; int match = MATCH_CATEGORY_EMPTY; @@ -917,20 +1003,34 @@ public class IntentFilter implements Parcelable { return NO_MATCH_DATA; } - if (authorities != null) { - int authMatch = matchDataAuthority(data); - if (authMatch >= 0) { - if (paths == null) { - match = authMatch; - } else if (hasDataPath(data.getPath())) { - match = MATCH_CATEGORY_PATH; + final ArrayList schemeSpecificParts = mDataSchemeSpecificParts; + if (schemeSpecificParts != null) { + match = hasDataSchemeSpecificPart(data.getSchemeSpecificPart()) + ? MATCH_CATEGORY_SCHEME_SPECIFIC_PART : NO_MATCH_DATA; + } + if (match != MATCH_CATEGORY_SCHEME_SPECIFIC_PART) { + // If there isn't any matching ssp, we need to match an authority. + final ArrayList authorities = mDataAuthorities; + if (authorities != null) { + int authMatch = matchDataAuthority(data); + if (authMatch >= 0) { + final ArrayList paths = mDataPaths; + if (paths == null) { + match = authMatch; + } else if (hasDataPath(data.getPath())) { + match = MATCH_CATEGORY_PATH; + } else { + return NO_MATCH_DATA; + } } else { return NO_MATCH_DATA; } - } else { - return NO_MATCH_DATA; } } + // If neither an ssp nor an authority matched, we're done. + if (match == NO_MATCH_DATA) { + return NO_MATCH_DATA; + } } else { // Special case: match either an Intent with no data URI, // or with a scheme: URI. This is to give a convenience for @@ -1173,6 +1273,23 @@ public class IntentFilter implements Parcelable { serializer.attribute(null, NAME_STR, mDataSchemes.get(i)); serializer.endTag(null, SCHEME_STR); } + N = countDataSchemeSpecificParts(); + for (int i=0; i it = mDataSchemeSpecificParts.iterator(); + while (it.hasNext()) { + PatternMatcher pe = it.next(); + sb.setLength(0); + sb.append(prefix); sb.append("Ssp: \""); + sb.append(pe); sb.append("\""); + du.println(sb.toString()); + } + } if (mDataAuthorities != null) { Iterator it = mDataAuthorities.iterator(); while (it.hasNext()) { @@ -1363,6 +1499,15 @@ public class IntentFilter implements Parcelable { } else { dest.writeInt(0); } + if (mDataSchemeSpecificParts != null) { + final int N = mDataSchemeSpecificParts.size(); + dest.writeInt(N); + for (int i=0; i 0) { - mDataAuthorities = new ArrayList(); + mDataSchemeSpecificParts = new ArrayList(N); + for (int i=0; i 0) { + mDataAuthorities = new ArrayList(N); for (int i=0; i 0) { - mDataPaths = new ArrayList(); + mDataPaths = new ArrayList(N); for (int i=0; i pIt = ri.filter.schemeSpecificPartsIterator(); + if (pIt != null) { + String ssp = data.getSchemeSpecificPart(); + while (ssp != null && pIt.hasNext()) { + PatternMatcher p = pIt.next(); + if (p.match(ssp)) { + filter.addDataSchemeSpecificPart(p.getPath(), p.getType()); + break; + } + } + } Iterator aIt = ri.filter.authoritiesIterator(); if (aIt != null) { while (aIt.hasNext()) { @@ -339,7 +350,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte } } } - Iterator pIt = ri.filter.pathsIterator(); + pIt = ri.filter.pathsIterator(); if (pIt != null) { String path = data.getPath(); while (path != null && pIt.hasNext()) { diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 0aaa5b7a26b36..728b1b031754d 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1624,6 +1624,27 @@ case-sensitive, unlike the formal RFC. As a result, schemes here should always use lower case letters.

--> + + + + + +