blob: 649fdb46367ec907438bb4c442491540708fb6f6 [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2007 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package android.content.pm;
18
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070019import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.IntentFilter;
21import android.graphics.drawable.Drawable;
22import android.os.Parcel;
23import android.os.Parcelable;
Nicolas Prevot88cc3462014-05-14 14:51:48 +010024import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.text.TextUtils;
26import android.util.Printer;
Jeff Sharkey85f5f812013-10-07 10:16:12 -070027import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
29import java.text.Collator;
30import java.util.Comparator;
31
32/**
33 * Information that is returned from resolving an intent
34 * against an IntentFilter. This partially corresponds to
35 * information collected from the AndroidManifest.xml's
36 * <intent> tags.
37 */
38public class ResolveInfo implements Parcelable {
Jeff Sharkey85f5f812013-10-07 10:16:12 -070039 private static final String TAG = "ResolveInfo";
40
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 /**
Jeff Sharkey85f5f812013-10-07 10:16:12 -070042 * The activity or broadcast receiver that corresponds to this resolution
43 * match, if this resolution is for an activity or broadcast receiver.
44 * Exactly one of {@link #activityInfo}, {@link #serviceInfo}, or
45 * {@link #providerInfo} will be non-null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 */
47 public ActivityInfo activityInfo;
48
49 /**
Jeff Sharkey85f5f812013-10-07 10:16:12 -070050 * The service that corresponds to this resolution match, if this resolution
51 * is for a service. Exactly one of {@link #activityInfo},
52 * {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 */
54 public ServiceInfo serviceInfo;
Jeff Sharkey85f5f812013-10-07 10:16:12 -070055
56 /**
57 * The provider that corresponds to this resolution match, if this
58 * resolution is for a provider. Exactly one of {@link #activityInfo},
59 * {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
60 */
61 public ProviderInfo providerInfo;
62
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 /**
64 * The IntentFilter that was matched for this ResolveInfo.
65 */
66 public IntentFilter filter;
67
68 /**
69 * The declared priority of this match. Comes from the "priority"
70 * attribute or, if not set, defaults to 0. Higher values are a higher
71 * priority.
72 */
73 public int priority;
74
75 /**
76 * Order of result according to the user's preference. If the user
77 * has not set a preference for this result, the value is 0; higher
78 * values are a higher priority.
79 */
80 public int preferredOrder;
81
82 /**
83 * The system's evaluation of how well the activity matches the
84 * IntentFilter. This is a match constant, a combination of
85 * {@link IntentFilter#MATCH_CATEGORY_MASK IntentFilter.MATCH_CATEGORY_MASK}
86 * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}.
87 */
88 public int match;
89
90 /**
91 * Only set when returned by
92 * {@link PackageManager#queryIntentActivityOptions}, this tells you
93 * which of the given specific intents this result came from. 0 is the
94 * first in the list, < 0 means it came from the generic Intent query.
95 */
96 public int specificIndex = -1;
97
98 /**
99 * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it
100 * would like to be considered a default action that the user can
101 * perform on this data.
102 */
103 public boolean isDefault;
104
105 /**
106 * A string resource identifier (in the package's resources) of this
107 * match's label. From the "label" attribute or, if not set, 0.
108 */
109 public int labelRes;
110
111 /**
112 * The actual string retrieve from <var>labelRes</var> or null if none
113 * was provided.
114 */
115 public CharSequence nonLocalizedLabel;
116
117 /**
118 * A drawable resource identifier (in the package's resources) of this
119 * match's icon. From the "icon" attribute or, if not set, 0.
120 */
121 public int icon;
122
123 /**
Dianne Hackborneb034652009-09-07 00:49:58 -0700124 * Optional -- if non-null, the {@link #labelRes} and {@link #icon}
125 * resources will be loaded from this package, rather than the one
126 * containing the resolved component.
127 */
128 public String resolvePackageName;
Dianne Hackbornd99b2932011-08-18 14:39:58 -0700129
130 /**
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100131 * If not equal to UserHandle.USER_CURRENT, then the intent will be forwarded to this user.
132 * @hide
133 */
134 public int targetUserId;
135
136 /**
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100137 * @hide
138 */
Nicolas Prevot7f7b0c72014-06-23 15:59:38 +0100139 public boolean noResourceId;
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100140
141 /**
Dianne Hackbornd99b2932011-08-18 14:39:58 -0700142 * @hide Target comes from system process?
143 */
144 public boolean system;
145
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800146 /**
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700147 * @hide Does the associated IntentFilter comes from a Browser ?
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800148 */
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700149 public boolean handleAllWebDataURI;
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -0800150
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700151 private ComponentInfo getComponentInfo() {
152 if (activityInfo != null) return activityInfo;
153 if (serviceInfo != null) return serviceInfo;
154 if (providerInfo != null) return providerInfo;
155 throw new IllegalStateException("Missing ComponentInfo!");
156 }
157
Dianne Hackborneb034652009-09-07 00:49:58 -0700158 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 * Retrieve the current textual label associated with this resolution. This
160 * will call back on the given PackageManager to load the label from
161 * the application.
162 *
163 * @param pm A PackageManager from which the label can be loaded; usually
164 * the PackageManager from which you originally retrieved this item.
165 *
166 * @return Returns a CharSequence containing the resolutions's label. If the
167 * item does not have a label, its name is returned.
168 */
169 public CharSequence loadLabel(PackageManager pm) {
170 if (nonLocalizedLabel != null) {
171 return nonLocalizedLabel;
172 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700173 CharSequence label;
174 if (resolvePackageName != null && labelRes != 0) {
175 label = pm.getText(resolvePackageName, labelRes, null);
176 if (label != null) {
Romain Guy2aba11f2010-03-29 16:03:01 -0700177 return label.toString().trim();
Dianne Hackborneb034652009-09-07 00:49:58 -0700178 }
179 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700180 ComponentInfo ci = getComponentInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 ApplicationInfo ai = ci.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 if (labelRes != 0) {
183 label = pm.getText(ci.packageName, labelRes, ai);
184 if (label != null) {
Romain Guy2aba11f2010-03-29 16:03:01 -0700185 return label.toString().trim();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 }
187 }
Romain Guy2aba11f2010-03-29 16:03:01 -0700188
189 CharSequence data = ci.loadLabel(pm);
190 // Make the data safe
191 if (data != null) data = data.toString().trim();
192 return data;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 }
194
195 /**
196 * Retrieve the current graphical icon associated with this resolution. This
197 * will call back on the given PackageManager to load the icon from
198 * the application.
199 *
200 * @param pm A PackageManager from which the icon can be loaded; usually
201 * the PackageManager from which you originally retrieved this item.
202 *
203 * @return Returns a Drawable containing the resolution's icon. If the
204 * item does not have an icon, the default activity icon is returned.
205 */
206 public Drawable loadIcon(PackageManager pm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 Drawable dr;
Dianne Hackborneb034652009-09-07 00:49:58 -0700208 if (resolvePackageName != null && icon != 0) {
209 dr = pm.getDrawable(resolvePackageName, icon, null);
210 if (dr != null) {
211 return dr;
212 }
213 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700214 ComponentInfo ci = getComponentInfo();
Jeff Brown07330792010-03-30 19:57:08 -0700215 ApplicationInfo ai = ci.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 if (icon != 0) {
217 dr = pm.getDrawable(ci.packageName, icon, ai);
218 if (dr != null) {
219 return dr;
220 }
221 }
222 return ci.loadIcon(pm);
223 }
Ricky Wai1281b182015-04-29 14:57:04 +0100224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 /**
226 * Return the icon resource identifier to use for this match. If the
227 * match defines an icon, that is used; else if the activity defines
228 * an icon, that is used; else, the application icon is used.
Ricky Wai1281b182015-04-29 14:57:04 +0100229 * This function does not check noResourceId flag.
230 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 * @return The icon associated with this match.
232 */
Ricky Wai1281b182015-04-29 14:57:04 +0100233 final int getIconResourceInternal() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 if (icon != 0) return icon;
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700235 final ComponentInfo ci = getComponentInfo();
Nicolas Prevot7f7b0c72014-06-23 15:59:38 +0100236 if (ci != null) {
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100237 return ci.getIconResource();
238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 return 0;
240 }
241
Ricky Wai1281b182015-04-29 14:57:04 +0100242 /**
243 * Return the icon resource identifier to use for this match. If the
244 * match defines an icon, that is used; else if the activity defines
245 * an icon, that is used; else, the application icon is used.
246 *
247 * @return The icon associated with this match.
248 */
249 public final int getIconResource() {
250 if (noResourceId) return 0;
251 return getIconResourceInternal();
252 }
253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 public void dump(Printer pw, String prefix) {
255 if (filter != null) {
256 pw.println(prefix + "Filter:");
257 filter.dump(pw, prefix + " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 }
259 pw.println(prefix + "priority=" + priority
260 + " preferredOrder=" + preferredOrder
261 + " match=0x" + Integer.toHexString(match)
262 + " specificIndex=" + specificIndex
263 + " isDefault=" + isDefault);
Dianne Hackborneb034652009-09-07 00:49:58 -0700264 if (resolvePackageName != null) {
265 pw.println(prefix + "resolvePackageName=" + resolvePackageName);
266 }
267 if (labelRes != 0 || nonLocalizedLabel != null || icon != 0) {
268 pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
269 + " nonLocalizedLabel=" + nonLocalizedLabel
270 + " icon=0x" + Integer.toHexString(icon));
271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 if (activityInfo != null) {
273 pw.println(prefix + "ActivityInfo:");
274 activityInfo.dump(pw, prefix + " ");
275 } else if (serviceInfo != null) {
276 pw.println(prefix + "ServiceInfo:");
Dianne Hackborneb034652009-09-07 00:49:58 -0700277 serviceInfo.dump(pw, prefix + " ");
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700278 } else if (providerInfo != null) {
279 pw.println(prefix + "ProviderInfo:");
280 providerInfo.dump(pw, prefix + " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 }
282 }
283
284 public ResolveInfo() {
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100285 targetUserId = UserHandle.USER_CURRENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 }
287
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700288 public ResolveInfo(ResolveInfo orig) {
289 activityInfo = orig.activityInfo;
290 serviceInfo = orig.serviceInfo;
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700291 providerInfo = orig.providerInfo;
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700292 filter = orig.filter;
293 priority = orig.priority;
294 preferredOrder = orig.preferredOrder;
295 match = orig.match;
296 specificIndex = orig.specificIndex;
297 labelRes = orig.labelRes;
298 nonLocalizedLabel = orig.nonLocalizedLabel;
299 icon = orig.icon;
300 resolvePackageName = orig.resolvePackageName;
301 system = orig.system;
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100302 targetUserId = orig.targetUserId;
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700303 handleAllWebDataURI = orig.handleAllWebDataURI;
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700304 }
305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 public String toString() {
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700307 final ComponentInfo ci = getComponentInfo();
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700308 StringBuilder sb = new StringBuilder(128);
309 sb.append("ResolveInfo{");
310 sb.append(Integer.toHexString(System.identityHashCode(this)));
311 sb.append(' ');
312 ComponentName.appendShortString(sb, ci.packageName, ci.name);
313 if (priority != 0) {
314 sb.append(" p=");
315 sb.append(priority);
316 }
317 if (preferredOrder != 0) {
318 sb.append(" o=");
319 sb.append(preferredOrder);
320 }
321 sb.append(" m=0x");
322 sb.append(Integer.toHexString(match));
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100323 if (targetUserId != UserHandle.USER_CURRENT) {
324 sb.append(" targetUserId=");
325 sb.append(targetUserId);
326 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700327 sb.append('}');
328 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 }
330
331 public int describeContents() {
332 return 0;
333 }
334
335 public void writeToParcel(Parcel dest, int parcelableFlags) {
336 if (activityInfo != null) {
337 dest.writeInt(1);
338 activityInfo.writeToParcel(dest, parcelableFlags);
339 } else if (serviceInfo != null) {
340 dest.writeInt(2);
341 serviceInfo.writeToParcel(dest, parcelableFlags);
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700342 } else if (providerInfo != null) {
343 dest.writeInt(3);
344 providerInfo.writeToParcel(dest, parcelableFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 } else {
346 dest.writeInt(0);
347 }
348 if (filter != null) {
349 dest.writeInt(1);
350 filter.writeToParcel(dest, parcelableFlags);
351 } else {
352 dest.writeInt(0);
353 }
354 dest.writeInt(priority);
355 dest.writeInt(preferredOrder);
356 dest.writeInt(match);
357 dest.writeInt(specificIndex);
358 dest.writeInt(labelRes);
359 TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
360 dest.writeInt(icon);
Dianne Hackborneb034652009-09-07 00:49:58 -0700361 dest.writeString(resolvePackageName);
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100362 dest.writeInt(targetUserId);
Dianne Hackbornd99b2932011-08-18 14:39:58 -0700363 dest.writeInt(system ? 1 : 0);
Nicolas Prevot7f7b0c72014-06-23 15:59:38 +0100364 dest.writeInt(noResourceId ? 1 : 0);
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700365 dest.writeInt(handleAllWebDataURI ? 1 : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 }
367
368 public static final Creator<ResolveInfo> CREATOR
369 = new Creator<ResolveInfo>() {
370 public ResolveInfo createFromParcel(Parcel source) {
371 return new ResolveInfo(source);
372 }
373 public ResolveInfo[] newArray(int size) {
374 return new ResolveInfo[size];
375 }
376 };
377
378 private ResolveInfo(Parcel source) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700379 activityInfo = null;
380 serviceInfo = null;
381 providerInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 switch (source.readInt()) {
383 case 1:
384 activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 break;
386 case 2:
387 serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700388 break;
389 case 3:
390 providerInfo = ProviderInfo.CREATOR.createFromParcel(source);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 break;
392 default:
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700393 Slog.w(TAG, "Missing ComponentInfo!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 break;
395 }
396 if (source.readInt() != 0) {
397 filter = IntentFilter.CREATOR.createFromParcel(source);
398 }
399 priority = source.readInt();
400 preferredOrder = source.readInt();
401 match = source.readInt();
402 specificIndex = source.readInt();
403 labelRes = source.readInt();
404 nonLocalizedLabel
405 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
406 icon = source.readInt();
Dianne Hackborneb034652009-09-07 00:49:58 -0700407 resolvePackageName = source.readString();
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100408 targetUserId = source.readInt();
Dianne Hackbornd99b2932011-08-18 14:39:58 -0700409 system = source.readInt() != 0;
Nicolas Prevot7f7b0c72014-06-23 15:59:38 +0100410 noResourceId = source.readInt() != 0;
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -0700411 handleAllWebDataURI = source.readInt() != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 }
413
414 public static class DisplayNameComparator
415 implements Comparator<ResolveInfo> {
416 public DisplayNameComparator(PackageManager pm) {
417 mPM = pm;
Adam Powell0256c6f2013-05-29 16:42:33 -0700418 mCollator.setStrength(Collator.PRIMARY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 }
420
421 public final int compare(ResolveInfo a, ResolveInfo b) {
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100422 // We want to put the one targeted to another user at the end of the dialog.
423 if (a.targetUserId != UserHandle.USER_CURRENT) {
424 return 1;
425 }
426 if (b.targetUserId != UserHandle.USER_CURRENT) {
427 return -1;
428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 CharSequence sa = a.loadLabel(mPM);
430 if (sa == null) sa = a.activityInfo.name;
431 CharSequence sb = b.loadLabel(mPM);
432 if (sb == null) sb = b.activityInfo.name;
433
Adam Powell0256c6f2013-05-29 16:42:33 -0700434 return mCollator.compare(sa.toString(), sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 }
436
Adam Powell0256c6f2013-05-29 16:42:33 -0700437 private final Collator mCollator = Collator.getInstance();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 private PackageManager mPM;
439 }
440}