From 07330791116513710d879c45b2f095cd314cbfd0 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Tue, 30 Mar 2010 19:57:08 -0700 Subject: [PATCH] Show SD unavailable icon for apps on SD when ejected. This change include a minor refactoring of PackageItemInfo and related classes to eliminate code duplication and to avoid redundant work searching for an ApplicationInfo instance we already have. Bug: b/2537578 Change-Id: Id0794c3f055ea58b943028f7a84abc7dec9d0aac --- core/java/android/app/ContextImpl.java | 57 +----------------- .../android/content/pm/ApplicationInfo.java | 32 +++++++++- .../android/content/pm/ComponentInfo.java | 34 +++++------ .../android/content/pm/PackageItemInfo.java | 38 ++++++++++-- core/java/android/content/pm/ResolveInfo.java | 4 +- .../sym_app_on_sd_unavailable_icon.png | Bin 0 -> 3342 bytes .../sym_app_on_sd_unavailable_icon.png | Bin 0 -> 5433 bytes .../android/server/PackageManagerService.java | 13 ++-- 8 files changed, 90 insertions(+), 88 deletions(-) create mode 100644 core/res/res/drawable-hdpi/sym_app_on_sd_unavailable_icon.png create mode 100644 core/res/res/drawable-mdpi/sym_app_on_sd_unavailable_icon.png diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 74cfbfa08c6a9..b07b690d5bd65 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2148,31 +2148,7 @@ class ContextImpl extends Context { } @Override public Drawable getApplicationIcon(ApplicationInfo info) { - final int icon = info.icon; - if (icon != 0) { - ResourceName name = new ResourceName(info, icon); - Drawable dr = getCachedIcon(name); - if (dr != null) { - return dr; - } - try { - Resources r = getResourcesForApplication(info); - dr = r.getDrawable(icon); - if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x" - + Integer.toHexString(icon) + " from " + r - + ": " + dr); - putCachedIcon(name, dr); - return dr; - } catch (NameNotFoundException e) { - Log.w("PackageManager", "Failure retrieving resources for" - + info.packageName); - } catch (RuntimeException e) { - // If an exception was thrown, fall through to return - // default icon. - Log.w("PackageManager", "Failure retrieving app icon", e); - } - } - return getDefaultActivityIcon(); + return info.loadIcon(this); } @Override public Drawable getApplicationIcon(String packageName) @@ -2413,25 +2389,6 @@ class ContextImpl extends Context { } } - private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) { - CharSequence cs = getCachedString(name); - if (cs != null) { - return cs; - } - try { - Resources r = getResourcesForApplication(app); - cs = r.getText(id); - putCachedString(name, cs); - } catch (NameNotFoundException e) { - Log.w("PackageManager", "Failure retrieving resources for" - + app.packageName); - } catch (RuntimeException e) { - // If an exception was thrown, fall through to return null - Log.w("ApplicationInfo", "Failure retrieving activity name", e); - } - return cs; - } - @Override public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) { @@ -2493,17 +2450,7 @@ class ContextImpl extends Context { @Override public CharSequence getApplicationLabel(ApplicationInfo info) { - if (info.nonLocalizedLabel != null) { - return info.nonLocalizedLabel; - } - final int id = info.labelRes; - if (id != 0) { - CharSequence cs = getLabel(new ResourceName(info, id), info, id); - if (cs != null) { - return cs; - } - } - return info.packageName; + return info.loadLabel(this); } @Override diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 480504df0884f..0a04e5b0df2e3 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -16,6 +16,9 @@ package android.content.pm; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.util.Printer; @@ -496,7 +499,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public CharSequence loadDescription(PackageManager pm) { if (descriptionRes != 0) { - CharSequence label = pm.getText(packageName, descriptionRes, null); + CharSequence label = pm.getText(packageName, descriptionRes, this); if (label != null) { return label; } @@ -514,4 +517,31 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS | FLAG_SUPPORTS_SCREEN_DENSITIES); } + + /** + * @hide + */ + @Override protected Drawable loadDefaultIcon(PackageManager pm) { + if ((flags & FLAG_EXTERNAL_STORAGE) != 0 + && isPackageUnavailable(pm)) { + return Resources.getSystem().getDrawable( + com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon); + } + return pm.getDefaultActivityIcon(); + } + + private boolean isPackageUnavailable(PackageManager pm) { + try { + return pm.getPackageInfo(packageName, 0) == null; + } catch (NameNotFoundException ex) { + return true; + } + } + + /** + * @hide + */ + @Override protected ApplicationInfo getApplicationInfo() { + return this; + } } diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java index 338c62b6c8207..cafe3725ec0a2 100644 --- a/core/java/android/content/pm/ComponentInfo.java +++ b/core/java/android/content/pm/ComponentInfo.java @@ -99,24 +99,6 @@ public class ComponentInfo extends PackageItemInfo { return name; } - @Override public Drawable loadIcon(PackageManager pm) { - ApplicationInfo ai = applicationInfo; - Drawable dr; - if (icon != 0) { - dr = pm.getDrawable(packageName, icon, ai); - if (dr != null) { - return dr; - } - } - if (ai.icon != 0) { - dr = pm.getDrawable(packageName, ai.icon, ai); - if (dr != null) { - return dr; - } - } - return pm.getDefaultActivityIcon(); - } - /** * Return the icon resource identifier to use for this component. If * the component defines an icon, that is used; else, the application @@ -155,7 +137,7 @@ public class ComponentInfo extends PackageItemInfo { dest.writeInt(enabled ? 1 : 0); dest.writeInt(exported ? 1 : 0); } - + protected ComponentInfo(Parcel source) { super(source); applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source); @@ -164,4 +146,18 @@ public class ComponentInfo extends PackageItemInfo { enabled = (source.readInt() != 0); exported = (source.readInt() != 0); } + + /** + * @hide + */ + @Override protected Drawable loadDefaultIcon(PackageManager pm) { + return applicationInfo.loadIcon(pm); + } + + /** + * @hide + */ + @Override protected ApplicationInfo getApplicationInfo() { + return applicationInfo; + } } diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index d666263183b91..14c068006c11f 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -103,7 +103,7 @@ public class PackageItemInfo { return nonLocalizedLabel; } if (labelRes != 0) { - CharSequence label = pm.getText(packageName, labelRes, null); + CharSequence label = pm.getText(packageName, labelRes, getApplicationInfo()); if (label != null) { return label.toString().trim(); } @@ -123,15 +123,31 @@ public class PackageItemInfo { * the PackageManager from which you originally retrieved this item. * * @return Returns a Drawable containing the item's icon. If the - * item does not have an icon, the default activity icon is returned. + * item does not have an icon, the item's default icon is returned + * such as the default activity icon. */ public Drawable loadIcon(PackageManager pm) { if (icon != 0) { - Drawable dr = pm.getDrawable(packageName, icon, null); + Drawable dr = pm.getDrawable(packageName, icon, getApplicationInfo()); if (dr != null) { return dr; } } + return loadDefaultIcon(pm); + } + + /** + * Retrieve the default graphical icon associated with this item. + * + * @param pm A PackageManager from which the icon can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the item's default icon + * such as the default activity icon. + * + * @hide + */ + protected Drawable loadDefaultIcon(PackageManager pm) { return pm.getDefaultActivityIcon(); } @@ -152,7 +168,7 @@ public class PackageItemInfo { if (metaData != null) { int resid = metaData.getInt(name); if (resid != 0) { - return pm.getXml(packageName, resid, null); + return pm.getXml(packageName, resid, getApplicationInfo()); } } return null; @@ -182,7 +198,7 @@ public class PackageItemInfo { dest.writeInt(icon); dest.writeBundle(metaData); } - + protected PackageItemInfo(Parcel source) { name = source.readString(); packageName = source.readString(); @@ -193,6 +209,18 @@ public class PackageItemInfo { metaData = source.readBundle(); } + /** + * Get the ApplicationInfo for the application to which this item belongs, + * if available, otherwise returns null. + * + * @return Returns the ApplicationInfo of this item, or null if not known. + * + * @hide + */ + protected ApplicationInfo getApplicationInfo() { + return null; + } + public static class DisplayNameComparator implements Comparator { public DisplayNameComparator(PackageManager pm) { diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index a35940f6dc965..74e756bbe5a25 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -163,8 +163,6 @@ public class ResolveInfo implements Parcelable { * item does not have an icon, the default activity icon is returned. */ public Drawable loadIcon(PackageManager pm) { - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; - ApplicationInfo ai = ci.applicationInfo; Drawable dr; if (resolvePackageName != null && icon != 0) { dr = pm.getDrawable(resolvePackageName, icon, null); @@ -172,6 +170,8 @@ public class ResolveInfo implements Parcelable { return dr; } } + ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + ApplicationInfo ai = ci.applicationInfo; if (icon != 0) { dr = pm.getDrawable(ci.packageName, icon, ai); if (dr != null) { diff --git a/core/res/res/drawable-hdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/drawable-hdpi/sym_app_on_sd_unavailable_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d915d416ff305cfdef197c906cc846562c600009 GIT binary patch literal 3342 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 Y0RJm9sX=e8y8r+H07*qoM6N<$f(370BLDyZ literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/drawable-mdpi/sym_app_on_sd_unavailable_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..47306683f3748f451fcc82f716624f43dc239f32 GIT binary patch literal 5433 zcmV-96~^j`P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000VPNklo;M$S&==m7NAFcnG^jyyVvI>WfC(sqq@_R;TPVGp-Rr*2?76I&^WdJzrgpcx z1xZ}V%IaQSvu1s_|N6fFh%gNKD>sF|c+-}eT)%!j-QC?xOiXNUZf+zn4;uR9h#O ziUD2MlW)KM_WootNj96Ma*YszFbokw0I*yPRjyratO+4#XlS5RDskk057>4-1kCYO_FsiO`90yI)P*s&62yh$+!!S@)^$+Wd z#UiCr2_ON~EeBa0OyjU}urV)lAK@gy68bSz4r4kJd4Ky}3GC4UJ z&qsR*Ay5>B*49=snGBgs2E#CDYina_YARm4*p*$^B?y9G)hHAl(DOVpnGBCV{y49{ z{yK`HP%IWH7K`}4PoYpCpU*QlH^;7ByLkTj=gDL;6bc2Tlw`A6q?GZx-Me>_N~M^b zoTRC#iNl8vBZMG|wIB#?>MOZvH5VcX0;H7qzK^D9Y}>YtAPCs9WeXD%6C5~jfad0A ze*E!APMtc%Yp=b==FOYAc<~}#U0obFaDa2?&M`VV%KrWP86FwjP?A*DNL?S^;OADt?o#Ouc z@29u7mr|+3@#DvF9EaA{Rt&@7+i$<+g%@7nv(G+b*zbSsA?)!c`wE)e?#47thKGk47#Lvl=FOzj zX|`F8%46f^v zNF;8ufMr>Dp2spFur!R;)zz7UgM%-wU%#H2nHjpex|o=lU~FuRM<0EZLZLu1nPh%` zo|cvtZrr#*cXu}cv$L}}jze>EGlPSJY~8w*mX;R6FyzvuOLTN}kWQy*ZEYo)OcDeE zSFT(^RaF#4`2&p3&(HJl!w>)4vaDRq0+^<077B$ISA*M;mMRZX2?*8vc)9;oWCs7v z=kvLmU8oFQD2jsXy4;C`Z?O}l?AvRc~B4p z!t*@gIF4f5w&J?3;`_b`f?!$SNhXs>DMKmcdO()D4+Q1DbPOaC3DdUi7gbfovaDM^ zyk%KRHk;LkhKBBOUH7o#IE`y?G3TCp?)mQ%Pdu>?Z~!k1!$4cfoVV&quIq|iE~kx; zkJnk2b#Q8Gs&RUHnoXNF5sf1wBXo3huz23GEb8m)qu)k4o!$d90Sjeo1X?Y=SqoBB zYmVb6Gcz-Z(a}*elgTuu(`gEYLVRaL`!6+LC=@VFGyc74)24c06X2G+zhVqTFIa0U zl}ciMem*fdIl0a-46!)ZS#1Y40P{d@#bmBhfVFnVag=N}t7Ws1sH%@ z6-FxykXyAt8GY1Jsifbk_RAJX0y-d;s|RBE41(a6Vn9kM6h%>jAW)(deXV0z08!Cv zv%p%=NKq6F!yuJP5r!f8d|uop3y7Kvnp$H(RaI0~jh|6fmBz+Kf*_#3zn^cu`GyM@ zF2n`P-FM%;rg14H)`UVUu?NLs5z{oOudm1RJW{C?LqkJ+`st_Q>eZ_vpU;b3yLL53 zuCTDM0I=$DskB;IF1xIyYnsN`*chLD@(EK@Q>0QUe*XDq-g@gTF*7qG)~#Eos;ZiJ z?z!h4OQ+N7ZE&HLEl>r%s^L66Jv|YJ!{Fc`{r&wyQ52!7s-Dee8(wgw=)UzAEE z#dY2A?Afy?zx(dH^AQwAT+_8{*HBfJp`jr@{P084=`@bxVB0ol&Ya<$ciy3|ua8tJ z#RCsKfbaXYyU=0*Y9V4XnGBBOV45ZuFJ261XJ>;T2&Ag2QcCGpx}%hmk3RYc(=<79 zGZy_aM%$+m6V7#kbo z^y$;2QmH>r0M~VCXlS6RsfimmZXkr9qoYGfCX?Fb%a<7+A77lI0QrL27U=2ep;#>P)KgC>(>jKrkS>FW83zUOvhrhl} zM+(3E(*Ko#Vy?`n)l~pTtpZ5EE>nrqWkDh