diff options
| author | 2013-06-13 02:10:20 +0000 | |
|---|---|---|
| committer | 2013-06-13 02:10:20 +0000 | |
| commit | 2d96d67ca2c58ed36c8362f84e25d9c6b32f4fe4 (patch) | |
| tree | cfad3209903db7a7b9bf1541c9a971692f77abb0 | |
| parent | 4d244e5f2bbbb70295e3de71a2bec5a184f89890 (diff) | |
| parent | df1c0bf7744d4abd3e2000fcfec01c119b857c75 (diff) | |
Merge "Add scheme specific part to IntentFilter."
| -rw-r--r-- | api/current.txt | 9 | ||||
| -rw-r--r-- | core/java/android/content/IntentFilter.java | 188 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 18 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ResolverActivity.java | 13 | ||||
| -rw-r--r-- | core/res/res/values/attrs_manifest.xml | 27 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 3 | ||||
| -rw-r--r-- | services/java/com/android/server/pm/Settings.java | 21 | 
7 files changed, 249 insertions, 30 deletions
diff --git a/api/current.txt b/api/current.txt index 520d0fedc8e5..d4144a88fa53 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<android.content.IntentFilter.AuthorityEntry> authoritiesIterator();      method public final java.util.Iterator<java.lang.String> 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>, java.lang.String); @@ -6355,6 +6362,7 @@ package android.content {      method public final int matchDataAuthority(android.net.Uri);      method public final java.util.Iterator<android.os.PatternMatcher> pathsIterator();      method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; +    method public final java.util.Iterator<android.os.PatternMatcher> schemeSpecificPartsIterator();      method public final java.util.Iterator<java.lang.String> schemesIterator();      method public final void setPriority(int);      method public final java.util.Iterator<java.lang.String> 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 5e65b59d01d4..4bdbf8656c21 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -50,8 +50,8 @@ import java.util.Set;   * <em>action</em>, <em>data</em>, and <em>categories</em>.  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!</em>  You should thus always use lower case letters   * for your schemes.   * + * <p><strong>Data Scheme Specific Part</strong> matches if any of the given values match + * the Intent's data scheme specific part <em>and</em> one of the data schemes in the filter + * has matched the Intent, <em>or</em> 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. + * <em>Note that scheme specific part matching is <b>case sensitive</b>.</em> + *   * <p><strong>Data Authority</strong> matches if any of the given values match - * the Intent's data authority <em>and</em> one of the data scheme's in the filter + * the Intent's data authority <em>and</em> one of the data schemes in the filter   * has matched the Intent, <em>or</em> 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.       */ @@ -210,6 +218,11 @@ public class IntentFilter implements Parcelable {       */      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.       */      public static final int MATCH_CATEGORY_TYPE = 0x0600000; @@ -236,6 +249,7 @@ public class IntentFilter implements Parcelable {      private final ArrayList<String> mActions;      private ArrayList<String> mCategories = null;      private ArrayList<String> mDataSchemes = null; +    private ArrayList<PatternMatcher> mDataSchemeSpecificParts = null;      private ArrayList<AuthorityEntry> mDataAuthorities = null;      private ArrayList<PatternMatcher> mDataPaths = null;      private ArrayList<String> mDataTypes = null; @@ -395,6 +409,9 @@ public class IntentFilter implements Parcelable {          if (o.mDataSchemes != null) {              mDataSchemes = new ArrayList<String>(o.mDataSchemes);          } +        if (o.mDataSchemeSpecificParts != null) { +            mDataSchemeSpecificParts = new ArrayList<PatternMatcher>(o.mDataSchemeSpecificParts); +        }          if (o.mDataAuthorities != null) {              mDataAuthorities = new ArrayList<AuthorityEntry>(o.mDataAuthorities);          } @@ -699,6 +716,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 <var>type</var>. +     * @param type Determines how <var>ssp</var> 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<PatternMatcher>(); +        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 <em>always</em> 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<PatternMatcher> 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       * authority to be considered.  If any authorities are @@ -900,8 +988,6 @@ public class IntentFilter implements Parcelable {      public final int matchData(String type, String scheme, Uri data) {          final ArrayList<String> types = mDataTypes;          final ArrayList<String> schemes = mDataSchemes; -        final ArrayList<AuthorityEntry> authorities = mDataAuthorities; -        final ArrayList<PatternMatcher> 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<PatternMatcher> 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<AuthorityEntry> authorities = mDataAuthorities; +                if (authorities != null) { +                    int authMatch = matchDataAuthority(data); +                    if (authMatch >= 0) { +                        final ArrayList<PatternMatcher> 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<N; i++) { +            serializer.startTag(null, SSP_STR); +            PatternMatcher pe = mDataSchemeSpecificParts.get(i); +            switch (pe.getType()) { +                case PatternMatcher.PATTERN_LITERAL: +                    serializer.attribute(null, LITERAL_STR, pe.getPath()); +                    break; +                case PatternMatcher.PATTERN_PREFIX: +                    serializer.attribute(null, PREFIX_STR, pe.getPath()); +                    break; +                case PatternMatcher.PATTERN_SIMPLE_GLOB: +                    serializer.attribute(null, SGLOB_STR, pe.getPath()); +                    break; +            } +            serializer.endTag(null, SSP_STR); +        }          N = countDataAuthorities();          for (int i=0; i<N; i++) {              serializer.startTag(null, AUTH_STR); @@ -1238,6 +1355,15 @@ public class IntentFilter implements Parcelable {                  if (name != null) {                      addDataScheme(name);                  } +            } else if (tagName.equals(SSP_STR)) { +                String ssp = parser.getAttributeValue(null, LITERAL_STR); +                if (ssp != null) { +                    addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_LITERAL); +                } else if ((ssp=parser.getAttributeValue(null, PREFIX_STR)) != null) { +                    addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_PREFIX); +                } else if ((ssp=parser.getAttributeValue(null, SGLOB_STR)) != null) { +                    addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_SIMPLE_GLOB); +                }              } else if (tagName.equals(AUTH_STR)) {                  String host = parser.getAttributeValue(null, HOST_STR);                  String port = parser.getAttributeValue(null, PORT_STR); @@ -1289,6 +1415,16 @@ public class IntentFilter implements Parcelable {                  du.println(sb.toString());              }          } +        if (mDataSchemeSpecificParts != null) { +            Iterator<PatternMatcher> 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<AuthorityEntry> 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<N; i++) { +                mDataSchemeSpecificParts.get(i).writeToParcel(dest, 0); +            } +        } else { +            dest.writeInt(0); +        }          if (mDataAuthorities != null) {              final int N = mDataAuthorities.size();              dest.writeInt(N); @@ -1428,14 +1573,21 @@ public class IntentFilter implements Parcelable {          }          int N = source.readInt();          if (N > 0) { -            mDataAuthorities = new ArrayList<AuthorityEntry>(); +            mDataSchemeSpecificParts = new ArrayList<PatternMatcher>(N); +            for (int i=0; i<N; i++) { +                mDataSchemeSpecificParts.add(new PatternMatcher(source)); +            } +        } +        N = source.readInt(); +        if (N > 0) { +            mDataAuthorities = new ArrayList<AuthorityEntry>(N);              for (int i=0; i<N; i++) {                  mDataAuthorities.add(new AuthorityEntry(source));              }          }          N = source.readInt();          if (N > 0) { -            mDataPaths = new ArrayList<PatternMatcher>(); +            mDataPaths = new ArrayList<PatternMatcher>(N);              for (int i=0; i<N; i++) {                  mDataPaths.add(new PatternMatcher(source));              } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 1b997f032129..a3bcfcbb3efc 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3288,6 +3288,24 @@ public class PackageParser {                      outInfo.addDataScheme(str);                  } +                str = sa.getNonConfigurationString( +                        com.android.internal.R.styleable.AndroidManifestData_ssp, 0); +                if (str != null) { +                    outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL); +                } + +                str = sa.getNonConfigurationString( +                        com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0); +                if (str != null) { +                    outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX); +                } + +                str = sa.getNonConfigurationString( +                        com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0); +                if (str != null) { +                    outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB); +                } +                  String host = sa.getNonConfigurationString(                          com.android.internal.R.styleable.AndroidManifestData_host, 0);                  String port = sa.getNonConfigurationString( diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index a674776031e7..aa947287891d 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -327,6 +327,17 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte                      // Look through the resolved filter to determine which part                      // of it matched the original Intent. +                    Iterator<PatternMatcher> 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<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();                      if (aIt != null) {                          while (aIt.hasNext()) { @@ -339,7 +350,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte                              }                          }                      } -                    Iterator<PatternMatcher> 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 0aaa5b7a26b3..728b1b031754 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.</em></p> -->          <attr name="scheme" format="string" /> +        <!-- Specify a URI scheme specific part that must exactly match, as per +             {@link android.content.IntentFilter#addDataSchemeSpecificPart +             IntentFilter.addDataSchemeSpecificPart()} with +             {@link android.os.PatternMatcher#PATTERN_LITERAL}. --> +        <attr name="ssp" format="string" /> +        <!-- Specify a URI scheme specific part that must be a prefix to match, as per +             {@link android.content.IntentFilter#addDataSchemeSpecificPart +             IntentFilter.addDataSchemeSpecificPart()} with +             {@link android.os.PatternMatcher#PATTERN_PREFIX}. --> +        <attr name="sspPrefix" format="string" /> +        <!-- Specify a URI scheme specific part that matches a simple pattern, as per +             {@link android.content.IntentFilter#addDataSchemeSpecificPart +             IntentFilter.addDataSchemeSpecificPart()} with +             {@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB}. +             Note that because '\' is used as an escape character when +             reading the string from XML (before it is parsed as a pattern), +             you will need to double-escape: for example a literal "*" would +             be written as "\\*" and a literal "\" would be written as +             "\\\\".  This is basically the same as what you would need to +             write if constructing the string in Java code. --> +        <attr name="sspPattern" format="string" />          <!-- Specify a URI authority host that is handled, as per               {@link android.content.IntentFilter#addDataAuthority               IntentFilter.addDataAuthority()}. @@ -1638,17 +1659,17 @@          <attr name="port" format="string" />          <!-- Specify a URI path that must exactly match, as per               {@link android.content.IntentFilter#addDataPath -             IntentFilter.addDataAuthority()} with +             IntentFilter.addDataPath()} with               {@link android.os.PatternMatcher#PATTERN_LITERAL}. -->          <attr name="path" />          <!-- Specify a URI path that must be a prefix to match, as per               {@link android.content.IntentFilter#addDataPath -             IntentFilter.addDataAuthority()} with +             IntentFilter.addDataPath()} with               {@link android.os.PatternMatcher#PATTERN_PREFIX}. -->          <attr name="pathPrefix" />          <!-- Specify a URI path that matches a simple pattern, as per               {@link android.content.IntentFilter#addDataPath -             IntentFilter.addDataAuthority()} with +             IntentFilter.addDataPath()} with               {@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB}.                Note that because '\' is used as an escape character when               reading the string from XML (before it is parsed as a pattern), diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 36a7a8631aa7..3858dcf283e7 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2063,5 +2063,8 @@    <public type="attr" name="fromScene" />    <public type="attr" name="toScene" />    <public type="attr" name="transition" /> +  <public type="attr" name="ssp" /> +  <public type="attr" name="sspPrefix" /> +  <public type="attr" name="sspPattern" />  </resources> diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index b7810ba8d75a..495e97dcc800 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -1917,15 +1917,20 @@ final class Settings {                      if (tmpPa.countDataSchemes() > 0) {                          Uri.Builder builder = new Uri.Builder();                          builder.scheme(tmpPa.getDataScheme(0)); -                        if (tmpPa.countDataAuthorities() > 0) { -                            IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(0); -                            if (auth.getHost() != null) { -                                builder.authority(auth.getHost()); +                        if (tmpPa.countDataSchemeSpecificParts() > 0) { +                            PatternMatcher path = tmpPa.getDataSchemeSpecificPart(0); +                            builder.opaquePart(path.getPath()); +                        } else { +                            if (tmpPa.countDataAuthorities() > 0) { +                                IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(0); +                                if (auth.getHost() != null) { +                                    builder.authority(auth.getHost()); +                                } +                            } +                            if (tmpPa.countDataPaths() > 0) { +                                PatternMatcher path = tmpPa.getDataPath(0); +                                builder.path(path.getPath());                              } -                        } -                        if (tmpPa.countDataPaths() > 0) { -                            PatternMatcher path = tmpPa.getDataPath(0); -                            builder.path(path.getPath());                          }                          intent.setData(builder.build());                      } else if (tmpPa.countDataTypes() > 0) {  |