Home | History | Annotate | Download | only in pm
      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 
     17 package android.content.pm;
     18 
     19 import android.content.IntentFilter;
     20 import android.graphics.drawable.Drawable;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 import android.text.TextUtils;
     24 import android.util.Printer;
     25 
     26 import java.text.Collator;
     27 import 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  */
     35 public 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 String toString() {
    234         ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
    235         return "ResolveInfo{"
    236             + Integer.toHexString(System.identityHashCode(this))
    237             + " " + ci.name + " p=" + priority + " o="
    238             + preferredOrder + " m=0x" + Integer.toHexString(match) + "}";
    239     }
    240 
    241     public int describeContents() {
    242         return 0;
    243     }
    244 
    245     public void writeToParcel(Parcel dest, int parcelableFlags) {
    246         if (activityInfo != null) {
    247             dest.writeInt(1);
    248             activityInfo.writeToParcel(dest, parcelableFlags);
    249         } else if (serviceInfo != null) {
    250             dest.writeInt(2);
    251             serviceInfo.writeToParcel(dest, parcelableFlags);
    252         } else {
    253             dest.writeInt(0);
    254         }
    255         if (filter != null) {
    256             dest.writeInt(1);
    257             filter.writeToParcel(dest, parcelableFlags);
    258         } else {
    259             dest.writeInt(0);
    260         }
    261         dest.writeInt(priority);
    262         dest.writeInt(preferredOrder);
    263         dest.writeInt(match);
    264         dest.writeInt(specificIndex);
    265         dest.writeInt(labelRes);
    266         TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
    267         dest.writeInt(icon);
    268         dest.writeString(resolvePackageName);
    269         dest.writeInt(system ? 1 : 0);
    270     }
    271 
    272     public static final Creator<ResolveInfo> CREATOR
    273             = new Creator<ResolveInfo>() {
    274         public ResolveInfo createFromParcel(Parcel source) {
    275             return new ResolveInfo(source);
    276         }
    277         public ResolveInfo[] newArray(int size) {
    278             return new ResolveInfo[size];
    279         }
    280     };
    281 
    282     private ResolveInfo(Parcel source) {
    283         switch (source.readInt()) {
    284             case 1:
    285                 activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
    286                 serviceInfo = null;
    287                 break;
    288             case 2:
    289                 serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
    290                 activityInfo = null;
    291                 break;
    292             default:
    293                 activityInfo = null;
    294                 serviceInfo = null;
    295                 break;
    296         }
    297         if (source.readInt() != 0) {
    298             filter = IntentFilter.CREATOR.createFromParcel(source);
    299         }
    300         priority = source.readInt();
    301         preferredOrder = source.readInt();
    302         match = source.readInt();
    303         specificIndex = source.readInt();
    304         labelRes = source.readInt();
    305         nonLocalizedLabel
    306                 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
    307         icon = source.readInt();
    308         resolvePackageName = source.readString();
    309         system = source.readInt() != 0;
    310     }
    311 
    312     public static class DisplayNameComparator
    313             implements Comparator<ResolveInfo> {
    314         public DisplayNameComparator(PackageManager pm) {
    315             mPM = pm;
    316         }
    317 
    318         public final int compare(ResolveInfo a, ResolveInfo b) {
    319             CharSequence  sa = a.loadLabel(mPM);
    320             if (sa == null) sa = a.activityInfo.name;
    321             CharSequence  sb = b.loadLabel(mPM);
    322             if (sb == null) sb = b.activityInfo.name;
    323 
    324             return sCollator.compare(sa.toString(), sb.toString());
    325         }
    326 
    327         private final Collator   sCollator = Collator.getInstance();
    328         private PackageManager   mPM;
    329     }
    330 }
    331