blob: 36d8a3720b5e45e2124e54268e2d0fec87c004b3 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content;
18
Todd Kennedyc05f5d12017-04-25 11:11:40 -070019import android.annotation.IntDef;
Todd Kennedy9c9fdf22017-03-06 10:58:27 -080020import android.annotation.SystemApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010021import android.annotation.UnsupportedAppUsage;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070022import android.net.Uri;
Mathew Inwood8c854f82018-09-14 12:35:36 +010023import android.os.Build;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070024import android.os.Parcel;
25import android.os.Parcelable;
26import android.os.PatternMatcher;
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -080027import android.text.TextUtils;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070028import android.util.AndroidException;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070029import android.util.Log;
30import android.util.Printer;
Yi Jin129fc6c2017-09-28 15:48:38 -070031import android.util.proto.ProtoOutputStream;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080032
33import com.android.internal.util.XmlUtils;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070034
Gilles Debunne37051cd2011-05-25 16:27:13 -070035import org.xmlpull.v1.XmlPullParser;
36import org.xmlpull.v1.XmlPullParserException;
37import org.xmlpull.v1.XmlSerializer;
38
39import java.io.IOException;
Todd Kennedyc05f5d12017-04-25 11:11:40 -070040import java.lang.annotation.Retention;
41import java.lang.annotation.RetentionPolicy;
Gilles Debunne37051cd2011-05-25 16:27:13 -070042import java.util.ArrayList;
43import java.util.Iterator;
44import java.util.Set;
45
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070046/**
47 * Structured description of Intent values to be matched. An IntentFilter can
48 * match against actions, categories, and data (either via its type, scheme,
49 * and/or path) in an Intent. It also includes a "priority" value which is
50 * used to order multiple matching filters.
51 *
52 * <p>IntentFilter objects are often created in XML as part of a package's
53 * {@link android.R.styleable#AndroidManifest AndroidManifest.xml} file,
54 * using {@link android.R.styleable#AndroidManifestIntentFilter intent-filter}
55 * tags.
56 *
57 * <p>There are three Intent characteristics you can filter on: the
58 * <em>action</em>, <em>data</em>, and <em>categories</em>. For each of these
59 * characteristics you can provide
60 * multiple possible matching values (via {@link #addAction},
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -070061 * {@link #addDataType}, {@link #addDataScheme}, {@link #addDataSchemeSpecificPart},
62 * {@link #addDataAuthority}, {@link #addDataPath}, and {@link #addCategory}, respectively).
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070063 * For actions, the field
64 * will not be tested if no values have been given (treating it as a wildcard);
65 * if no data characteristics are specified, however, then the filter will
66 * only match intents that contain no data.
67 *
68 * <p>The data characteristic is
69 * itself divided into three attributes: type, scheme, authority, and path.
70 * Any that are
71 * specified must match the contents of the Intent. If you specify a scheme
72 * but no type, only Intent that does not have a type (such as mailto:) will
73 * match; a content: URI will never match because they always have a MIME type
74 * that is supplied by their content provider. Specifying a type with no scheme
75 * has somewhat special meaning: it will match either an Intent with no URI
76 * field, or an Intent with a content: or file: URI. If you specify neither,
77 * then only an Intent with no data or type will match. To specify an authority,
78 * you must also specify one or more schemes that it is associated with.
79 * To specify a path, you also must specify both one or more authorities and
80 * one or more schemes it is associated with.
81 *
Joe Fernandezb54e7a32011-10-03 15:09:50 -070082 * <div class="special reference">
83 * <h3>Developer Guides</h3>
84 * <p>For information about how to create and resolve intents, read the
85 * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
86 * developer guide.</p>
87 * </div>
88 *
89 * <h3>Filter Rules</h3>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070090 * <p>A match is based on the following rules. Note that
91 * for an IntentFilter to match an Intent, three conditions must hold:
92 * the <strong>action</strong> and <strong>category</strong> must match, and
93 * the data (both the <strong>data type</strong> and
Dianne Hackborn0ea920d2013-10-11 09:40:18 -070094 * <strong>data scheme+authority+path</strong> if specified) must match
95 * (see {@link #match(ContentResolver, Intent, boolean, String)} for more details
96 * on how the data fields match).
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070097 *
98 * <p><strong>Action</strong> matches if any of the given values match the
Dianne Hackborna53ee352013-02-20 12:47:02 -080099 * Intent action; if the filter specifies no actions, then it will only match
100 * Intents that do not contain an action.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700101 *
102 * <p><strong>Data Type</strong> matches if any of the given values match the
103 * Intent type. The Intent
104 * type is determined by calling {@link Intent#resolveType}. A wildcard can be
105 * used for the MIME sub-type, in both the Intent and IntentFilter, so that the
106 * type "audio/*" will match "audio/mpeg", "audio/aiff", "audio/*", etc.
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700107 * <em>Note that MIME type matching here is <b>case sensitive</b>, unlike
108 * formal RFC MIME types!</em> You should thus always use lower case letters
109 * for your MIME types.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700110 *
111 * <p><strong>Data Scheme</strong> matches if any of the given values match the
112 * Intent data's scheme.
113 * The Intent scheme is determined by calling {@link Intent#getData}
114 * and {@link android.net.Uri#getScheme} on that URI.
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700115 * <em>Note that scheme matching here is <b>case sensitive</b>, unlike
116 * formal RFC schemes!</em> You should thus always use lower case letters
117 * for your schemes.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700118 *
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700119 * <p><strong>Data Scheme Specific Part</strong> matches if any of the given values match
120 * the Intent's data scheme specific part <em>and</em> one of the data schemes in the filter
121 * has matched the Intent, <em>or</em> no scheme specific parts were supplied in the filter.
122 * The Intent scheme specific part is determined by calling
123 * {@link Intent#getData} and {@link android.net.Uri#getSchemeSpecificPart} on that URI.
124 * <em>Note that scheme specific part matching is <b>case sensitive</b>.</em>
125 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700126 * <p><strong>Data Authority</strong> matches if any of the given values match
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700127 * the Intent's data authority <em>and</em> one of the data schemes in the filter
Josh Gao0febb232018-08-28 11:19:16 -0700128 * has matched the Intent, <em>or</em> no authorities were supplied in the filter.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700129 * The Intent authority is determined by calling
130 * {@link Intent#getData} and {@link android.net.Uri#getAuthority} on that URI.
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700131 * <em>Note that authority matching here is <b>case sensitive</b>, unlike
132 * formal RFC host names!</em> You should thus always use lower case letters
133 * for your authority.
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700134 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700135 * <p><strong>Data Path</strong> matches if any of the given values match the
136 * Intent's data path <em>and</em> both a scheme and authority in the filter
137 * has matched against the Intent, <em>or</em> no paths were supplied in the
138 * filter. The Intent authority is determined by calling
139 * {@link Intent#getData} and {@link android.net.Uri#getPath} on that URI.
140 *
141 * <p><strong>Categories</strong> match if <em>all</em> of the categories in
142 * the Intent match categories given in the filter. Extra categories in the
143 * filter that are not in the Intent will not cause the match to fail. Note
144 * that unlike the action, an IntentFilter with no categories
145 * will only match an Intent that does not have any categories.
146 */
147public class IntentFilter implements Parcelable {
Todd Kennedy9c9fdf22017-03-06 10:58:27 -0800148 private static final String AGLOB_STR = "aglob";
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700149 private static final String SGLOB_STR = "sglob";
150 private static final String PREFIX_STR = "prefix";
151 private static final String LITERAL_STR = "literal";
152 private static final String PATH_STR = "path";
153 private static final String PORT_STR = "port";
154 private static final String HOST_STR = "host";
155 private static final String AUTH_STR = "auth";
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700156 private static final String SSP_STR = "ssp";
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700157 private static final String SCHEME_STR = "scheme";
158 private static final String TYPE_STR = "type";
159 private static final String CAT_STR = "cat";
160 private static final String NAME_STR = "name";
161 private static final String ACTION_STR = "action";
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800162 private static final String AUTO_VERIFY_STR = "autoVerify";
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700163
164 /**
165 * The filter {@link #setPriority} value at which system high-priority
166 * receivers are placed; that is, receivers that should execute before
167 * application code. Applications should never use filters with this or
168 * higher priorities.
169 *
170 * @see #setPriority
171 */
172 public static final int SYSTEM_HIGH_PRIORITY = 1000;
173
174 /**
175 * The filter {@link #setPriority} value at which system low-priority
176 * receivers are placed; that is, receivers that should execute after
177 * application code. Applications should never use filters with this or
178 * lower priorities.
179 *
180 * @see #setPriority
181 */
182 public static final int SYSTEM_LOW_PRIORITY = -1000;
183
184 /**
185 * The part of a match constant that describes the category of match
186 * that occurred. May be either {@link #MATCH_CATEGORY_EMPTY},
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700187 * {@link #MATCH_CATEGORY_SCHEME}, {@link #MATCH_CATEGORY_SCHEME_SPECIFIC_PART},
188 * {@link #MATCH_CATEGORY_HOST}, {@link #MATCH_CATEGORY_PORT},
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700189 * {@link #MATCH_CATEGORY_PATH}, or {@link #MATCH_CATEGORY_TYPE}. Higher
190 * values indicate a better match.
191 */
192 public static final int MATCH_CATEGORY_MASK = 0xfff0000;
193
194 /**
195 * The part of a match constant that applies a quality adjustment to the
196 * basic category of match. The value {@link #MATCH_ADJUSTMENT_NORMAL}
197 * is no adjustment; higher numbers than that improve the quality, while
198 * lower numbers reduce it.
199 */
200 public static final int MATCH_ADJUSTMENT_MASK = 0x000ffff;
201
202 /**
203 * Quality adjustment applied to the category of match that signifies
204 * the default, base value; higher numbers improve the quality while
205 * lower numbers reduce it.
206 */
207 public static final int MATCH_ADJUSTMENT_NORMAL = 0x8000;
208
209 /**
210 * The filter matched an intent that had no data specified.
211 */
212 public static final int MATCH_CATEGORY_EMPTY = 0x0100000;
213 /**
214 * The filter matched an intent with the same data URI scheme.
215 */
216 public static final int MATCH_CATEGORY_SCHEME = 0x0200000;
217 /**
218 * The filter matched an intent with the same data URI scheme and
219 * authority host.
220 */
221 public static final int MATCH_CATEGORY_HOST = 0x0300000;
222 /**
223 * The filter matched an intent with the same data URI scheme and
224 * authority host and port.
225 */
226 public static final int MATCH_CATEGORY_PORT = 0x0400000;
227 /**
228 * The filter matched an intent with the same data URI scheme,
229 * authority, and path.
230 */
231 public static final int MATCH_CATEGORY_PATH = 0x0500000;
232 /**
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700233 * The filter matched an intent with the same data URI scheme and
234 * scheme specific part.
235 */
236 public static final int MATCH_CATEGORY_SCHEME_SPECIFIC_PART = 0x0580000;
237 /**
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700238 * The filter matched an intent with the same data MIME type.
239 */
240 public static final int MATCH_CATEGORY_TYPE = 0x0600000;
241
242 /**
243 * The filter didn't match due to different MIME types.
244 */
245 public static final int NO_MATCH_TYPE = -1;
246 /**
247 * The filter didn't match due to different data URIs.
248 */
249 public static final int NO_MATCH_DATA = -2;
250 /**
251 * The filter didn't match due to different actions.
252 */
253 public static final int NO_MATCH_ACTION = -3;
254 /**
255 * The filter didn't match because it required one or more categories
256 * that were not in the Intent.
257 */
258 public static final int NO_MATCH_CATEGORY = -4;
259
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800260 /**
261 * HTTP scheme.
262 *
263 * @see #addDataScheme(String)
Dianne Hackbornece0f4f2015-06-11 13:29:01 -0700264 * @hide
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800265 */
266 public static final String SCHEME_HTTP = "http";
267 /**
268 * HTTPS scheme.
269 *
270 * @see #addDataScheme(String)
Dianne Hackbornece0f4f2015-06-11 13:29:01 -0700271 * @hide
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800272 */
273 public static final String SCHEME_HTTPS = "https";
274
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700275 private int mPriority;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100276 @UnsupportedAppUsage
Todd Kennedyc2e96d42016-09-08 15:34:03 -0700277 private int mOrder;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100278 @UnsupportedAppUsage
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700279 private final ArrayList<String> mActions;
280 private ArrayList<String> mCategories = null;
281 private ArrayList<String> mDataSchemes = null;
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700282 private ArrayList<PatternMatcher> mDataSchemeSpecificParts = null;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700283 private ArrayList<AuthorityEntry> mDataAuthorities = null;
284 private ArrayList<PatternMatcher> mDataPaths = null;
285 private ArrayList<String> mDataTypes = null;
286 private boolean mHasPartialTypes = false;
287
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800288 private static final int STATE_VERIFY_AUTO = 0x00000001;
289 private static final int STATE_NEED_VERIFY = 0x00000010;
290 private static final int STATE_NEED_VERIFY_CHECKED = 0x00000100;
291 private static final int STATE_VERIFIED = 0x00001000;
292
293 private int mVerifyState;
Todd Kennedyc05f5d12017-04-25 11:11:40 -0700294 /** @hide */
295 public static final int VISIBILITY_NONE = 0;
296 /** @hide */
297 public static final int VISIBILITY_EXPLICIT = 1;
298 /** @hide */
299 public static final int VISIBILITY_IMPLICIT = 2;
300 /** @hide */
301 @IntDef(prefix = { "VISIBILITY_" }, value = {
302 VISIBILITY_NONE,
303 VISIBILITY_EXPLICIT,
304 VISIBILITY_IMPLICIT,
305 })
306 @Retention(RetentionPolicy.SOURCE)
307 public @interface InstantAppVisibility {}
Todd Kennedy66b5c042017-04-07 11:38:39 -0700308 /** Whether or not the intent filter is visible to instant apps. */
Todd Kennedyc05f5d12017-04-25 11:11:40 -0700309 private @InstantAppVisibility int mInstantAppVisibility;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700310 // These functions are the start of more optimized code for managing
311 // the string sets... not yet implemented.
312
313 private static int findStringInSet(String[] set, String string,
314 int[] lengths, int lenPos) {
315 if (set == null) return -1;
316 final int N = lengths[lenPos];
317 for (int i=0; i<N; i++) {
318 if (set[i].equals(string)) return i;
319 }
320 return -1;
321 }
322
323 private static String[] addStringToSet(String[] set, String string,
324 int[] lengths, int lenPos) {
325 if (findStringInSet(set, string, lengths, lenPos) >= 0) return set;
326 if (set == null) {
327 set = new String[2];
328 set[0] = string;
329 lengths[lenPos] = 1;
330 return set;
331 }
332 final int N = lengths[lenPos];
333 if (N < set.length) {
334 set[N] = string;
335 lengths[lenPos] = N+1;
336 return set;
337 }
338
339 String[] newSet = new String[(N*3)/2 + 2];
340 System.arraycopy(set, 0, newSet, 0, N);
341 set = newSet;
342 set[N] = string;
343 lengths[lenPos] = N+1;
344 return set;
345 }
346
347 private static String[] removeStringFromSet(String[] set, String string,
348 int[] lengths, int lenPos) {
349 int pos = findStringInSet(set, string, lengths, lenPos);
350 if (pos < 0) return set;
351 final int N = lengths[lenPos];
352 if (N > (set.length/4)) {
353 int copyLen = N-(pos+1);
354 if (copyLen > 0) {
355 System.arraycopy(set, pos+1, set, pos, copyLen);
356 }
357 set[N-1] = null;
358 lengths[lenPos] = N-1;
359 return set;
360 }
361
362 String[] newSet = new String[set.length/3];
363 if (pos > 0) System.arraycopy(set, 0, newSet, 0, pos);
364 if ((pos+1) < N) System.arraycopy(set, pos+1, newSet, pos, N-(pos+1));
365 return newSet;
366 }
367
368 /**
369 * This exception is thrown when a given MIME type does not have a valid
370 * syntax.
371 */
372 public static class MalformedMimeTypeException extends AndroidException {
373 public MalformedMimeTypeException() {
374 }
375
376 public MalformedMimeTypeException(String name) {
377 super(name);
378 }
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800379 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700380
381 /**
382 * Create a new IntentFilter instance with a specified action and MIME
383 * type, where you know the MIME type is correctly formatted. This catches
384 * the {@link MalformedMimeTypeException} exception that the constructor
385 * can call and turns it into a runtime exception.
386 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700387 * @param action The action to match, such as Intent.ACTION_VIEW.
388 * @param dataType The type to match, such as "vnd.android.cursor.dir/person".
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700389 *
390 * @return A new IntentFilter for the given action and type.
391 *
392 * @see #IntentFilter(String, String)
393 */
394 public static IntentFilter create(String action, String dataType) {
395 try {
396 return new IntentFilter(action, dataType);
397 } catch (MalformedMimeTypeException e) {
398 throw new RuntimeException("Bad MIME type", e);
399 }
400 }
401
402 /**
403 * New empty IntentFilter.
404 */
405 public IntentFilter() {
406 mPriority = 0;
407 mActions = new ArrayList<String>();
408 }
409
410 /**
411 * New IntentFilter that matches a single action with no data. If
412 * no data characteristics are subsequently specified, then the
413 * filter will only match intents that contain no data.
414 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700415 * @param action The action to match, such as Intent.ACTION_MAIN.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700416 */
417 public IntentFilter(String action) {
418 mPriority = 0;
419 mActions = new ArrayList<String>();
420 addAction(action);
421 }
422
423 /**
424 * New IntentFilter that matches a single action and data type.
425 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700426 * <p><em>Note: MIME type matching in the Android framework is
427 * case-sensitive, unlike formal RFC MIME types. As a result,
428 * you should always write your MIME types with lower case letters,
429 * and any MIME types you receive from outside of Android should be
430 * converted to lower case before supplying them here.</em></p>
431 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700432 * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
433 * not syntactically correct.
434 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700435 * @param action The action to match, such as Intent.ACTION_VIEW.
436 * @param dataType The type to match, such as "vnd.android.cursor.dir/person".
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700437 *
438 */
439 public IntentFilter(String action, String dataType)
440 throws MalformedMimeTypeException {
441 mPriority = 0;
442 mActions = new ArrayList<String>();
Tom Gibara24847f32008-11-04 02:25:42 +0000443 addAction(action);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700444 addDataType(dataType);
445 }
446
447 /**
448 * New IntentFilter containing a copy of an existing filter.
449 *
450 * @param o The original filter to copy.
451 */
452 public IntentFilter(IntentFilter o) {
453 mPriority = o.mPriority;
Todd Kennedyc2e96d42016-09-08 15:34:03 -0700454 mOrder = o.mOrder;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700455 mActions = new ArrayList<String>(o.mActions);
456 if (o.mCategories != null) {
457 mCategories = new ArrayList<String>(o.mCategories);
458 }
459 if (o.mDataTypes != null) {
460 mDataTypes = new ArrayList<String>(o.mDataTypes);
461 }
462 if (o.mDataSchemes != null) {
463 mDataSchemes = new ArrayList<String>(o.mDataSchemes);
464 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -0700465 if (o.mDataSchemeSpecificParts != null) {
466 mDataSchemeSpecificParts = new ArrayList<PatternMatcher>(o.mDataSchemeSpecificParts);
467 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700468 if (o.mDataAuthorities != null) {
469 mDataAuthorities = new ArrayList<AuthorityEntry>(o.mDataAuthorities);
470 }
471 if (o.mDataPaths != null) {
472 mDataPaths = new ArrayList<PatternMatcher>(o.mDataPaths);
473 }
474 mHasPartialTypes = o.mHasPartialTypes;
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800475 mVerifyState = o.mVerifyState;
Todd Kennedyc05f5d12017-04-25 11:11:40 -0700476 mInstantAppVisibility = o.mInstantAppVisibility;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700477 }
478
479 /**
Todd Kennedy2c4078612016-04-06 10:57:51 -0700480 * Modify priority of this filter. This only affects receiver filters.
481 * The priority of activity filters are set in XML and cannot be changed
kopriva219f7dc2018-10-09 13:42:28 -0700482 * programmatically. The default priority is 0. Positive values will be
Todd Kennedy2c4078612016-04-06 10:57:51 -0700483 * before the default, lower values will be after it. Applications should
484 * use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and
485 * smaller than {@link #SYSTEM_HIGH_PRIORITY} .
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700486 *
487 * @param priority The new priority value.
488 *
489 * @see #getPriority
490 * @see #SYSTEM_LOW_PRIORITY
491 * @see #SYSTEM_HIGH_PRIORITY
492 */
493 public final void setPriority(int priority) {
494 mPriority = priority;
495 }
496
497 /**
498 * Return the priority of this filter.
499 *
500 * @return The priority of the filter.
501 *
502 * @see #setPriority
503 */
504 public final int getPriority() {
505 return mPriority;
506 }
507
Todd Kennedyc2e96d42016-09-08 15:34:03 -0700508 /** @hide */
Todd Kennedy9c9fdf22017-03-06 10:58:27 -0800509 @SystemApi
Todd Kennedyc2e96d42016-09-08 15:34:03 -0700510 public final void setOrder(int order) {
511 mOrder = order;
512 }
513
514 /** @hide */
Todd Kennedy9c9fdf22017-03-06 10:58:27 -0800515 @SystemApi
Todd Kennedyc2e96d42016-09-08 15:34:03 -0700516 public final int getOrder() {
517 return mOrder;
518 }
519
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700520 /**
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800521 * Set whether this filter will needs to be automatically verified against its data URIs or not.
522 * The default is false.
523 *
524 * The verification would need to happen only and only if the Intent action is
525 * {@link android.content.Intent#ACTION_VIEW} and the Intent category is
526 * {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent data scheme
527 * is "http" or "https".
528 *
529 * True means that the filter will need to use its data URIs to be verified.
530 *
531 * @param autoVerify The new autoVerify value.
532 *
533 * @see #getAutoVerify()
534 * @see #addAction(String)
535 * @see #getAction(int)
536 * @see #addCategory(String)
537 * @see #getCategory(int)
538 * @see #addDataScheme(String)
539 * @see #getDataScheme(int)
540 *
541 * @hide
542 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100543 @UnsupportedAppUsage
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800544 public final void setAutoVerify(boolean autoVerify) {
545 mVerifyState &= ~STATE_VERIFY_AUTO;
546 if (autoVerify) mVerifyState |= STATE_VERIFY_AUTO;
547 }
548
549 /**
550 * Return if this filter will needs to be automatically verified again its data URIs or not.
551 *
552 * @return True if the filter will needs to be automatically verified. False otherwise.
553 *
554 * @see #setAutoVerify(boolean)
555 *
556 * @hide
557 */
558 public final boolean getAutoVerify() {
Christopher Tate3decab62016-12-15 14:18:15 -0800559 return ((mVerifyState & STATE_VERIFY_AUTO) == STATE_VERIFY_AUTO);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800560 }
561
562 /**
Christopher Tate21347442015-06-26 17:23:32 -0700563 * Return if this filter handle all HTTP or HTTPS data URI or not. This is the
564 * core check for whether a given activity qualifies as a "browser".
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700565 *
566 * @return True if the filter handle all HTTP or HTTPS data URI. False otherwise.
567 *
Fabrice Di Meglio2d897fb2015-04-09 20:03:23 -0700568 * This will check if:
569 *
570 * - either the Intent category is {@link android.content.Intent#CATEGORY_APP_BROWSER}
571 * - either the Intent action is {@link android.content.Intent#ACTION_VIEW} and
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700572 * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
573 * data scheme is "http" or "https" and that there is no specific host defined.
574 *
575 * @hide
576 */
577 public final boolean handleAllWebDataURI() {
Fabrice Di Meglio2d897fb2015-04-09 20:03:23 -0700578 return hasCategory(Intent.CATEGORY_APP_BROWSER) ||
Christopher Tate21347442015-06-26 17:23:32 -0700579 (handlesWebUris(false) && countDataAuthorities() == 0);
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700580 }
581
582 /**
Christopher Tate21347442015-06-26 17:23:32 -0700583 * Return if this filter handles HTTP or HTTPS data URIs.
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700584 *
Christopher Tate413020a2015-06-23 19:23:46 -0700585 * @return True if the filter handles ACTION_VIEW/CATEGORY_BROWSABLE,
Christopher Tate21347442015-06-26 17:23:32 -0700586 * has at least one HTTP or HTTPS data URI pattern defined, and optionally
587 * does not define any non-http/https data URI patterns.
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700588 *
589 * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
590 * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
591 * data scheme is "http" or "https".
592 *
Christopher Tate21347442015-06-26 17:23:32 -0700593 * @param onlyWebSchemes When true, requires that the intent filter declare
594 * that it handles *only* http: or https: schemes. This is a requirement for
595 * the intent filter's domain linkage being verifiable.
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700596 * @hide
597 */
Christopher Tate21347442015-06-26 17:23:32 -0700598 public final boolean handlesWebUris(boolean onlyWebSchemes) {
Christopher Tate413020a2015-06-23 19:23:46 -0700599 // Require ACTION_VIEW, CATEGORY_BROWSEABLE, and at least one scheme
600 if (!hasAction(Intent.ACTION_VIEW)
601 || !hasCategory(Intent.CATEGORY_BROWSABLE)
602 || mDataSchemes == null
603 || mDataSchemes.size() == 0) {
604 return false;
605 }
606
607 // Now allow only the schemes "http" and "https"
608 final int N = mDataSchemes.size();
609 for (int i = 0; i < N; i++) {
610 final String scheme = mDataSchemes.get(i);
Christopher Tate21347442015-06-26 17:23:32 -0700611 final boolean isWebScheme =
612 SCHEME_HTTP.equals(scheme) || SCHEME_HTTPS.equals(scheme);
613 if (onlyWebSchemes) {
614 // If we're specifically trying to ensure that there are no non-web schemes
615 // declared in this filter, then if we ever see a non-http/https scheme then
616 // we know it's a failure.
617 if (!isWebScheme) {
618 return false;
619 }
620 } else {
621 // If we see any http/https scheme declaration in this case then the
622 // filter matches what we're looking for.
623 if (isWebScheme) {
624 return true;
625 }
Christopher Tate413020a2015-06-23 19:23:46 -0700626 }
627 }
628
Christopher Tate21347442015-06-26 17:23:32 -0700629 // We get here if:
630 // 1) onlyWebSchemes and no non-web schemes were found, i.e success; or
631 // 2) !onlyWebSchemes and no http/https schemes were found, i.e. failure.
632 return onlyWebSchemes;
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700633 }
634
635 /**
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800636 * Return if this filter needs to be automatically verified again its data URIs or not.
637 *
638 * @return True if the filter needs to be automatically verified. False otherwise.
639 *
640 * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
641 * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
642 * data scheme is "http" or "https".
643 *
644 * @see #setAutoVerify(boolean)
645 *
646 * @hide
647 */
648 public final boolean needsVerification() {
Christopher Tate21347442015-06-26 17:23:32 -0700649 return getAutoVerify() && handlesWebUris(true);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800650 }
651
652 /**
653 * Return if this filter has been verified
654 *
655 * @return true if the filter has been verified or if autoVerify is false.
656 *
657 * @hide
658 */
Mathew Inwood8c854f82018-09-14 12:35:36 +0100659 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800660 public final boolean isVerified() {
661 if ((mVerifyState & STATE_NEED_VERIFY_CHECKED) == STATE_NEED_VERIFY_CHECKED) {
662 return ((mVerifyState & STATE_NEED_VERIFY) == STATE_NEED_VERIFY);
663 }
664 return false;
665 }
666
667 /**
668 * Set if this filter has been verified
669 *
670 * @param verified true if this filter has been verified. False otherwise.
671 *
672 * @hide
673 */
674 public void setVerified(boolean verified) {
675 mVerifyState |= STATE_NEED_VERIFY_CHECKED;
676 mVerifyState &= ~STATE_VERIFIED;
677 if (verified) mVerifyState |= STATE_VERIFIED;
678 }
679
Todd Kennedy7bc3a702016-12-08 14:54:48 -0800680 /** @hide */
Todd Kennedyc05f5d12017-04-25 11:11:40 -0700681 public void setVisibilityToInstantApp(@InstantAppVisibility int visibility) {
682 mInstantAppVisibility = visibility;
683 }
684 /** @hide */
685 public @InstantAppVisibility int getVisibilityToInstantApp() {
686 return mInstantAppVisibility;
Todd Kennedy7bc3a702016-12-08 14:54:48 -0800687 }
688 /** @hide */
Todd Kennedybe0b8892017-02-15 14:13:52 -0800689 public boolean isVisibleToInstantApp() {
Todd Kennedyc05f5d12017-04-25 11:11:40 -0700690 return mInstantAppVisibility != VISIBILITY_NONE;
691 }
692 /** @hide */
693 public boolean isExplicitlyVisibleToInstantApp() {
694 return mInstantAppVisibility == VISIBILITY_EXPLICIT;
695 }
696 /** @hide */
697 public boolean isImplicitlyVisibleToInstantApp() {
698 return mInstantAppVisibility == VISIBILITY_IMPLICIT;
Todd Kennedy7bc3a702016-12-08 14:54:48 -0800699 }
700
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800701 /**
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700702 * Add a new Intent action to match against. If any actions are included
703 * in the filter, then an Intent's action must be one of those values for
704 * it to match. If no actions are included, the Intent action is ignored.
705 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700706 * @param action Name of the action to match, such as Intent.ACTION_VIEW.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700707 */
708 public final void addAction(String action) {
709 if (!mActions.contains(action)) {
710 mActions.add(action.intern());
711 }
712 }
713
714 /**
715 * Return the number of actions in the filter.
716 */
717 public final int countActions() {
718 return mActions.size();
719 }
720
721 /**
722 * Return an action in the filter.
723 */
724 public final String getAction(int index) {
725 return mActions.get(index);
726 }
727
728 /**
729 * Is the given action included in the filter? Note that if the filter
730 * does not include any actions, false will <em>always</em> be returned.
731 *
732 * @param action The action to look for.
733 *
734 * @return True if the action is explicitly mentioned in the filter.
735 */
736 public final boolean hasAction(String action) {
Jeff Brown2c376fc2011-01-28 17:34:01 -0800737 return action != null && mActions.contains(action);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700738 }
739
740 /**
741 * Match this filter against an Intent's action. If the filter does not
742 * specify any actions, the match will always fail.
743 *
744 * @param action The desired action to look for.
745 *
Jeff Brown2c376fc2011-01-28 17:34:01 -0800746 * @return True if the action is listed in the filter.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700747 */
748 public final boolean matchAction(String action) {
Jeff Brown2c376fc2011-01-28 17:34:01 -0800749 return hasAction(action);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700750 }
751
752 /**
753 * Return an iterator over the filter's actions. If there are no actions,
754 * returns null.
755 */
756 public final Iterator<String> actionsIterator() {
757 return mActions != null ? mActions.iterator() : null;
758 }
759
760 /**
761 * Add a new Intent data type to match against. If any types are
762 * included in the filter, then an Intent's data must be <em>either</em>
763 * one of these types <em>or</em> a matching scheme. If no data types
764 * are included, then an Intent will only match if it specifies no data.
765 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700766 * <p><em>Note: MIME type matching in the Android framework is
767 * case-sensitive, unlike formal RFC MIME types. As a result,
768 * you should always write your MIME types with lower case letters,
769 * and any MIME types you receive from outside of Android should be
770 * converted to lower case before supplying them here.</em></p>
771 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700772 * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
773 * not syntactically correct.
774 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700775 * @param type Name of the data type to match, such as "vnd.android.cursor.dir/person".
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700776 *
777 * @see #matchData
778 */
779 public final void addDataType(String type)
780 throws MalformedMimeTypeException {
781 final int slashpos = type.indexOf('/');
782 final int typelen = type.length();
783 if (slashpos > 0 && typelen >= slashpos+2) {
784 if (mDataTypes == null) mDataTypes = new ArrayList<String>();
785 if (typelen == slashpos+2 && type.charAt(slashpos+1) == '*') {
786 String str = type.substring(0, slashpos);
787 if (!mDataTypes.contains(str)) {
788 mDataTypes.add(str.intern());
789 }
790 mHasPartialTypes = true;
791 } else {
792 if (!mDataTypes.contains(type)) {
793 mDataTypes.add(type.intern());
794 }
795 }
796 return;
797 }
798
799 throw new MalformedMimeTypeException(type);
800 }
801
802 /**
803 * Is the given data type included in the filter? Note that if the filter
804 * does not include any type, false will <em>always</em> be returned.
805 *
806 * @param type The data type to look for.
807 *
808 * @return True if the type is explicitly mentioned in the filter.
809 */
810 public final boolean hasDataType(String type) {
811 return mDataTypes != null && findMimeType(type);
812 }
813
Dianne Hackbornf2ac2762014-08-16 11:44:40 -0700814 /** @hide */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100815 @UnsupportedAppUsage
Dianne Hackbornf2ac2762014-08-16 11:44:40 -0700816 public final boolean hasExactDataType(String type) {
817 return mDataTypes != null && mDataTypes.contains(type);
818 }
819
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700820 /**
821 * Return the number of data types in the filter.
822 */
823 public final int countDataTypes() {
824 return mDataTypes != null ? mDataTypes.size() : 0;
825 }
826
827 /**
828 * Return a data type in the filter.
829 */
830 public final String getDataType(int index) {
831 return mDataTypes.get(index);
832 }
833
834 /**
835 * Return an iterator over the filter's data types.
836 */
837 public final Iterator<String> typesIterator() {
838 return mDataTypes != null ? mDataTypes.iterator() : null;
839 }
840
841 /**
842 * Add a new Intent data scheme to match against. If any schemes are
843 * included in the filter, then an Intent's data must be <em>either</em>
844 * one of these schemes <em>or</em> a matching data type. If no schemes
845 * are included, then an Intent will match only if it includes no data.
846 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700847 * <p><em>Note: scheme matching in the Android framework is
848 * case-sensitive, unlike formal RFC schemes. As a result,
849 * you should always write your schemes with lower case letters,
850 * and any schemes you receive from outside of Android should be
851 * converted to lower case before supplying them here.</em></p>
852 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700853 * @param scheme Name of the scheme to match, such as "http".
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700854 *
855 * @see #matchData
856 */
857 public final void addDataScheme(String scheme) {
858 if (mDataSchemes == null) mDataSchemes = new ArrayList<String>();
859 if (!mDataSchemes.contains(scheme)) {
860 mDataSchemes.add(scheme.intern());
861 }
862 }
863
864 /**
865 * Return the number of data schemes in the filter.
866 */
867 public final int countDataSchemes() {
868 return mDataSchemes != null ? mDataSchemes.size() : 0;
869 }
870
871 /**
872 * Return a data scheme in the filter.
873 */
874 public final String getDataScheme(int index) {
875 return mDataSchemes.get(index);
876 }
877
878 /**
879 * Is the given data scheme included in the filter? Note that if the
880 * filter does not include any scheme, false will <em>always</em> be
881 * returned.
882 *
883 * @param scheme The data scheme to look for.
884 *
885 * @return True if the scheme is explicitly mentioned in the filter.
886 */
887 public final boolean hasDataScheme(String scheme) {
888 return mDataSchemes != null && mDataSchemes.contains(scheme);
889 }
890
891 /**
892 * Return an iterator over the filter's data schemes.
893 */
894 public final Iterator<String> schemesIterator() {
895 return mDataSchemes != null ? mDataSchemes.iterator() : null;
896 }
897
898 /**
899 * This is an entry for a single authority in the Iterator returned by
900 * {@link #authoritiesIterator()}.
901 */
902 public final static class AuthorityEntry {
903 private final String mOrigHost;
904 private final String mHost;
905 private final boolean mWild;
906 private final int mPort;
907
908 public AuthorityEntry(String host, String port) {
909 mOrigHost = host;
910 mWild = host.length() > 0 && host.charAt(0) == '*';
911 mHost = mWild ? host.substring(1).intern() : host;
912 mPort = port != null ? Integer.parseInt(port) : -1;
913 }
914
915 AuthorityEntry(Parcel src) {
916 mOrigHost = src.readString();
917 mHost = src.readString();
918 mWild = src.readInt() != 0;
919 mPort = src.readInt();
920 }
921
922 void writeToParcel(Parcel dest) {
923 dest.writeString(mOrigHost);
924 dest.writeString(mHost);
925 dest.writeInt(mWild ? 1 : 0);
926 dest.writeInt(mPort);
927 }
928
Yi Jin129fc6c2017-09-28 15:48:38 -0700929 void writeToProto(ProtoOutputStream proto, long fieldId) {
930 long token = proto.start(fieldId);
931 // The original host information is already contained in host and wild, no output now.
932 proto.write(AuthorityEntryProto.HOST, mHost);
933 proto.write(AuthorityEntryProto.WILD, mWild);
934 proto.write(AuthorityEntryProto.PORT, mPort);
935 proto.end(token);
936 }
937
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700938 public String getHost() {
939 return mOrigHost;
940 }
941
942 public int getPort() {
943 return mPort;
944 }
945
Dianne Hackbornf2ac2762014-08-16 11:44:40 -0700946 /** @hide */
947 public boolean match(AuthorityEntry other) {
948 if (mWild != other.mWild) {
949 return false;
950 }
951 if (!mHost.equals(other.mHost)) {
952 return false;
953 }
954 if (mPort != other.mPort) {
955 return false;
956 }
957 return true;
958 }
959
Todd Kennedy5585dd92016-03-29 13:07:01 -0700960 @Override
961 public boolean equals(Object obj) {
962 if (obj instanceof AuthorityEntry) {
963 final AuthorityEntry other = (AuthorityEntry)obj;
964 return match(other);
965 }
966 return false;
967 }
968
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700969 /**
970 * Determine whether this AuthorityEntry matches the given data Uri.
971 * <em>Note that this comparison is case-sensitive, unlike formal
972 * RFC host names. You thus should always normalize to lower-case.</em>
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -0700973 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -0700974 * @param data The Uri to match.
975 * @return Returns either {@link IntentFilter#NO_MATCH_DATA},
976 * {@link IntentFilter#MATCH_CATEGORY_PORT}, or
977 * {@link IntentFilter#MATCH_CATEGORY_HOST}.
978 */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700979 public int match(Uri data) {
980 String host = data.getHost();
981 if (host == null) {
982 return NO_MATCH_DATA;
983 }
Joe Onorato43a17652011-04-06 19:22:23 -0700984 if (false) Log.v("IntentFilter",
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700985 "Match host " + host + ": " + mHost);
986 if (mWild) {
987 if (host.length() < mHost.length()) {
988 return NO_MATCH_DATA;
989 }
990 host = host.substring(host.length()-mHost.length());
991 }
992 if (host.compareToIgnoreCase(mHost) != 0) {
993 return NO_MATCH_DATA;
994 }
995 if (mPort >= 0) {
996 if (mPort != data.getPort()) {
997 return NO_MATCH_DATA;
998 }
999 return MATCH_CATEGORY_PORT;
1000 }
1001 return MATCH_CATEGORY_HOST;
1002 }
Todd Kennedy5585dd92016-03-29 13:07:01 -07001003 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001004
1005 /**
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001006 * Add a new Intent data "scheme specific part" to match against. The filter must
1007 * include one or more schemes (via {@link #addDataScheme}) for the
1008 * scheme specific part to be considered. If any scheme specific parts are
1009 * included in the filter, then an Intent's data must match one of
1010 * them. If no scheme specific parts are included, then only the scheme must match.
1011 *
Dianne Hackbornebc15ef2013-10-09 17:36:57 -07001012 * <p>The "scheme specific part" that this matches against is the string returned
1013 * by {@link android.net.Uri#getSchemeSpecificPart() Uri.getSchemeSpecificPart}.
1014 * For Uris that contain a path, this kind of matching is not generally of interest,
1015 * since {@link #addDataAuthority(String, String)} and
1016 * {@link #addDataPath(String, int)} can provide a better mechanism for matching
1017 * them. However, for Uris that do not contain a path, the authority and path
1018 * are empty, so this is the only way to match against the non-scheme part.</p>
1019 *
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001020 * @param ssp Either a raw string that must exactly match the scheme specific part
1021 * path, or a simple pattern, depending on <var>type</var>.
1022 * @param type Determines how <var>ssp</var> will be compared to
1023 * determine a match: either {@link PatternMatcher#PATTERN_LITERAL},
1024 * {@link PatternMatcher#PATTERN_PREFIX}, or
1025 * {@link PatternMatcher#PATTERN_SIMPLE_GLOB}.
1026 *
1027 * @see #matchData
1028 * @see #addDataScheme
1029 */
1030 public final void addDataSchemeSpecificPart(String ssp, int type) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07001031 addDataSchemeSpecificPart(new PatternMatcher(ssp, type));
1032 }
1033
1034 /** @hide */
1035 public final void addDataSchemeSpecificPart(PatternMatcher ssp) {
Dianne Hackborn439e9bc82013-06-12 19:13:49 -07001036 if (mDataSchemeSpecificParts == null) {
1037 mDataSchemeSpecificParts = new ArrayList<PatternMatcher>();
1038 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07001039 mDataSchemeSpecificParts.add(ssp);
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001040 }
1041
1042 /**
1043 * Return the number of data scheme specific parts in the filter.
1044 */
1045 public final int countDataSchemeSpecificParts() {
1046 return mDataSchemeSpecificParts != null ? mDataSchemeSpecificParts.size() : 0;
1047 }
1048
1049 /**
1050 * Return a data scheme specific part in the filter.
1051 */
1052 public final PatternMatcher getDataSchemeSpecificPart(int index) {
1053 return mDataSchemeSpecificParts.get(index);
1054 }
1055
1056 /**
1057 * Is the given data scheme specific part included in the filter? Note that if the
1058 * filter does not include any scheme specific parts, false will <em>always</em> be
1059 * returned.
1060 *
1061 * @param data The scheme specific part that is being looked for.
1062 *
1063 * @return Returns true if the data string matches a scheme specific part listed in the
1064 * filter.
1065 */
1066 public final boolean hasDataSchemeSpecificPart(String data) {
1067 if (mDataSchemeSpecificParts == null) {
1068 return false;
1069 }
1070 final int numDataSchemeSpecificParts = mDataSchemeSpecificParts.size();
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001071 for (int i = 0; i < numDataSchemeSpecificParts; i++) {
1072 final PatternMatcher pe = mDataSchemeSpecificParts.get(i);
1073 if (pe.match(data)) {
1074 return true;
1075 }
1076 }
1077 return false;
1078 }
1079
Dianne Hackbornf2ac2762014-08-16 11:44:40 -07001080 /** @hide */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001081 @UnsupportedAppUsage
Dianne Hackbornf2ac2762014-08-16 11:44:40 -07001082 public final boolean hasDataSchemeSpecificPart(PatternMatcher ssp) {
1083 if (mDataSchemeSpecificParts == null) {
1084 return false;
1085 }
1086 final int numDataSchemeSpecificParts = mDataSchemeSpecificParts.size();
1087 for (int i = 0; i < numDataSchemeSpecificParts; i++) {
1088 final PatternMatcher pe = mDataSchemeSpecificParts.get(i);
1089 if (pe.getType() == ssp.getType() && pe.getPath().equals(ssp.getPath())) {
1090 return true;
1091 }
1092 }
1093 return false;
1094 }
1095
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001096 /**
1097 * Return an iterator over the filter's data scheme specific parts.
1098 */
1099 public final Iterator<PatternMatcher> schemeSpecificPartsIterator() {
1100 return mDataSchemeSpecificParts != null ? mDataSchemeSpecificParts.iterator() : null;
1101 }
1102
1103 /**
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001104 * Add a new Intent data authority to match against. The filter must
1105 * include one or more schemes (via {@link #addDataScheme}) for the
1106 * authority to be considered. If any authorities are
1107 * included in the filter, then an Intent's data must match one of
1108 * them. If no authorities are included, then only the scheme must match.
1109 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -07001110 * <p><em>Note: host name in the Android framework is
1111 * case-sensitive, unlike formal RFC host names. As a result,
1112 * you should always write your host names with lower case letters,
1113 * and any host names you receive from outside of Android should be
1114 * converted to lower case before supplying them here.</em></p>
1115 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001116 * @param host The host part of the authority to match. May start with a
1117 * single '*' to wildcard the front of the host name.
1118 * @param port Optional port part of the authority to match. If null, any
1119 * port is allowed.
1120 *
1121 * @see #matchData
1122 * @see #addDataScheme
1123 */
1124 public final void addDataAuthority(String host, String port) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07001125 if (port != null) port = port.intern();
1126 addDataAuthority(new AuthorityEntry(host.intern(), port));
1127 }
1128
1129 /** @hide */
1130 public final void addDataAuthority(AuthorityEntry ent) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001131 if (mDataAuthorities == null) mDataAuthorities =
1132 new ArrayList<AuthorityEntry>();
Dianne Hackbornb09491f2013-07-22 15:30:11 -07001133 mDataAuthorities.add(ent);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001134 }
1135
1136 /**
1137 * Return the number of data authorities in the filter.
1138 */
1139 public final int countDataAuthorities() {
1140 return mDataAuthorities != null ? mDataAuthorities.size() : 0;
1141 }
1142
1143 /**
1144 * Return a data authority in the filter.
1145 */
1146 public final AuthorityEntry getDataAuthority(int index) {
1147 return mDataAuthorities.get(index);
1148 }
1149
1150 /**
1151 * Is the given data authority included in the filter? Note that if the
1152 * filter does not include any authorities, false will <em>always</em> be
1153 * returned.
1154 *
1155 * @param data The data whose authority is being looked for.
1156 *
1157 * @return Returns true if the data string matches an authority listed in the
1158 * filter.
1159 */
1160 public final boolean hasDataAuthority(Uri data) {
1161 return matchDataAuthority(data) >= 0;
1162 }
1163
Dianne Hackbornf2ac2762014-08-16 11:44:40 -07001164 /** @hide */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001165 @UnsupportedAppUsage
Dianne Hackbornf2ac2762014-08-16 11:44:40 -07001166 public final boolean hasDataAuthority(AuthorityEntry auth) {
1167 if (mDataAuthorities == null) {
1168 return false;
1169 }
1170 final int numDataAuthorities = mDataAuthorities.size();
1171 for (int i = 0; i < numDataAuthorities; i++) {
1172 if (mDataAuthorities.get(i).match(auth)) {
1173 return true;
1174 }
1175 }
1176 return false;
1177 }
1178
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001179 /**
1180 * Return an iterator over the filter's data authorities.
1181 */
1182 public final Iterator<AuthorityEntry> authoritiesIterator() {
1183 return mDataAuthorities != null ? mDataAuthorities.iterator() : null;
1184 }
1185
1186 /**
Gilles Debunne37051cd2011-05-25 16:27:13 -07001187 * Add a new Intent data path to match against. The filter must
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001188 * include one or more schemes (via {@link #addDataScheme}) <em>and</em>
1189 * one or more authorities (via {@link #addDataAuthority}) for the
1190 * path to be considered. If any paths are
1191 * included in the filter, then an Intent's data must match one of
1192 * them. If no paths are included, then only the scheme/authority must
1193 * match.
1194 *
1195 * <p>The path given here can either be a literal that must directly
1196 * match or match against a prefix, or it can be a simple globbing pattern.
1197 * If the latter, you can use '*' anywhere in the pattern to match zero
1198 * or more instances of the previous character, '.' as a wildcard to match
1199 * any character, and '\' to escape the next character.
1200 *
1201 * @param path Either a raw string that must exactly match the file
1202 * path, or a simple pattern, depending on <var>type</var>.
1203 * @param type Determines how <var>path</var> will be compared to
1204 * determine a match: either {@link PatternMatcher#PATTERN_LITERAL},
1205 * {@link PatternMatcher#PATTERN_PREFIX}, or
1206 * {@link PatternMatcher#PATTERN_SIMPLE_GLOB}.
1207 *
1208 * @see #matchData
1209 * @see #addDataScheme
1210 * @see #addDataAuthority
1211 */
1212 public final void addDataPath(String path, int type) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07001213 addDataPath(new PatternMatcher(path.intern(), type));
1214 }
1215
1216 /** @hide */
1217 public final void addDataPath(PatternMatcher path) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001218 if (mDataPaths == null) mDataPaths = new ArrayList<PatternMatcher>();
Dianne Hackbornb09491f2013-07-22 15:30:11 -07001219 mDataPaths.add(path);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001220 }
1221
1222 /**
1223 * Return the number of data paths in the filter.
1224 */
1225 public final int countDataPaths() {
1226 return mDataPaths != null ? mDataPaths.size() : 0;
1227 }
1228
1229 /**
1230 * Return a data path in the filter.
1231 */
1232 public final PatternMatcher getDataPath(int index) {
1233 return mDataPaths.get(index);
1234 }
1235
1236 /**
1237 * Is the given data path included in the filter? Note that if the
1238 * filter does not include any paths, false will <em>always</em> be
1239 * returned.
1240 *
1241 * @param data The data path to look for. This is without the scheme
1242 * prefix.
1243 *
1244 * @return True if the data string matches a path listed in the
1245 * filter.
1246 */
1247 public final boolean hasDataPath(String data) {
1248 if (mDataPaths == null) {
1249 return false;
1250 }
Jeff Brown2c376fc2011-01-28 17:34:01 -08001251 final int numDataPaths = mDataPaths.size();
1252 for (int i = 0; i < numDataPaths; i++) {
1253 final PatternMatcher pe = mDataPaths.get(i);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001254 if (pe.match(data)) {
1255 return true;
1256 }
1257 }
1258 return false;
1259 }
1260
Dianne Hackbornf2ac2762014-08-16 11:44:40 -07001261 /** @hide */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001262 @UnsupportedAppUsage
Dianne Hackbornf2ac2762014-08-16 11:44:40 -07001263 public final boolean hasDataPath(PatternMatcher path) {
1264 if (mDataPaths == null) {
1265 return false;
1266 }
1267 final int numDataPaths = mDataPaths.size();
1268 for (int i = 0; i < numDataPaths; i++) {
1269 final PatternMatcher pe = mDataPaths.get(i);
1270 if (pe.getType() == path.getType() && pe.getPath().equals(path.getPath())) {
1271 return true;
1272 }
1273 }
1274 return false;
1275 }
1276
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001277 /**
1278 * Return an iterator over the filter's data paths.
1279 */
1280 public final Iterator<PatternMatcher> pathsIterator() {
1281 return mDataPaths != null ? mDataPaths.iterator() : null;
1282 }
1283
1284 /**
1285 * Match this intent filter against the given Intent data. This ignores
1286 * the data scheme -- unlike {@link #matchData}, the authority will match
1287 * regardless of whether there is a matching scheme.
1288 *
1289 * @param data The data whose authority is being looked for.
1290 *
1291 * @return Returns either {@link #MATCH_CATEGORY_HOST},
1292 * {@link #MATCH_CATEGORY_PORT}, {@link #NO_MATCH_DATA}.
1293 */
1294 public final int matchDataAuthority(Uri data) {
Dianne Hackborn9dc6c612015-07-28 17:30:59 -07001295 if (mDataAuthorities == null || data == null) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001296 return NO_MATCH_DATA;
1297 }
Jeff Brown2c376fc2011-01-28 17:34:01 -08001298 final int numDataAuthorities = mDataAuthorities.size();
1299 for (int i = 0; i < numDataAuthorities; i++) {
1300 final AuthorityEntry ae = mDataAuthorities.get(i);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001301 int match = ae.match(data);
1302 if (match >= 0) {
1303 return match;
1304 }
1305 }
1306 return NO_MATCH_DATA;
1307 }
1308
1309 /**
1310 * Match this filter against an Intent's data (type, scheme and path). If
1311 * the filter does not specify any types and does not specify any
1312 * schemes/paths, the match will only succeed if the intent does not
Dianne Hackborn0ea920d2013-10-11 09:40:18 -07001313 * also specify a type or data. If the filter does not specify any schemes,
1314 * it will implicitly match intents with no scheme, or the schemes "content:"
1315 * or "file:" (basically performing a MIME-type only match). If the filter
1316 * does not specify any MIME types, the Intent also must not specify a MIME
1317 * type.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001318 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -07001319 * <p>Be aware that to match against an authority, you must also specify a base
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001320 * scheme the authority is in. To match against a data path, both a scheme
1321 * and authority must be specified. If the filter does not specify any
1322 * types or schemes that it matches against, it is considered to be empty
1323 * (any authority or data path given is ignored, as if it were empty as
1324 * well).
1325 *
Dianne Hackbornb3cddae2009-04-13 16:54:00 -07001326 * <p><em>Note: MIME type, Uri scheme, and host name matching in the
1327 * Android framework is case-sensitive, unlike the formal RFC definitions.
1328 * As a result, you should always write these elements with lower case letters,
1329 * and normalize any MIME types or Uris you receive from
1330 * outside of Android to ensure these elements are lower case before
1331 * supplying them here.</em></p>
1332 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001333 * @param type The desired data type to look for, as returned by
1334 * Intent.resolveType().
1335 * @param scheme The desired data scheme to look for, as returned by
1336 * Intent.getScheme().
1337 * @param data The full data string to match against, as supplied in
1338 * Intent.data.
1339 *
1340 * @return Returns either a valid match constant (a combination of
1341 * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
1342 * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match
1343 * or {@link #NO_MATCH_DATA} if the scheme/path didn't match.
1344 *
1345 * @see #match
1346 */
1347 public final int matchData(String type, String scheme, Uri data) {
1348 final ArrayList<String> types = mDataTypes;
1349 final ArrayList<String> schemes = mDataSchemes;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001350
1351 int match = MATCH_CATEGORY_EMPTY;
1352
1353 if (types == null && schemes == null) {
1354 return ((type == null && data == null)
1355 ? (MATCH_CATEGORY_EMPTY+MATCH_ADJUSTMENT_NORMAL) : NO_MATCH_DATA);
1356 }
1357
1358 if (schemes != null) {
1359 if (schemes.contains(scheme != null ? scheme : "")) {
1360 match = MATCH_CATEGORY_SCHEME;
1361 } else {
1362 return NO_MATCH_DATA;
1363 }
1364
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001365 final ArrayList<PatternMatcher> schemeSpecificParts = mDataSchemeSpecificParts;
Dianne Hackborn9dc6c612015-07-28 17:30:59 -07001366 if (schemeSpecificParts != null && data != null) {
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001367 match = hasDataSchemeSpecificPart(data.getSchemeSpecificPart())
1368 ? MATCH_CATEGORY_SCHEME_SPECIFIC_PART : NO_MATCH_DATA;
1369 }
1370 if (match != MATCH_CATEGORY_SCHEME_SPECIFIC_PART) {
1371 // If there isn't any matching ssp, we need to match an authority.
1372 final ArrayList<AuthorityEntry> authorities = mDataAuthorities;
1373 if (authorities != null) {
1374 int authMatch = matchDataAuthority(data);
1375 if (authMatch >= 0) {
1376 final ArrayList<PatternMatcher> paths = mDataPaths;
1377 if (paths == null) {
1378 match = authMatch;
1379 } else if (hasDataPath(data.getPath())) {
1380 match = MATCH_CATEGORY_PATH;
1381 } else {
1382 return NO_MATCH_DATA;
1383 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001384 } else {
1385 return NO_MATCH_DATA;
1386 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001387 }
1388 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001389 // If neither an ssp nor an authority matched, we're done.
1390 if (match == NO_MATCH_DATA) {
1391 return NO_MATCH_DATA;
1392 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001393 } else {
1394 // Special case: match either an Intent with no data URI,
1395 // or with a scheme: URI. This is to give a convenience for
1396 // the common case where you want to deal with data in a
1397 // content provider, which is done by type, and we don't want
1398 // to force everyone to say they handle content: or file: URIs.
1399 if (scheme != null && !"".equals(scheme)
1400 && !"content".equals(scheme)
1401 && !"file".equals(scheme)) {
1402 return NO_MATCH_DATA;
1403 }
1404 }
1405
1406 if (types != null) {
1407 if (findMimeType(type)) {
1408 match = MATCH_CATEGORY_TYPE;
1409 } else {
1410 return NO_MATCH_TYPE;
1411 }
1412 } else {
1413 // If no MIME types are specified, then we will only match against
1414 // an Intent that does not have a MIME type.
1415 if (type != null) {
1416 return NO_MATCH_TYPE;
1417 }
1418 }
1419
1420 return match + MATCH_ADJUSTMENT_NORMAL;
1421 }
1422
1423 /**
1424 * Add a new Intent category to match against. The semantics of
1425 * categories is the opposite of actions -- an Intent includes the
1426 * categories that it requires, all of which must be included in the
1427 * filter in order to match. In other words, adding a category to the
1428 * filter has no impact on matching unless that category is specified in
1429 * the intent.
1430 *
Kevin Hufnaglee20b3d72016-09-22 18:33:57 -07001431 * @param category Name of category to match, such as Intent.CATEGORY_EMBED.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001432 */
1433 public final void addCategory(String category) {
1434 if (mCategories == null) mCategories = new ArrayList<String>();
1435 if (!mCategories.contains(category)) {
1436 mCategories.add(category.intern());
1437 }
1438 }
1439
1440 /**
1441 * Return the number of categories in the filter.
1442 */
1443 public final int countCategories() {
1444 return mCategories != null ? mCategories.size() : 0;
1445 }
1446
1447 /**
1448 * Return a category in the filter.
1449 */
1450 public final String getCategory(int index) {
1451 return mCategories.get(index);
1452 }
1453
1454 /**
1455 * Is the given category included in the filter?
1456 *
1457 * @param category The category that the filter supports.
1458 *
1459 * @return True if the category is explicitly mentioned in the filter.
1460 */
1461 public final boolean hasCategory(String category) {
1462 return mCategories != null && mCategories.contains(category);
1463 }
1464
1465 /**
1466 * Return an iterator over the filter's categories.
Kenny Rootd2d29252011-08-08 11:27:57 -07001467 *
1468 * @return Iterator if this filter has categories or {@code null} if none.
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001469 */
1470 public final Iterator<String> categoriesIterator() {
1471 return mCategories != null ? mCategories.iterator() : null;
1472 }
1473
1474 /**
1475 * Match this filter against an Intent's categories. Each category in
1476 * the Intent must be specified by the filter; if any are not in the
1477 * filter, the match fails.
1478 *
1479 * @param categories The categories included in the intent, as returned by
1480 * Intent.getCategories().
1481 *
1482 * @return If all categories match (success), null; else the name of the
1483 * first category that didn't match.
1484 */
1485 public final String matchCategories(Set<String> categories) {
1486 if (categories == null) {
1487 return null;
1488 }
1489
1490 Iterator<String> it = categories.iterator();
1491
1492 if (mCategories == null) {
1493 return it.hasNext() ? it.next() : null;
1494 }
1495
1496 while (it.hasNext()) {
1497 final String category = it.next();
1498 if (!mCategories.contains(category)) {
1499 return category;
1500 }
1501 }
1502
1503 return null;
1504 }
1505
1506 /**
1507 * Test whether this filter matches the given <var>intent</var>.
1508 *
1509 * @param intent The Intent to compare against.
1510 * @param resolve If true, the intent's type will be resolved by calling
1511 * Intent.resolveType(); otherwise a simple match against
1512 * Intent.type will be performed.
1513 * @param logTag Tag to use in debugging messages.
1514 *
1515 * @return Returns either a valid match constant (a combination of
1516 * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
1517 * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match,
1518 * {@link #NO_MATCH_DATA} if the scheme/path didn't match,
Dianne Hackborndc894042014-08-12 18:59:28 -07001519 * {@link #NO_MATCH_ACTION} if the action didn't match, or
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001520 * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match.
1521 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001522 * @see #match(String, String, String, android.net.Uri , Set, String)
1523 */
1524 public final int match(ContentResolver resolver, Intent intent,
1525 boolean resolve, String logTag) {
1526 String type = resolve ? intent.resolveType(resolver) : intent.getType();
1527 return match(intent.getAction(), type, intent.getScheme(),
1528 intent.getData(), intent.getCategories(), logTag);
1529 }
1530
1531 /**
1532 * Test whether this filter matches the given intent data. A match is
1533 * only successful if the actions and categories in the Intent match
1534 * against the filter, as described in {@link IntentFilter}; in that case,
1535 * the match result returned will be as per {@link #matchData}.
1536 *
1537 * @param action The intent action to match against (Intent.getAction).
1538 * @param type The intent type to match against (Intent.resolveType()).
1539 * @param scheme The data scheme to match against (Intent.getScheme()).
1540 * @param data The data URI to match against (Intent.getData()).
1541 * @param categories The categories to match against
1542 * (Intent.getCategories()).
1543 * @param logTag Tag to use in debugging messages.
1544 *
1545 * @return Returns either a valid match constant (a combination of
1546 * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
1547 * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match,
1548 * {@link #NO_MATCH_DATA} if the scheme/path didn't match,
Dianne Hackborndc894042014-08-12 18:59:28 -07001549 * {@link #NO_MATCH_ACTION} if the action didn't match, or
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001550 * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match.
1551 *
1552 * @see #matchData
1553 * @see Intent#getAction
1554 * @see Intent#resolveType
1555 * @see Intent#getScheme
1556 * @see Intent#getData
1557 * @see Intent#getCategories
1558 */
1559 public final int match(String action, String type, String scheme,
1560 Uri data, Set<String> categories, String logTag) {
Jeff Brown239f77d2011-02-26 16:03:48 -08001561 if (action != null && !matchAction(action)) {
Joe Onorato43a17652011-04-06 19:22:23 -07001562 if (false) Log.v(
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001563 logTag, "No matching action " + action + " for " + this);
1564 return NO_MATCH_ACTION;
1565 }
1566
1567 int dataMatch = matchData(type, scheme, data);
1568 if (dataMatch < 0) {
Joe Onorato43a17652011-04-06 19:22:23 -07001569 if (false) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001570 if (dataMatch == NO_MATCH_TYPE) {
1571 Log.v(logTag, "No matching type " + type
1572 + " for " + this);
1573 }
1574 if (dataMatch == NO_MATCH_DATA) {
1575 Log.v(logTag, "No matching scheme/path " + data
1576 + " for " + this);
1577 }
1578 }
1579 return dataMatch;
1580 }
1581
Jeff Brown2c376fc2011-01-28 17:34:01 -08001582 String categoryMismatch = matchCategories(categories);
1583 if (categoryMismatch != null) {
Joe Onorato43a17652011-04-06 19:22:23 -07001584 if (false) {
Jeff Brown2c376fc2011-01-28 17:34:01 -08001585 Log.v(logTag, "No matching category " + categoryMismatch + " for " + this);
1586 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001587 return NO_MATCH_CATEGORY;
1588 }
1589
1590 // It would be nice to treat container activities as more
1591 // important than ones that can be embedded, but this is not the way...
1592 if (false) {
1593 if (categories != null) {
1594 dataMatch -= mCategories.size() - categories.size();
1595 }
1596 }
1597
1598 return dataMatch;
1599 }
1600
1601 /**
1602 * Write the contents of the IntentFilter as an XML stream.
1603 */
1604 public void writeToXml(XmlSerializer serializer) throws IOException {
Wale Ogunwale15b9fd22015-06-19 08:59:52 -07001605
1606 if (getAutoVerify()) {
1607 serializer.attribute(null, AUTO_VERIFY_STR, Boolean.toString(true));
1608 }
1609
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001610 int N = countActions();
1611 for (int i=0; i<N; i++) {
1612 serializer.startTag(null, ACTION_STR);
1613 serializer.attribute(null, NAME_STR, mActions.get(i));
1614 serializer.endTag(null, ACTION_STR);
1615 }
1616 N = countCategories();
1617 for (int i=0; i<N; i++) {
1618 serializer.startTag(null, CAT_STR);
1619 serializer.attribute(null, NAME_STR, mCategories.get(i));
1620 serializer.endTag(null, CAT_STR);
1621 }
1622 N = countDataTypes();
1623 for (int i=0; i<N; i++) {
1624 serializer.startTag(null, TYPE_STR);
1625 String type = mDataTypes.get(i);
1626 if (type.indexOf('/') < 0) type = type + "/*";
1627 serializer.attribute(null, NAME_STR, type);
1628 serializer.endTag(null, TYPE_STR);
1629 }
1630 N = countDataSchemes();
1631 for (int i=0; i<N; i++) {
1632 serializer.startTag(null, SCHEME_STR);
1633 serializer.attribute(null, NAME_STR, mDataSchemes.get(i));
1634 serializer.endTag(null, SCHEME_STR);
1635 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001636 N = countDataSchemeSpecificParts();
1637 for (int i=0; i<N; i++) {
1638 serializer.startTag(null, SSP_STR);
1639 PatternMatcher pe = mDataSchemeSpecificParts.get(i);
1640 switch (pe.getType()) {
1641 case PatternMatcher.PATTERN_LITERAL:
1642 serializer.attribute(null, LITERAL_STR, pe.getPath());
1643 break;
1644 case PatternMatcher.PATTERN_PREFIX:
1645 serializer.attribute(null, PREFIX_STR, pe.getPath());
1646 break;
1647 case PatternMatcher.PATTERN_SIMPLE_GLOB:
1648 serializer.attribute(null, SGLOB_STR, pe.getPath());
1649 break;
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08001650 case PatternMatcher.PATTERN_ADVANCED_GLOB:
1651 serializer.attribute(null, AGLOB_STR, pe.getPath());
1652 break;
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001653 }
1654 serializer.endTag(null, SSP_STR);
1655 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001656 N = countDataAuthorities();
1657 for (int i=0; i<N; i++) {
1658 serializer.startTag(null, AUTH_STR);
1659 AuthorityEntry ae = mDataAuthorities.get(i);
1660 serializer.attribute(null, HOST_STR, ae.getHost());
1661 if (ae.getPort() >= 0) {
1662 serializer.attribute(null, PORT_STR, Integer.toString(ae.getPort()));
1663 }
1664 serializer.endTag(null, AUTH_STR);
1665 }
1666 N = countDataPaths();
1667 for (int i=0; i<N; i++) {
1668 serializer.startTag(null, PATH_STR);
1669 PatternMatcher pe = mDataPaths.get(i);
1670 switch (pe.getType()) {
1671 case PatternMatcher.PATTERN_LITERAL:
1672 serializer.attribute(null, LITERAL_STR, pe.getPath());
1673 break;
1674 case PatternMatcher.PATTERN_PREFIX:
1675 serializer.attribute(null, PREFIX_STR, pe.getPath());
1676 break;
1677 case PatternMatcher.PATTERN_SIMPLE_GLOB:
1678 serializer.attribute(null, SGLOB_STR, pe.getPath());
1679 break;
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08001680 case PatternMatcher.PATTERN_ADVANCED_GLOB:
1681 serializer.attribute(null, AGLOB_STR, pe.getPath());
1682 break;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001683 }
1684 serializer.endTag(null, PATH_STR);
1685 }
1686 }
1687
1688 public void readFromXml(XmlPullParser parser) throws XmlPullParserException,
1689 IOException {
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08001690 String autoVerify = parser.getAttributeValue(null, AUTO_VERIFY_STR);
1691 setAutoVerify(TextUtils.isEmpty(autoVerify) ? false : Boolean.getBoolean(autoVerify));
1692
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001693 int outerDepth = parser.getDepth();
1694 int type;
1695 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1696 && (type != XmlPullParser.END_TAG
1697 || parser.getDepth() > outerDepth)) {
1698 if (type == XmlPullParser.END_TAG
1699 || type == XmlPullParser.TEXT) {
1700 continue;
1701 }
1702
1703 String tagName = parser.getName();
1704 if (tagName.equals(ACTION_STR)) {
1705 String name = parser.getAttributeValue(null, NAME_STR);
1706 if (name != null) {
1707 addAction(name);
1708 }
1709 } else if (tagName.equals(CAT_STR)) {
1710 String name = parser.getAttributeValue(null, NAME_STR);
1711 if (name != null) {
1712 addCategory(name);
1713 }
1714 } else if (tagName.equals(TYPE_STR)) {
1715 String name = parser.getAttributeValue(null, NAME_STR);
1716 if (name != null) {
1717 try {
1718 addDataType(name);
1719 } catch (MalformedMimeTypeException e) {
1720 }
1721 }
1722 } else if (tagName.equals(SCHEME_STR)) {
1723 String name = parser.getAttributeValue(null, NAME_STR);
1724 if (name != null) {
1725 addDataScheme(name);
1726 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001727 } else if (tagName.equals(SSP_STR)) {
1728 String ssp = parser.getAttributeValue(null, LITERAL_STR);
1729 if (ssp != null) {
1730 addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_LITERAL);
1731 } else if ((ssp=parser.getAttributeValue(null, PREFIX_STR)) != null) {
1732 addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_PREFIX);
1733 } else if ((ssp=parser.getAttributeValue(null, SGLOB_STR)) != null) {
1734 addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_SIMPLE_GLOB);
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08001735 } else if ((ssp=parser.getAttributeValue(null, AGLOB_STR)) != null) {
1736 addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_ADVANCED_GLOB);
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001737 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001738 } else if (tagName.equals(AUTH_STR)) {
1739 String host = parser.getAttributeValue(null, HOST_STR);
1740 String port = parser.getAttributeValue(null, PORT_STR);
1741 if (host != null) {
1742 addDataAuthority(host, port);
1743 }
1744 } else if (tagName.equals(PATH_STR)) {
1745 String path = parser.getAttributeValue(null, LITERAL_STR);
1746 if (path != null) {
1747 addDataPath(path, PatternMatcher.PATTERN_LITERAL);
1748 } else if ((path=parser.getAttributeValue(null, PREFIX_STR)) != null) {
1749 addDataPath(path, PatternMatcher.PATTERN_PREFIX);
1750 } else if ((path=parser.getAttributeValue(null, SGLOB_STR)) != null) {
1751 addDataPath(path, PatternMatcher.PATTERN_SIMPLE_GLOB);
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08001752 } else if ((path=parser.getAttributeValue(null, AGLOB_STR)) != null) {
1753 addDataPath(path, PatternMatcher.PATTERN_ADVANCED_GLOB);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001754 }
1755 } else {
1756 Log.w("IntentFilter", "Unknown tag parsing IntentFilter: " + tagName);
1757 }
1758 XmlUtils.skipCurrentTag(parser);
1759 }
1760 }
1761
Yi Jin129fc6c2017-09-28 15:48:38 -07001762 /** @hide */
1763 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1764 long token = proto.start(fieldId);
1765 if (mActions.size() > 0) {
1766 Iterator<String> it = mActions.iterator();
1767 while (it.hasNext()) {
1768 proto.write(IntentFilterProto.ACTIONS, it.next());
1769 }
1770 }
1771 if (mCategories != null) {
1772 Iterator<String> it = mCategories.iterator();
1773 while (it.hasNext()) {
1774 proto.write(IntentFilterProto.CATEGORIES, it.next());
1775 }
1776 }
1777 if (mDataSchemes != null) {
1778 Iterator<String> it = mDataSchemes.iterator();
1779 while (it.hasNext()) {
1780 proto.write(IntentFilterProto.DATA_SCHEMES, it.next());
1781 }
1782 }
1783 if (mDataSchemeSpecificParts != null) {
1784 Iterator<PatternMatcher> it = mDataSchemeSpecificParts.iterator();
1785 while (it.hasNext()) {
1786 it.next().writeToProto(proto, IntentFilterProto.DATA_SCHEME_SPECS);
1787 }
1788 }
1789 if (mDataAuthorities != null) {
1790 Iterator<AuthorityEntry> it = mDataAuthorities.iterator();
1791 while (it.hasNext()) {
1792 it.next().writeToProto(proto, IntentFilterProto.DATA_AUTHORITIES);
1793 }
1794 }
1795 if (mDataPaths != null) {
1796 Iterator<PatternMatcher> it = mDataPaths.iterator();
1797 while (it.hasNext()) {
1798 it.next().writeToProto(proto, IntentFilterProto.DATA_PATHS);
1799 }
1800 }
1801 if (mDataTypes != null) {
1802 Iterator<String> it = mDataTypes.iterator();
1803 while (it.hasNext()) {
1804 proto.write(IntentFilterProto.DATA_TYPES, it.next());
1805 }
1806 }
1807 if (mPriority != 0 || mHasPartialTypes) {
1808 proto.write(IntentFilterProto.PRIORITY, mPriority);
1809 proto.write(IntentFilterProto.HAS_PARTIAL_TYPES, mHasPartialTypes);
1810 }
1811 proto.write(IntentFilterProto.GET_AUTO_VERIFY, getAutoVerify());
1812 proto.end(token);
1813 }
1814
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001815 public void dump(Printer du, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001816 StringBuilder sb = new StringBuilder(256);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001817 if (mActions.size() > 0) {
1818 Iterator<String> it = mActions.iterator();
1819 while (it.hasNext()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001820 sb.setLength(0);
1821 sb.append(prefix); sb.append("Action: \"");
1822 sb.append(it.next()); sb.append("\"");
1823 du.println(sb.toString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001824 }
1825 }
1826 if (mCategories != null) {
1827 Iterator<String> it = mCategories.iterator();
1828 while (it.hasNext()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001829 sb.setLength(0);
1830 sb.append(prefix); sb.append("Category: \"");
1831 sb.append(it.next()); sb.append("\"");
1832 du.println(sb.toString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001833 }
1834 }
1835 if (mDataSchemes != null) {
1836 Iterator<String> it = mDataSchemes.iterator();
1837 while (it.hasNext()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001838 sb.setLength(0);
1839 sb.append(prefix); sb.append("Scheme: \"");
1840 sb.append(it.next()); sb.append("\"");
1841 du.println(sb.toString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001842 }
1843 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001844 if (mDataSchemeSpecificParts != null) {
1845 Iterator<PatternMatcher> it = mDataSchemeSpecificParts.iterator();
1846 while (it.hasNext()) {
1847 PatternMatcher pe = it.next();
1848 sb.setLength(0);
1849 sb.append(prefix); sb.append("Ssp: \"");
1850 sb.append(pe); sb.append("\"");
1851 du.println(sb.toString());
1852 }
1853 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001854 if (mDataAuthorities != null) {
1855 Iterator<AuthorityEntry> it = mDataAuthorities.iterator();
1856 while (it.hasNext()) {
1857 AuthorityEntry ae = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001858 sb.setLength(0);
1859 sb.append(prefix); sb.append("Authority: \"");
1860 sb.append(ae.mHost); sb.append("\": ");
1861 sb.append(ae.mPort);
1862 if (ae.mWild) sb.append(" WILD");
1863 du.println(sb.toString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001864 }
1865 }
1866 if (mDataPaths != null) {
1867 Iterator<PatternMatcher> it = mDataPaths.iterator();
1868 while (it.hasNext()) {
1869 PatternMatcher pe = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001870 sb.setLength(0);
1871 sb.append(prefix); sb.append("Path: \"");
1872 sb.append(pe); sb.append("\"");
1873 du.println(sb.toString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001874 }
1875 }
1876 if (mDataTypes != null) {
1877 Iterator<String> it = mDataTypes.iterator();
1878 while (it.hasNext()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001879 sb.setLength(0);
1880 sb.append(prefix); sb.append("Type: \"");
1881 sb.append(it.next()); sb.append("\"");
1882 du.println(sb.toString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001883 }
1884 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08001885 if (mPriority != 0 || mOrder != 0 || mHasPartialTypes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001886 sb.setLength(0);
1887 sb.append(prefix); sb.append("mPriority="); sb.append(mPriority);
Todd Kennedy6d418b62018-02-22 14:15:18 -08001888 sb.append(", mOrder="); sb.append(mOrder);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001889 sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
1890 du.println(sb.toString());
1891 }
Dianne Hackborn342e6032017-04-13 18:04:31 -07001892 if (getAutoVerify()) {
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08001893 sb.setLength(0);
1894 sb.append(prefix); sb.append("AutoVerify="); sb.append(getAutoVerify());
1895 du.println(sb.toString());
1896 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001897 }
1898
1899 public static final Parcelable.Creator<IntentFilter> CREATOR
1900 = new Parcelable.Creator<IntentFilter>() {
1901 public IntentFilter createFromParcel(Parcel source) {
1902 return new IntentFilter(source);
1903 }
1904
1905 public IntentFilter[] newArray(int size) {
1906 return new IntentFilter[size];
1907 }
1908 };
1909
1910 public final int describeContents() {
1911 return 0;
1912 }
1913
1914 public final void writeToParcel(Parcel dest, int flags) {
1915 dest.writeStringList(mActions);
1916 if (mCategories != null) {
1917 dest.writeInt(1);
1918 dest.writeStringList(mCategories);
1919 } else {
1920 dest.writeInt(0);
1921 }
1922 if (mDataSchemes != null) {
1923 dest.writeInt(1);
1924 dest.writeStringList(mDataSchemes);
1925 } else {
1926 dest.writeInt(0);
1927 }
1928 if (mDataTypes != null) {
1929 dest.writeInt(1);
1930 dest.writeStringList(mDataTypes);
1931 } else {
1932 dest.writeInt(0);
1933 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001934 if (mDataSchemeSpecificParts != null) {
1935 final int N = mDataSchemeSpecificParts.size();
1936 dest.writeInt(N);
1937 for (int i=0; i<N; i++) {
Dianne Hackborn439e9bc82013-06-12 19:13:49 -07001938 mDataSchemeSpecificParts.get(i).writeToParcel(dest, flags);
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07001939 }
1940 } else {
1941 dest.writeInt(0);
1942 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001943 if (mDataAuthorities != null) {
1944 final int N = mDataAuthorities.size();
1945 dest.writeInt(N);
1946 for (int i=0; i<N; i++) {
1947 mDataAuthorities.get(i).writeToParcel(dest);
1948 }
1949 } else {
1950 dest.writeInt(0);
1951 }
1952 if (mDataPaths != null) {
1953 final int N = mDataPaths.size();
1954 dest.writeInt(N);
1955 for (int i=0; i<N; i++) {
Dianne Hackborn439e9bc82013-06-12 19:13:49 -07001956 mDataPaths.get(i).writeToParcel(dest, flags);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001957 }
1958 } else {
1959 dest.writeInt(0);
1960 }
1961 dest.writeInt(mPriority);
1962 dest.writeInt(mHasPartialTypes ? 1 : 0);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08001963 dest.writeInt(getAutoVerify() ? 1 : 0);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07001964 dest.writeInt(mInstantAppVisibility);
Todd Kennedy6d418b62018-02-22 14:15:18 -08001965 dest.writeInt(mOrder);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001966 }
1967
1968 /**
1969 * For debugging -- perform a check on the filter, return true if it passed
1970 * or false if it failed.
1971 *
1972 * {@hide}
1973 */
1974 public boolean debugCheck() {
1975 return true;
1976
1977 // This code looks for intent filters that do not specify data.
1978 /*
1979 if (mActions != null && mActions.size() == 1
1980 && mActions.contains(Intent.ACTION_MAIN)) {
1981 return true;
1982 }
1983
1984 if (mDataTypes == null && mDataSchemes == null) {
1985 Log.w("IntentFilter", "QUESTIONABLE INTENT FILTER:");
1986 dump(Log.WARN, "IntentFilter", " ");
1987 return false;
1988 }
1989
1990 return true;
1991 */
1992 }
1993
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001994 /** @hide */
1995 public IntentFilter(Parcel source) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001996 mActions = new ArrayList<String>();
1997 source.readStringList(mActions);
1998 if (source.readInt() != 0) {
1999 mCategories = new ArrayList<String>();
2000 source.readStringList(mCategories);
2001 }
2002 if (source.readInt() != 0) {
2003 mDataSchemes = new ArrayList<String>();
2004 source.readStringList(mDataSchemes);
2005 }
2006 if (source.readInt() != 0) {
2007 mDataTypes = new ArrayList<String>();
2008 source.readStringList(mDataTypes);
2009 }
2010 int N = source.readInt();
2011 if (N > 0) {
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07002012 mDataSchemeSpecificParts = new ArrayList<PatternMatcher>(N);
2013 for (int i=0; i<N; i++) {
2014 mDataSchemeSpecificParts.add(new PatternMatcher(source));
2015 }
2016 }
2017 N = source.readInt();
2018 if (N > 0) {
2019 mDataAuthorities = new ArrayList<AuthorityEntry>(N);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002020 for (int i=0; i<N; i++) {
2021 mDataAuthorities.add(new AuthorityEntry(source));
2022 }
2023 }
2024 N = source.readInt();
2025 if (N > 0) {
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07002026 mDataPaths = new ArrayList<PatternMatcher>(N);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002027 for (int i=0; i<N; i++) {
2028 mDataPaths.add(new PatternMatcher(source));
2029 }
2030 }
2031 mPriority = source.readInt();
2032 mHasPartialTypes = source.readInt() > 0;
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08002033 setAutoVerify(source.readInt() > 0);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07002034 setVisibilityToInstantApp(source.readInt());
Todd Kennedy6d418b62018-02-22 14:15:18 -08002035 mOrder = source.readInt();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002036 }
2037
2038 private final boolean findMimeType(String type) {
2039 final ArrayList<String> t = mDataTypes;
2040
2041 if (type == null) {
2042 return false;
2043 }
2044
2045 if (t.contains(type)) {
2046 return true;
2047 }
2048
2049 // Deal with an Intent wanting to match every type in the IntentFilter.
2050 final int typeLength = type.length();
2051 if (typeLength == 3 && type.equals("*/*")) {
2052 return !t.isEmpty();
2053 }
2054
2055 // Deal with this IntentFilter wanting to match every Intent type.
2056 if (mHasPartialTypes && t.contains("*")) {
2057 return true;
2058 }
2059
2060 final int slashpos = type.indexOf('/');
2061 if (slashpos > 0) {
2062 if (mHasPartialTypes && t.contains(type.substring(0, slashpos))) {
2063 return true;
2064 }
2065 if (typeLength == slashpos+2 && type.charAt(slashpos+1) == '*') {
2066 // Need to look through all types for one that matches
2067 // our base...
Jeff Brown2c376fc2011-01-28 17:34:01 -08002068 final int numTypes = t.size();
2069 for (int i = 0; i < numTypes; i++) {
2070 final String v = t.get(i);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002071 if (type.regionMatches(0, v, 0, slashpos+1)) {
2072 return true;
2073 }
2074 }
2075 }
2076 }
2077
2078 return false;
2079 }
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08002080
2081 /**
2082 * @hide
2083 */
2084 public ArrayList<String> getHostsList() {
2085 ArrayList<String> result = new ArrayList<>();
2086 Iterator<IntentFilter.AuthorityEntry> it = authoritiesIterator();
2087 if (it != null) {
2088 while (it.hasNext()) {
2089 IntentFilter.AuthorityEntry entry = it.next();
2090 result.add(entry.getHost());
2091 }
2092 }
2093 return result;
2094 }
2095
2096 /**
2097 * @hide
2098 */
2099 public String[] getHosts() {
2100 ArrayList<String> list = getHostsList();
2101 return list.toArray(new String[list.size()]);
2102 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002103}