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 static android.text.TextUtils.SAFE_STRING_FLAG_FIRST_LINE; 20 import static android.text.TextUtils.SAFE_STRING_FLAG_SINGLE_LINE; 21 import static android.text.TextUtils.SAFE_STRING_FLAG_TRIM; 22 import static android.text.TextUtils.makeSafeForPresentation; 23 24 import android.annotation.FloatRange; 25 import android.annotation.NonNull; 26 import android.annotation.SystemApi; 27 import android.content.res.XmlResourceParser; 28 import android.graphics.drawable.Drawable; 29 import android.os.Bundle; 30 import android.os.Parcel; 31 import android.os.UserHandle; 32 import android.text.TextUtils; 33 import android.util.Printer; 34 import android.util.proto.ProtoOutputStream; 35 36 import com.android.internal.util.Preconditions; 37 38 import java.text.Collator; 39 import java.util.Comparator; 40 41 /** 42 * Base class containing information common to all package items held by 43 * the package manager. This provides a very common basic set of attributes: 44 * a label, icon, and meta-data. This class is not intended 45 * to be used by itself; it is simply here to share common definitions 46 * between all items returned by the package manager. As such, it does not 47 * itself implement Parcelable, but does provide convenience methods to assist 48 * in the implementation of Parcelable in subclasses. 49 */ 50 public class PackageItemInfo { 51 /** The maximum length of a safe label, in characters */ 52 private static final int MAX_SAFE_LABEL_LENGTH = 50000; 53 54 /** @hide */ 55 public static final float DEFAULT_MAX_LABEL_SIZE_PX = 500f; 56 57 /** 58 * Remove {@link Character#isWhitespace(int) whitespace} and non-breaking spaces from the edges 59 * of the label. 60 * 61 * @see #loadSafeLabel(PackageManager, float, int) 62 * 63 * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_TRIM} instead 64 * @hide 65 * @removed 66 */ 67 @Deprecated 68 @SystemApi 69 public static final int SAFE_LABEL_FLAG_TRIM = SAFE_STRING_FLAG_TRIM; 70 71 /** 72 * Force entire string into single line of text (no newlines). Cannot be set at the same time as 73 * {@link #SAFE_LABEL_FLAG_FIRST_LINE}. 74 * 75 * @see #loadSafeLabel(PackageManager, float, int) 76 * 77 * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_SINGLE_LINE} instead 78 * @hide 79 * @removed 80 */ 81 @Deprecated 82 @SystemApi 83 public static final int SAFE_LABEL_FLAG_SINGLE_LINE = SAFE_STRING_FLAG_SINGLE_LINE; 84 85 /** 86 * Return only first line of text (truncate at first newline). Cannot be set at the same time as 87 * {@link #SAFE_LABEL_FLAG_SINGLE_LINE}. 88 * 89 * @see #loadSafeLabel(PackageManager, float, int) 90 * 91 * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_FIRST_LINE} instead 92 * @hide 93 * @removed 94 */ 95 @Deprecated 96 @SystemApi 97 public static final int SAFE_LABEL_FLAG_FIRST_LINE = SAFE_STRING_FLAG_FIRST_LINE; 98 99 private static volatile boolean sForceSafeLabels = false; 100 101 /** 102 * Always use {@link #loadSafeLabel safe labels} when calling {@link #loadLabel}. 103 * 104 * @hide 105 */ 106 @SystemApi forceSafeLabels()107 public static void forceSafeLabels() { 108 sForceSafeLabels = true; 109 } 110 111 /** 112 * Public name of this item. From the "android:name" attribute. 113 */ 114 public String name; 115 116 /** 117 * Name of the package that this item is in. 118 */ 119 public String packageName; 120 121 /** 122 * A string resource identifier (in the package's resources) of this 123 * component's label. From the "label" attribute or, if not set, 0. 124 */ 125 public int labelRes; 126 127 /** 128 * The string provided in the AndroidManifest file, if any. You 129 * probably don't want to use this. You probably want 130 * {@link PackageManager#getApplicationLabel} 131 */ 132 public CharSequence nonLocalizedLabel; 133 134 /** 135 * A drawable resource identifier (in the package's resources) of this 136 * component's icon. From the "icon" attribute or, if not set, 0. 137 */ 138 public int icon; 139 140 /** 141 * A drawable resource identifier (in the package's resources) of this 142 * component's banner. From the "banner" attribute or, if not set, 0. 143 */ 144 public int banner; 145 146 /** 147 * A drawable resource identifier (in the package's resources) of this 148 * component's logo. Logos may be larger/wider than icons and are 149 * displayed by certain UI elements in place of a name or name/icon 150 * combination. From the "logo" attribute or, if not set, 0. 151 */ 152 public int logo; 153 154 /** 155 * Additional meta-data associated with this component. This field 156 * will only be filled in if you set the 157 * {@link PackageManager#GET_META_DATA} flag when requesting the info. 158 */ 159 public Bundle metaData; 160 161 /** 162 * If different of UserHandle.USER_NULL, The icon of this item will represent that user. 163 * @hide 164 */ 165 public int showUserIcon; 166 PackageItemInfo()167 public PackageItemInfo() { 168 showUserIcon = UserHandle.USER_NULL; 169 } 170 PackageItemInfo(PackageItemInfo orig)171 public PackageItemInfo(PackageItemInfo orig) { 172 name = orig.name; 173 if (name != null) name = name.trim(); 174 packageName = orig.packageName; 175 labelRes = orig.labelRes; 176 nonLocalizedLabel = orig.nonLocalizedLabel; 177 if (nonLocalizedLabel != null) nonLocalizedLabel = nonLocalizedLabel.toString().trim(); 178 icon = orig.icon; 179 banner = orig.banner; 180 logo = orig.logo; 181 metaData = orig.metaData; 182 showUserIcon = orig.showUserIcon; 183 } 184 185 /** 186 * Retrieve the current textual label associated with this item. This 187 * will call back on the given PackageManager to load the label from 188 * the application. 189 * 190 * @param pm A PackageManager from which the label can be loaded; usually 191 * the PackageManager from which you originally retrieved this item. 192 * 193 * @return Returns a CharSequence containing the item's label. If the 194 * item does not have a label, its name is returned. 195 */ loadLabel(@onNull PackageManager pm)196 public @NonNull CharSequence loadLabel(@NonNull PackageManager pm) { 197 if (sForceSafeLabels) { 198 return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM 199 | SAFE_STRING_FLAG_FIRST_LINE); 200 } else { 201 return loadUnsafeLabel(pm); 202 } 203 } 204 205 /** {@hide} */ loadUnsafeLabel(PackageManager pm)206 public CharSequence loadUnsafeLabel(PackageManager pm) { 207 if (nonLocalizedLabel != null) { 208 return nonLocalizedLabel; 209 } 210 if (labelRes != 0) { 211 CharSequence label = pm.getText(packageName, labelRes, getApplicationInfo()); 212 if (label != null) { 213 return label.toString().trim(); 214 } 215 } 216 if (name != null) { 217 return name; 218 } 219 return packageName; 220 } 221 222 /** 223 * @hide 224 * @deprecated use loadSafeLabel(PackageManager, float, int) instead 225 */ 226 @SystemApi 227 @Deprecated loadSafeLabel(@onNull PackageManager pm)228 public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm) { 229 return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM 230 | SAFE_STRING_FLAG_FIRST_LINE); 231 } 232 233 /** 234 * Calls {@link TextUtils#makeSafeForPresentation} for the label of this item. 235 * 236 * <p>For parameters see {@link TextUtils#makeSafeForPresentation}. 237 * 238 * @hide 239 */ 240 @SystemApi loadSafeLabel(@onNull PackageManager pm, @FloatRange(from = 0) float ellipsizeDip, @TextUtils.SafeStringFlags int flags)241 public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm, 242 @FloatRange(from = 0) float ellipsizeDip, @TextUtils.SafeStringFlags int flags) { 243 Preconditions.checkNotNull(pm); 244 245 return makeSafeForPresentation(loadUnsafeLabel(pm).toString(), MAX_SAFE_LABEL_LENGTH, 246 ellipsizeDip, flags); 247 } 248 249 /** 250 * Retrieve the current graphical icon associated with this item. This 251 * will call back on the given PackageManager to load the icon from 252 * the application. 253 * 254 * @param pm A PackageManager from which the icon can be loaded; usually 255 * the PackageManager from which you originally retrieved this item. 256 * 257 * @return Returns a Drawable containing the item's icon. If the 258 * item does not have an icon, the item's default icon is returned 259 * such as the default activity icon. 260 */ loadIcon(PackageManager pm)261 public Drawable loadIcon(PackageManager pm) { 262 return pm.loadItemIcon(this, getApplicationInfo()); 263 } 264 265 /** 266 * Retrieve the current graphical icon associated with this item without 267 * the addition of a work badge if applicable. 268 * This will call back on the given PackageManager to load the icon from 269 * the application. 270 * 271 * @param pm A PackageManager from which the icon can be loaded; usually 272 * the PackageManager from which you originally retrieved this item. 273 * 274 * @return Returns a Drawable containing the item's icon. If the 275 * item does not have an icon, the item's default icon is returned 276 * such as the default activity icon. 277 */ loadUnbadgedIcon(PackageManager pm)278 public Drawable loadUnbadgedIcon(PackageManager pm) { 279 return pm.loadUnbadgedItemIcon(this, getApplicationInfo()); 280 } 281 282 /** 283 * Retrieve the current graphical banner associated with this item. This 284 * will call back on the given PackageManager to load the banner from 285 * the application. 286 * 287 * @param pm A PackageManager from which the banner can be loaded; usually 288 * the PackageManager from which you originally retrieved this item. 289 * 290 * @return Returns a Drawable containing the item's banner. If the item 291 * does not have a banner, this method will return null. 292 */ loadBanner(PackageManager pm)293 public Drawable loadBanner(PackageManager pm) { 294 if (banner != 0) { 295 Drawable dr = pm.getDrawable(packageName, banner, getApplicationInfo()); 296 if (dr != null) { 297 return dr; 298 } 299 } 300 return loadDefaultBanner(pm); 301 } 302 303 /** 304 * Retrieve the default graphical icon associated with this item. 305 * 306 * @param pm A PackageManager from which the icon can be loaded; usually 307 * the PackageManager from which you originally retrieved this item. 308 * 309 * @return Returns a Drawable containing the item's default icon 310 * such as the default activity icon. 311 * 312 * @hide 313 */ loadDefaultIcon(PackageManager pm)314 public Drawable loadDefaultIcon(PackageManager pm) { 315 return pm.getDefaultActivityIcon(); 316 } 317 318 /** 319 * Retrieve the default graphical banner associated with this item. 320 * 321 * @param pm A PackageManager from which the banner can be loaded; usually 322 * the PackageManager from which you originally retrieved this item. 323 * 324 * @return Returns a Drawable containing the item's default banner 325 * or null if no default logo is available. 326 * 327 * @hide 328 */ loadDefaultBanner(PackageManager pm)329 protected Drawable loadDefaultBanner(PackageManager pm) { 330 return null; 331 } 332 333 /** 334 * Retrieve the current graphical logo associated with this item. This 335 * will call back on the given PackageManager to load the logo from 336 * the application. 337 * 338 * @param pm A PackageManager from which the logo can be loaded; usually 339 * the PackageManager from which you originally retrieved this item. 340 * 341 * @return Returns a Drawable containing the item's logo. If the item 342 * does not have a logo, this method will return null. 343 */ loadLogo(PackageManager pm)344 public Drawable loadLogo(PackageManager pm) { 345 if (logo != 0) { 346 Drawable d = pm.getDrawable(packageName, logo, getApplicationInfo()); 347 if (d != null) { 348 return d; 349 } 350 } 351 return loadDefaultLogo(pm); 352 } 353 354 /** 355 * Retrieve the default graphical logo associated with this item. 356 * 357 * @param pm A PackageManager from which the logo can be loaded; usually 358 * the PackageManager from which you originally retrieved this item. 359 * 360 * @return Returns a Drawable containing the item's default logo 361 * or null if no default logo is available. 362 * 363 * @hide 364 */ loadDefaultLogo(PackageManager pm)365 protected Drawable loadDefaultLogo(PackageManager pm) { 366 return null; 367 } 368 369 /** 370 * Load an XML resource attached to the meta-data of this item. This will 371 * retrieved the name meta-data entry, and if defined call back on the 372 * given PackageManager to load its XML file from the application. 373 * 374 * @param pm A PackageManager from which the XML can be loaded; usually 375 * the PackageManager from which you originally retrieved this item. 376 * @param name Name of the meta-date you would like to load. 377 * 378 * @return Returns an XmlPullParser you can use to parse the XML file 379 * assigned as the given meta-data. If the meta-data name is not defined 380 * or the XML resource could not be found, null is returned. 381 */ loadXmlMetaData(PackageManager pm, String name)382 public XmlResourceParser loadXmlMetaData(PackageManager pm, String name) { 383 if (metaData != null) { 384 int resid = metaData.getInt(name); 385 if (resid != 0) { 386 return pm.getXml(packageName, resid, getApplicationInfo()); 387 } 388 } 389 return null; 390 } 391 392 /** 393 * @hide Flag for dumping: include all details. 394 */ 395 public static final int DUMP_FLAG_DETAILS = 1<<0; 396 397 /** 398 * @hide Flag for dumping: include nested ApplicationInfo. 399 */ 400 public static final int DUMP_FLAG_APPLICATION = 1<<1; 401 402 /** 403 * @hide Flag for dumping: all flags to dump everything. 404 */ 405 public static final int DUMP_FLAG_ALL = DUMP_FLAG_DETAILS | DUMP_FLAG_APPLICATION; 406 dumpFront(Printer pw, String prefix)407 protected void dumpFront(Printer pw, String prefix) { 408 if (name != null) { 409 pw.println(prefix + "name=" + name); 410 } 411 pw.println(prefix + "packageName=" + packageName); 412 if (labelRes != 0 || nonLocalizedLabel != null || icon != 0 || banner != 0) { 413 pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) 414 + " nonLocalizedLabel=" + nonLocalizedLabel 415 + " icon=0x" + Integer.toHexString(icon) 416 + " banner=0x" + Integer.toHexString(banner)); 417 } 418 } 419 dumpBack(Printer pw, String prefix)420 protected void dumpBack(Printer pw, String prefix) { 421 // no back here 422 } 423 writeToParcel(Parcel dest, int parcelableFlags)424 public void writeToParcel(Parcel dest, int parcelableFlags) { 425 dest.writeString(name); 426 dest.writeString(packageName); 427 dest.writeInt(labelRes); 428 TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); 429 dest.writeInt(icon); 430 dest.writeInt(logo); 431 dest.writeBundle(metaData); 432 dest.writeInt(banner); 433 dest.writeInt(showUserIcon); 434 } 435 436 /** 437 * @hide 438 */ writeToProto(ProtoOutputStream proto, long fieldId, int dumpFlags)439 public void writeToProto(ProtoOutputStream proto, long fieldId, int dumpFlags) { 440 long token = proto.start(fieldId); 441 if (name != null) { 442 proto.write(PackageItemInfoProto.NAME, name); 443 } 444 proto.write(PackageItemInfoProto.PACKAGE_NAME, packageName); 445 proto.write(PackageItemInfoProto.LABEL_RES, labelRes); 446 if (nonLocalizedLabel != null) { 447 proto.write(PackageItemInfoProto.NON_LOCALIZED_LABEL, nonLocalizedLabel.toString()); 448 } 449 proto.write(PackageItemInfoProto.ICON, icon); 450 proto.write(PackageItemInfoProto.BANNER, banner); 451 proto.end(token); 452 } 453 PackageItemInfo(Parcel source)454 protected PackageItemInfo(Parcel source) { 455 name = source.readString(); 456 packageName = source.readString(); 457 labelRes = source.readInt(); 458 nonLocalizedLabel 459 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 460 icon = source.readInt(); 461 logo = source.readInt(); 462 metaData = source.readBundle(); 463 banner = source.readInt(); 464 showUserIcon = source.readInt(); 465 } 466 467 /** 468 * Get the ApplicationInfo for the application to which this item belongs, 469 * if available, otherwise returns null. 470 * 471 * @return Returns the ApplicationInfo of this item, or null if not known. 472 * 473 * @hide 474 */ getApplicationInfo()475 protected ApplicationInfo getApplicationInfo() { 476 return null; 477 } 478 479 public static class DisplayNameComparator 480 implements Comparator<PackageItemInfo> { DisplayNameComparator(PackageManager pm)481 public DisplayNameComparator(PackageManager pm) { 482 mPM = pm; 483 } 484 compare(PackageItemInfo aa, PackageItemInfo ab)485 public final int compare(PackageItemInfo aa, PackageItemInfo ab) { 486 CharSequence sa = aa.loadLabel(mPM); 487 if (sa == null) sa = aa.name; 488 CharSequence sb = ab.loadLabel(mPM); 489 if (sb == null) sb = ab.name; 490 return sCollator.compare(sa.toString(), sb.toString()); 491 } 492 493 private final Collator sCollator = Collator.getInstance(); 494 private PackageManager mPM; 495 } 496 } 497