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.res.XmlResourceParser;
20
21import android.graphics.drawable.Drawable;
22import android.os.Bundle;
23import android.os.Parcel;
24import android.text.TextUtils;
25import android.util.Printer;
26
27import java.text.Collator;
28import java.util.Comparator;
29
30/**
31 * Base class containing information common to all package items held by
32 * the package manager.  This provides a very common basic set of attributes:
33 * a label, icon, and meta-data.  This class is not intended
34 * to be used by itself; it is simply here to share common definitions
35 * between all items returned by the package manager.  As such, it does not
36 * itself implement Parcelable, but does provide convenience methods to assist
37 * in the implementation of Parcelable in subclasses.
38 */
39public class PackageItemInfo {
40    /**
41     * Public name of this item. From the "android:name" attribute.
42     */
43    public String name;
44
45    /**
46     * Name of the package that this item is in.
47     */
48    public String packageName;
49
50    /**
51     * A string resource identifier (in the package's resources) of this
52     * component's label.  From the "label" attribute or, if not set, 0.
53     */
54    public int labelRes;
55
56    /**
57     * The string provided in the AndroidManifest file, if any.  You
58     * probably don't want to use this.  You probably want
59     * {@link PackageManager#getApplicationLabel}
60     */
61    public CharSequence nonLocalizedLabel;
62
63    /**
64     * A drawable resource identifier (in the package's resources) of this
65     * component's icon.  From the "icon" attribute or, if not set, 0.
66     */
67    public int icon;
68
69    /**
70     * A drawable resource identifier (in the package's resources) of this
71     * component's logo. Logos may be larger/wider than icons and are
72     * displayed by certain UI elements in place of a name or name/icon
73     * combination. From the "logo" attribute or, if not set, 0.
74     */
75    public int logo;
76
77    /**
78     * Additional meta-data associated with this component.  This field
79     * will only be filled in if you set the
80     * {@link PackageManager#GET_META_DATA} flag when requesting the info.
81     */
82    public Bundle metaData;
83
84    public PackageItemInfo() {
85    }
86
87    public PackageItemInfo(PackageItemInfo orig) {
88        name = orig.name;
89        if (name != null) name = name.trim();
90        packageName = orig.packageName;
91        labelRes = orig.labelRes;
92        nonLocalizedLabel = orig.nonLocalizedLabel;
93        if (nonLocalizedLabel != null) nonLocalizedLabel = nonLocalizedLabel.toString().trim();
94        icon = orig.icon;
95        logo = orig.logo;
96        metaData = orig.metaData;
97    }
98
99    /**
100     * Retrieve the current textual label associated with this item.  This
101     * will call back on the given PackageManager to load the label from
102     * the application.
103     *
104     * @param pm A PackageManager from which the label can be loaded; usually
105     * the PackageManager from which you originally retrieved this item.
106     *
107     * @return Returns a CharSequence containing the item's label.  If the
108     * item does not have a label, its name is returned.
109     */
110    public CharSequence loadLabel(PackageManager pm) {
111        if (nonLocalizedLabel != null) {
112            return nonLocalizedLabel;
113        }
114        if (labelRes != 0) {
115            CharSequence label = pm.getText(packageName, labelRes, getApplicationInfo());
116            if (label != null) {
117                return label.toString().trim();
118            }
119        }
120        if (name != null) {
121            return name;
122        }
123        return packageName;
124    }
125
126    /**
127     * Retrieve the current graphical icon associated with this item.  This
128     * will call back on the given PackageManager to load the icon from
129     * the application.
130     *
131     * @param pm A PackageManager from which the icon can be loaded; usually
132     * the PackageManager from which you originally retrieved this item.
133     *
134     * @return Returns a Drawable containing the item's icon.  If the
135     * item does not have an icon, the item's default icon is returned
136     * such as the default activity icon.
137     */
138    public Drawable loadIcon(PackageManager pm) {
139        if (icon != 0) {
140            Drawable dr = pm.getDrawable(packageName, icon, getApplicationInfo());
141            if (dr != null) {
142                return dr;
143            }
144        }
145        return loadDefaultIcon(pm);
146    }
147
148    /**
149     * Retrieve the default graphical icon associated with this item.
150     *
151     * @param pm A PackageManager from which the icon can be loaded; usually
152     * the PackageManager from which you originally retrieved this item.
153     *
154     * @return Returns a Drawable containing the item's default icon
155     * such as the default activity icon.
156     *
157     * @hide
158     */
159    protected Drawable loadDefaultIcon(PackageManager pm) {
160        return pm.getDefaultActivityIcon();
161    }
162
163    /**
164     * Retrieve the current graphical logo associated with this item. This
165     * will call back on the given PackageManager to load the logo from
166     * the application.
167     *
168     * @param pm A PackageManager from which the logo can be loaded; usually
169     * the PackageManager from which you originally retrieved this item.
170     *
171     * @return Returns a Drawable containing the item's logo. If the item
172     * does not have a logo, this method will return null.
173     */
174    public Drawable loadLogo(PackageManager pm) {
175        if (logo != 0) {
176            Drawable d = pm.getDrawable(packageName, logo, getApplicationInfo());
177            if (d != null) {
178                return d;
179            }
180        }
181        return loadDefaultLogo(pm);
182    }
183
184    /**
185     * Retrieve the default graphical logo associated with this item.
186     *
187     * @param pm A PackageManager from which the logo can be loaded; usually
188     * the PackageManager from which you originally retrieved this item.
189     *
190     * @return Returns a Drawable containing the item's default logo
191     * or null if no default logo is available.
192     *
193     * @hide
194     */
195    protected Drawable loadDefaultLogo(PackageManager pm) {
196        return null;
197    }
198
199    /**
200     * Load an XML resource attached to the meta-data of this item.  This will
201     * retrieved the name meta-data entry, and if defined call back on the
202     * given PackageManager to load its XML file from the application.
203     *
204     * @param pm A PackageManager from which the XML can be loaded; usually
205     * the PackageManager from which you originally retrieved this item.
206     * @param name Name of the meta-date you would like to load.
207     *
208     * @return Returns an XmlPullParser you can use to parse the XML file
209     * assigned as the given meta-data.  If the meta-data name is not defined
210     * or the XML resource could not be found, null is returned.
211     */
212    public XmlResourceParser loadXmlMetaData(PackageManager pm, String name) {
213        if (metaData != null) {
214            int resid = metaData.getInt(name);
215            if (resid != 0) {
216                return pm.getXml(packageName, resid, getApplicationInfo());
217            }
218        }
219        return null;
220    }
221
222    protected void dumpFront(Printer pw, String prefix) {
223        if (name != null) {
224            pw.println(prefix + "name=" + name);
225        }
226        pw.println(prefix + "packageName=" + packageName);
227        if (labelRes != 0 || nonLocalizedLabel != null || icon != 0) {
228            pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
229                    + " nonLocalizedLabel=" + nonLocalizedLabel
230                    + " icon=0x" + Integer.toHexString(icon));
231        }
232    }
233
234    protected void dumpBack(Printer pw, String prefix) {
235        // no back here
236    }
237
238    public void writeToParcel(Parcel dest, int parcelableFlags) {
239        dest.writeString(name);
240        dest.writeString(packageName);
241        dest.writeInt(labelRes);
242        TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
243        dest.writeInt(icon);
244        dest.writeInt(logo);
245        dest.writeBundle(metaData);
246    }
247
248    protected PackageItemInfo(Parcel source) {
249        name = source.readString();
250        packageName = source.readString();
251        labelRes = source.readInt();
252        nonLocalizedLabel
253                = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
254        icon = source.readInt();
255        logo = source.readInt();
256        metaData = source.readBundle();
257    }
258
259    /**
260     * Get the ApplicationInfo for the application to which this item belongs,
261     * if available, otherwise returns null.
262     *
263     * @return Returns the ApplicationInfo of this item, or null if not known.
264     *
265     * @hide
266     */
267    protected ApplicationInfo getApplicationInfo() {
268        return null;
269    }
270
271    public static class DisplayNameComparator
272            implements Comparator<PackageItemInfo> {
273        public DisplayNameComparator(PackageManager pm) {
274            mPM = pm;
275        }
276
277        public final int compare(PackageItemInfo aa, PackageItemInfo ab) {
278            CharSequence  sa = aa.loadLabel(mPM);
279            if (sa == null) sa = aa.name;
280            CharSequence  sb = ab.loadLabel(mPM);
281            if (sb == null) sb = ab.name;
282            return sCollator.compare(sa.toString(), sb.toString());
283        }
284
285        private final Collator   sCollator = Collator.getInstance();
286        private PackageManager   mPM;
287    }
288}
289