1/* 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 17package android.content.pm; 18 19import android.content.IntentFilter; 20import android.graphics.drawable.Drawable; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.text.TextUtils; 24import android.util.Printer; 25 26import java.text.Collator; 27import java.util.Comparator; 28 29/** 30 * Information that is returned from resolving an intent 31 * against an IntentFilter. This partially corresponds to 32 * information collected from the AndroidManifest.xml's 33 * <intent> tags. 34 */ 35public class ResolveInfo implements Parcelable { 36 /** 37 * The activity or broadcast receiver that corresponds to this resolution match, 38 * if this resolution is for an activity or broadcast receiver. One and only one of this and 39 * serviceInfo must be non-null. 40 */ 41 public ActivityInfo activityInfo; 42 43 /** 44 * The service that corresponds to this resolution match, if this 45 * resolution is for a service. One and only one of this and 46 * activityInfo must be non-null. 47 */ 48 public ServiceInfo serviceInfo; 49 50 /** 51 * The IntentFilter that was matched for this ResolveInfo. 52 */ 53 public IntentFilter filter; 54 55 /** 56 * The declared priority of this match. Comes from the "priority" 57 * attribute or, if not set, defaults to 0. Higher values are a higher 58 * priority. 59 */ 60 public int priority; 61 62 /** 63 * Order of result according to the user's preference. If the user 64 * has not set a preference for this result, the value is 0; higher 65 * values are a higher priority. 66 */ 67 public int preferredOrder; 68 69 /** 70 * The system's evaluation of how well the activity matches the 71 * IntentFilter. This is a match constant, a combination of 72 * {@link IntentFilter#MATCH_CATEGORY_MASK IntentFilter.MATCH_CATEGORY_MASK} 73 * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}. 74 */ 75 public int match; 76 77 /** 78 * Only set when returned by 79 * {@link PackageManager#queryIntentActivityOptions}, this tells you 80 * which of the given specific intents this result came from. 0 is the 81 * first in the list, < 0 means it came from the generic Intent query. 82 */ 83 public int specificIndex = -1; 84 85 /** 86 * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it 87 * would like to be considered a default action that the user can 88 * perform on this data. 89 */ 90 public boolean isDefault; 91 92 /** 93 * A string resource identifier (in the package's resources) of this 94 * match's label. From the "label" attribute or, if not set, 0. 95 */ 96 public int labelRes; 97 98 /** 99 * The actual string retrieve from <var>labelRes</var> or null if none 100 * was provided. 101 */ 102 public CharSequence nonLocalizedLabel; 103 104 /** 105 * A drawable resource identifier (in the package's resources) of this 106 * match's icon. From the "icon" attribute or, if not set, 0. 107 */ 108 public int icon; 109 110 /** 111 * Optional -- if non-null, the {@link #labelRes} and {@link #icon} 112 * resources will be loaded from this package, rather than the one 113 * containing the resolved component. 114 */ 115 public String resolvePackageName; 116 117 /** 118 * @hide Target comes from system process? 119 */ 120 public boolean system; 121 122 /** 123 * Retrieve the current textual label associated with this resolution. This 124 * will call back on the given PackageManager to load the label from 125 * the application. 126 * 127 * @param pm A PackageManager from which the label can be loaded; usually 128 * the PackageManager from which you originally retrieved this item. 129 * 130 * @return Returns a CharSequence containing the resolutions's label. If the 131 * item does not have a label, its name is returned. 132 */ 133 public CharSequence loadLabel(PackageManager pm) { 134 if (nonLocalizedLabel != null) { 135 return nonLocalizedLabel; 136 } 137 CharSequence label; 138 if (resolvePackageName != null && labelRes != 0) { 139 label = pm.getText(resolvePackageName, labelRes, null); 140 if (label != null) { 141 return label.toString().trim(); 142 } 143 } 144 ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; 145 ApplicationInfo ai = ci.applicationInfo; 146 if (labelRes != 0) { 147 label = pm.getText(ci.packageName, labelRes, ai); 148 if (label != null) { 149 return label.toString().trim(); 150 } 151 } 152 153 CharSequence data = ci.loadLabel(pm); 154 // Make the data safe 155 if (data != null) data = data.toString().trim(); 156 return data; 157 } 158 159 /** 160 * Retrieve the current graphical icon associated with this resolution. This 161 * will call back on the given PackageManager to load the icon from 162 * the application. 163 * 164 * @param pm A PackageManager from which the icon can be loaded; usually 165 * the PackageManager from which you originally retrieved this item. 166 * 167 * @return Returns a Drawable containing the resolution's icon. If the 168 * item does not have an icon, the default activity icon is returned. 169 */ 170 public Drawable loadIcon(PackageManager pm) { 171 Drawable dr; 172 if (resolvePackageName != null && icon != 0) { 173 dr = pm.getDrawable(resolvePackageName, icon, null); 174 if (dr != null) { 175 return dr; 176 } 177 } 178 ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; 179 ApplicationInfo ai = ci.applicationInfo; 180 if (icon != 0) { 181 dr = pm.getDrawable(ci.packageName, icon, ai); 182 if (dr != null) { 183 return dr; 184 } 185 } 186 return ci.loadIcon(pm); 187 } 188 189 /** 190 * Return the icon resource identifier to use for this match. If the 191 * match defines an icon, that is used; else if the activity defines 192 * an icon, that is used; else, the application icon is used. 193 * 194 * @return The icon associated with this match. 195 */ 196 public final int getIconResource() { 197 if (icon != 0) return icon; 198 if (activityInfo != null) return activityInfo.getIconResource(); 199 if (serviceInfo != null) return serviceInfo.getIconResource(); 200 return 0; 201 } 202 203 public void dump(Printer pw, String prefix) { 204 if (filter != null) { 205 pw.println(prefix + "Filter:"); 206 filter.dump(pw, prefix + " "); 207 } 208 pw.println(prefix + "priority=" + priority 209 + " preferredOrder=" + preferredOrder 210 + " match=0x" + Integer.toHexString(match) 211 + " specificIndex=" + specificIndex 212 + " isDefault=" + isDefault); 213 if (resolvePackageName != null) { 214 pw.println(prefix + "resolvePackageName=" + resolvePackageName); 215 } 216 if (labelRes != 0 || nonLocalizedLabel != null || icon != 0) { 217 pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) 218 + " nonLocalizedLabel=" + nonLocalizedLabel 219 + " icon=0x" + Integer.toHexString(icon)); 220 } 221 if (activityInfo != null) { 222 pw.println(prefix + "ActivityInfo:"); 223 activityInfo.dump(pw, prefix + " "); 224 } else if (serviceInfo != null) { 225 pw.println(prefix + "ServiceInfo:"); 226 serviceInfo.dump(pw, prefix + " "); 227 } 228 } 229 230 public ResolveInfo() { 231 } 232 233 public ResolveInfo(ResolveInfo orig) { 234 activityInfo = orig.activityInfo; 235 serviceInfo = orig.serviceInfo; 236 filter = orig.filter; 237 priority = orig.priority; 238 preferredOrder = orig.preferredOrder; 239 match = orig.match; 240 specificIndex = orig.specificIndex; 241 labelRes = orig.labelRes; 242 nonLocalizedLabel = orig.nonLocalizedLabel; 243 icon = orig.icon; 244 resolvePackageName = orig.resolvePackageName; 245 system = orig.system; 246 } 247 248 public String toString() { 249 ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; 250 return "ResolveInfo{" 251 + Integer.toHexString(System.identityHashCode(this)) 252 + " " + ci.name + " p=" + priority + " o=" 253 + preferredOrder + " m=0x" + Integer.toHexString(match) + "}"; 254 } 255 256 public int describeContents() { 257 return 0; 258 } 259 260 public void writeToParcel(Parcel dest, int parcelableFlags) { 261 if (activityInfo != null) { 262 dest.writeInt(1); 263 activityInfo.writeToParcel(dest, parcelableFlags); 264 } else if (serviceInfo != null) { 265 dest.writeInt(2); 266 serviceInfo.writeToParcel(dest, parcelableFlags); 267 } else { 268 dest.writeInt(0); 269 } 270 if (filter != null) { 271 dest.writeInt(1); 272 filter.writeToParcel(dest, parcelableFlags); 273 } else { 274 dest.writeInt(0); 275 } 276 dest.writeInt(priority); 277 dest.writeInt(preferredOrder); 278 dest.writeInt(match); 279 dest.writeInt(specificIndex); 280 dest.writeInt(labelRes); 281 TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); 282 dest.writeInt(icon); 283 dest.writeString(resolvePackageName); 284 dest.writeInt(system ? 1 : 0); 285 } 286 287 public static final Creator<ResolveInfo> CREATOR 288 = new Creator<ResolveInfo>() { 289 public ResolveInfo createFromParcel(Parcel source) { 290 return new ResolveInfo(source); 291 } 292 public ResolveInfo[] newArray(int size) { 293 return new ResolveInfo[size]; 294 } 295 }; 296 297 private ResolveInfo(Parcel source) { 298 switch (source.readInt()) { 299 case 1: 300 activityInfo = ActivityInfo.CREATOR.createFromParcel(source); 301 serviceInfo = null; 302 break; 303 case 2: 304 serviceInfo = ServiceInfo.CREATOR.createFromParcel(source); 305 activityInfo = null; 306 break; 307 default: 308 activityInfo = null; 309 serviceInfo = null; 310 break; 311 } 312 if (source.readInt() != 0) { 313 filter = IntentFilter.CREATOR.createFromParcel(source); 314 } 315 priority = source.readInt(); 316 preferredOrder = source.readInt(); 317 match = source.readInt(); 318 specificIndex = source.readInt(); 319 labelRes = source.readInt(); 320 nonLocalizedLabel 321 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 322 icon = source.readInt(); 323 resolvePackageName = source.readString(); 324 system = source.readInt() != 0; 325 } 326 327 public static class DisplayNameComparator 328 implements Comparator<ResolveInfo> { 329 public DisplayNameComparator(PackageManager pm) { 330 mPM = pm; 331 } 332 333 public final int compare(ResolveInfo a, ResolveInfo b) { 334 CharSequence sa = a.loadLabel(mPM); 335 if (sa == null) sa = a.activityInfo.name; 336 CharSequence sb = b.loadLabel(mPM); 337 if (sb == null) sb = b.activityInfo.name; 338 339 return sCollator.compare(sa.toString(), sb.toString()); 340 } 341 342 private final Collator sCollator = Collator.getInstance(); 343 private PackageManager mPM; 344 } 345} 346