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 that corresponds to this resolution match, if this
     38      * resolution is for an activity.  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      * Retrieve the current textual label associated with this resolution.  This
    119      * will call back on the given PackageManager to load the label from
    120      * the application.
    121      *
    122      * @param pm A PackageManager from which the label can be loaded; usually
    123      * the PackageManager from which you originally retrieved this item.
    124      *
    125      * @return Returns a CharSequence containing the resolutions's label.  If the
    126      * item does not have a label, its name is returned.
    127      */
    128     public CharSequence loadLabel(PackageManager pm) {
    129         if (nonLocalizedLabel != null) {
    130             return nonLocalizedLabel;
    131         }
    132         CharSequence label;
    133         if (resolvePackageName != null && labelRes != 0) {
    134             label = pm.getText(resolvePackageName, labelRes, null);
    135             if (label != null) {
    136                 return label.toString().trim();
    137             }
    138         }
    139         ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
    140         ApplicationInfo ai = ci.applicationInfo;
    141         if (labelRes != 0) {
    142             label = pm.getText(ci.packageName, labelRes, ai);
    143             if (label != null) {
    144                 return label.toString().trim();
    145             }
    146         }
    147 
    148         CharSequence data = ci.loadLabel(pm);
    149         // Make the data safe
    150         if (data != null) data = data.toString().trim();
    151         return data;
    152     }
    153 
    154     /**
    155      * Retrieve the current graphical icon associated with this resolution.  This
    156      * will call back on the given PackageManager to load the icon from
    157      * the application.
    158      *
    159      * @param pm A PackageManager from which the icon can be loaded; usually
    160      * the PackageManager from which you originally retrieved this item.
    161      *
    162      * @return Returns a Drawable containing the resolution's icon.  If the
    163      * item does not have an icon, the default activity icon is returned.
    164      */
    165     public Drawable loadIcon(PackageManager pm) {
    166         Drawable dr;
    167         if (resolvePackageName != null && icon != 0) {
    168             dr = pm.getDrawable(resolvePackageName, icon, null);
    169             if (dr != null) {
    170                 return dr;
    171             }
    172         }
    173         ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
    174         ApplicationInfo ai = ci.applicationInfo;
    175         if (icon != 0) {
    176             dr = pm.getDrawable(ci.packageName, icon, ai);
    177             if (dr != null) {
    178                 return dr;
    179             }
    180         }
    181         return ci.loadIcon(pm);
    182     }
    183 
    184     /**
    185      * Return the icon resource identifier to use for this match.  If the
    186      * match defines an icon, that is used; else if the activity defines
    187      * an icon, that is used; else, the application icon is used.
    188      *
    189      * @return The icon associated with this match.
    190      */
    191     public final int getIconResource() {
    192         if (icon != 0) return icon;
    193         if (activityInfo != null) return activityInfo.getIconResource();
    194         if (serviceInfo != null) return serviceInfo.getIconResource();
    195         return 0;
    196     }
    197 
    198     public void dump(Printer pw, String prefix) {
    199         if (filter != null) {
    200             pw.println(prefix + "Filter:");
    201             filter.dump(pw, prefix + "  ");
    202         }
    203         pw.println(prefix + "priority=" + priority
    204                 + " preferredOrder=" + preferredOrder
    205                 + " match=0x" + Integer.toHexString(match)
    206                 + " specificIndex=" + specificIndex
    207                 + " isDefault=" + isDefault);
    208         if (resolvePackageName != null) {
    209             pw.println(prefix + "resolvePackageName=" + resolvePackageName);
    210         }
    211         if (labelRes != 0 || nonLocalizedLabel != null || icon != 0) {
    212             pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
    213                     + " nonLocalizedLabel=" + nonLocalizedLabel
    214                     + " icon=0x" + Integer.toHexString(icon));
    215         }
    216         if (activityInfo != null) {
    217             pw.println(prefix + "ActivityInfo:");
    218             activityInfo.dump(pw, prefix + "  ");
    219         } else if (serviceInfo != null) {
    220             pw.println(prefix + "ServiceInfo:");
    221             serviceInfo.dump(pw, prefix + "  ");
    222         }
    223     }
    224 
    225     public ResolveInfo() {
    226     }
    227 
    228     public String toString() {
    229         ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
    230         return "ResolveInfo{"
    231             + Integer.toHexString(System.identityHashCode(this))
    232             + " " + ci.name + " p=" + priority + " o="
    233             + preferredOrder + " m=0x" + Integer.toHexString(match) + "}";
    234     }
    235 
    236     public int describeContents() {
    237         return 0;
    238     }
    239 
    240     public void writeToParcel(Parcel dest, int parcelableFlags) {
    241         if (activityInfo != null) {
    242             dest.writeInt(1);
    243             activityInfo.writeToParcel(dest, parcelableFlags);
    244         } else if (serviceInfo != null) {
    245             dest.writeInt(2);
    246             serviceInfo.writeToParcel(dest, parcelableFlags);
    247         } else {
    248             dest.writeInt(0);
    249         }
    250         if (filter != null) {
    251             dest.writeInt(1);
    252             filter.writeToParcel(dest, parcelableFlags);
    253         } else {
    254             dest.writeInt(0);
    255         }
    256         dest.writeInt(priority);
    257         dest.writeInt(preferredOrder);
    258         dest.writeInt(match);
    259         dest.writeInt(specificIndex);
    260         dest.writeInt(labelRes);
    261         TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
    262         dest.writeInt(icon);
    263         dest.writeString(resolvePackageName);
    264     }
    265 
    266     public static final Creator<ResolveInfo> CREATOR
    267             = new Creator<ResolveInfo>() {
    268         public ResolveInfo createFromParcel(Parcel source) {
    269             return new ResolveInfo(source);
    270         }
    271         public ResolveInfo[] newArray(int size) {
    272             return new ResolveInfo[size];
    273         }
    274     };
    275 
    276     private ResolveInfo(Parcel source) {
    277         switch (source.readInt()) {
    278             case 1:
    279                 activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
    280                 serviceInfo = null;
    281                 break;
    282             case 2:
    283                 serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
    284                 activityInfo = null;
    285                 break;
    286             default:
    287                 activityInfo = null;
    288                 serviceInfo = null;
    289                 break;
    290         }
    291         if (source.readInt() != 0) {
    292             filter = IntentFilter.CREATOR.createFromParcel(source);
    293         }
    294         priority = source.readInt();
    295         preferredOrder = source.readInt();
    296         match = source.readInt();
    297         specificIndex = source.readInt();
    298         labelRes = source.readInt();
    299         nonLocalizedLabel
    300                 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
    301         icon = source.readInt();
    302         resolvePackageName = source.readString();
    303     }
    304 
    305     public static class DisplayNameComparator
    306             implements Comparator<ResolveInfo> {
    307         public DisplayNameComparator(PackageManager pm) {
    308             mPM = pm;
    309         }
    310 
    311         public final int compare(ResolveInfo a, ResolveInfo b) {
    312             CharSequence  sa = a.loadLabel(mPM);
    313             if (sa == null) sa = a.activityInfo.name;
    314             CharSequence  sb = b.loadLabel(mPM);
    315             if (sb == null) sb = b.activityInfo.name;
    316 
    317             return sCollator.compare(sa.toString(), sb.toString());
    318         }
    319 
    320         private final Collator   sCollator = Collator.getInstance();
    321         private PackageManager   mPM;
    322     }
    323 }
    324