diff options
| -rw-r--r-- | api/current.txt | 7 | ||||
| -rw-r--r-- | core/java/android/app/Notification.java | 2 | ||||
| -rw-r--r-- | core/java/android/appwidget/AppWidgetHost.java | 16 | ||||
| -rw-r--r-- | core/java/android/appwidget/AppWidgetProviderInfo.java | 39 | ||||
| -rw-r--r-- | core/java/android/content/pm/LauncherActivityInfo.java | 3 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 145 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java | 2 | ||||
| -rw-r--r-- | services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java | 11 |
8 files changed, 149 insertions, 76 deletions
diff --git a/api/current.txt b/api/current.txt index 7743a590a4de..e1460f219952 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5834,7 +5834,7 @@ package android.appwidget { field public static final int WIDGET_CATEGORY_RECENTS = 4; // 0x4 field public int autoAdvanceViewId; field public android.content.ComponentName configure; - field public deprecated int icon; + field public int icon; field public int initialKeyguardLayout; field public int initialLayout; field public deprecated java.lang.String label; @@ -5842,7 +5842,7 @@ package android.appwidget { field public int minResizeHeight; field public int minResizeWidth; field public int minWidth; - field public deprecated int previewImage; + field public int previewImage; field public android.content.ComponentName provider; field public int resizeMode; field public int updatePeriodMillis; @@ -22775,7 +22775,8 @@ package android.os { public class UserManager { method public android.os.Bundle getApplicationRestrictions(java.lang.String); - method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle); + method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int); + method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle); method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle); method public long getSerialNumberForUser(android.os.UserHandle); method public int getUserCount(); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 797a0a032a4e..5b36b8bd74fb 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2562,7 +2562,7 @@ public class Notification implements Parcelable // Note: This assumes that the current user can read the profile badge of the // originating user. UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - Drawable badge = userManager.getBadgeForUser(new UserHandle(mOriginatingUserId)); + Drawable badge = userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0); if (badge == null) { return null; } diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index e7b68f56ceff..66a6eb6bfeee 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -32,7 +32,6 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.RemoteViews; @@ -57,7 +56,6 @@ public class AppWidgetHost { private DisplayMetrics mDisplayMetrics; Context mContext; - String mPackageName; Handler mHandler; int mHostId; Callbacks mCallbacks = new Callbacks(); @@ -154,10 +152,7 @@ public class AppWidgetHost { int[] updatedIds; ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>(); try { - if (mPackageName == null) { - mPackageName = mContext.getPackageName(); - } - updatedIds = sService.startListening(mCallbacks, mPackageName, mHostId, + updatedIds = sService.startListening(mCallbacks, mContext.getPackageName(), mHostId, updatedViews); } catch (RemoteException e) { @@ -176,7 +171,7 @@ public class AppWidgetHost { */ public void stopListening() { try { - sService.stopListening(mPackageName, mHostId); + sService.stopListening(mContext.getPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -194,10 +189,7 @@ public class AppWidgetHost { */ public int allocateAppWidgetId() { try { - if (mPackageName == null) { - mPackageName = mContext.getPackageName(); - } - return sService.allocateAppWidgetId(mPackageName, mHostId); + return sService.allocateAppWidgetId(mContext.getPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -326,7 +318,7 @@ public class AppWidgetHost { } RemoteViews views; try { - views = sService.getAppWidgetViews(mPackageName, appWidgetId); + views = sService.getAppWidgetViews(mContext.getPackageName(), appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index e4dad5ab36db..6835368d576f 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -20,13 +20,11 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Resources; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.content.ComponentName; import android.os.UserHandle; -import android.os.UserManager; /** * Describes the meta data for an installed AppWidget provider. The fields in this class @@ -166,10 +164,7 @@ public class AppWidgetProviderInfo implements Parcelable { * * <p>This field corresponds to the <code>android:icon</code> attribute in * the <code><receiver></code> element in the AndroidManifest.xml file. - * - * @deprecated Use {@link #loadIcon(android.content.Context, int)}. */ - @Deprecated public int icon; /** @@ -186,10 +181,7 @@ public class AppWidgetProviderInfo implements Parcelable { * * <p>This field corresponds to the <code>android:previewImage</code> attribute in * the <code><receiver></code> element in the AndroidManifest.xml file. - * - * @deprecated User {@link #loadPreviewImage(android.content.Context, int)}. */ - @Deprecated public int previewImage; /** @@ -271,16 +263,11 @@ public class AppWidgetProviderInfo implements Parcelable { * The loaded icon corresponds to the <code>android:icon</code> attribute in * the <code><receiver></code> element in the AndroidManifest.xml file. * </p> - * <p> - * <strong>Note:</strong> If you care about widgets from different profiles, you - * should use this method to load the icon as the system will apply the correct - * badging when applicable, so the user knows which profile a widget comes from. - * </p> * * @param context Context for accessing resources. * @param density The optional desired density as per * {@link android.util.DisplayMetrics#densityDpi}. - * @return The potentially badged provider icon. + * @return The provider icon. */ public final Drawable loadIcon(Context context, int density) { return loadDrawable(context, density, providerInfo.getIconResource()); @@ -296,19 +283,12 @@ public class AppWidgetProviderInfo implements Parcelable { * The loaded image corresponds to the <code>android:previewImage</code> attribute * in the <code><receiver></code> element in the AndroidManifest.xml file. * </p> - * <p> - * <strong>Note:</strong> If you care about widgets from different profiles, you - * should use this method to load the preview image as the system will apply the - * correct badging when applicable, so the user knows which profile a previewed - * widget comes from. - * </p> * * @param context Context for accessing resources. * @param density The optional desired density as per * {@link android.util.DisplayMetrics#densityDpi}. - * @return The potentially badged widget preview image. + * @return The widget preview image. */ - @SuppressWarnings("deprecation") public final Drawable loadPreviewImage(Context context, int density) { return loadDrawable(context, density, previewImage); } @@ -384,27 +364,16 @@ public class AppWidgetProviderInfo implements Parcelable { try { Resources resources = context.getPackageManager().getResourcesForApplication( providerInfo.applicationInfo); - - final Drawable drawable; if (resourceId > 0) { if (density <= 0) { density = context.getResources().getDisplayMetrics().densityDpi; } - drawable = resources.getDrawableForDensity(resourceId, density); - } else { - drawable = providerInfo.loadIcon(context.getPackageManager()); - } - - if (drawable instanceof BitmapDrawable) { - UserManager userManager = (UserManager) context.getSystemService( - Context.USER_SERVICE); - return userManager.getBadgedDrawableForUser(drawable, getProfile()); + return resources.getDrawableForDensity(resourceId, density); } } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { /* ignore */ } - - return null; + return providerInfo.loadIcon(context.getPackageManager()); } /** diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 5d48868a9a06..0cff08b35266 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -179,8 +179,7 @@ public class LauncherActivityInfo { } if (originalIcon instanceof BitmapDrawable) { - return mUm.getBadgedDrawableForUser( - originalIcon, mUser); + return mUm.getBadgedIconForUser(originalIcon, mUser); } else { Log.e(TAG, "Unable to create badged icon for " + mActivityInfo); } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 13f93a70abcd..04e6227ca11e 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -755,17 +755,50 @@ public class UserManager { /** * If the target user is a managed profile of the calling user or the caller * is itself a managed profile, then this returns a badged copy of the given + * icon to be able to distinguish it from the original icon. For badging an + * arbitrary drawable use {@link #getBadgedDrawableForUser( + * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}. + * <p> + * If the original drawable is a BitmapDrawable and the backing bitmap is + * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading + * is performed in place and the original drawable is returned. + * </p> + * + * @param icon The icon to badge. + * @param user The target user. + * @return A drawable that combines the original icon and a badge as + * determined by the system. + */ + public Drawable getBadgedIconForUser(Drawable icon, UserHandle user) { + final int badgeResId = getBadgeResIdForUser(user.getIdentifier()); + if (badgeResId == 0) { + return icon; + } + Drawable badgeIcon = mContext.getPackageManager() + .getDrawable("system", badgeResId, null); + return getBadgedDrawable(icon, badgeIcon, null, true); + } + + /** + * If the target user is a managed profile of the calling user or the caller + * is itself a managed profile, then this returns a badged copy of the given * icon to be able to distinguish it from the original icon. - * <P> + * <p> * If the original drawable is not a BitmapDrawable, then the original * drawable is returned. - * </P> + * </p> * * @param icon The icon to badge. * @param user The target user. * @return A drawable that combines the original icon and a badge as * determined by the system. + * + * @deprecation Use {@link #getBadgedIconForUser( + * android.graphics.drawable.Drawable, UserHandle)} + * + * @hide */ + @Deprecated public Drawable getBadgedDrawableForUser(Drawable icon, UserHandle user) { int badgeResId = getBadgeResIdForUser(user.getIdentifier()); if (badgeResId == 0) { @@ -773,12 +806,45 @@ public class UserManager { } else { Drawable badgeIcon = mContext.getPackageManager() .getDrawable("system", badgeResId, null); - return getMergedDrawable(icon, badgeIcon); + return getBadgedDrawable(icon, badgeIcon, null, false); } } /** * If the target user is a managed profile of the calling user or the caller + * is itself a managed profile, then this returns a badged copy of the given + * drawable allowing the user to distinguish it from the original drawable. + * The caller can specify the location in the bounds of the drawable to be + * badged where the badge should be applied as well as the density of the + * badge to be used. + * <p> + * If the original drawable is a BitmapDrawable and the backing bitmap is + * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading + * is performed in place and the original drawable is returned. + * </p> + * + * @param badgedDrawable The drawable to badge. + * @param user The target user. + * @param badgeLocation Where in the bounds of the badged drawable to place + * the badge. If not provided, the badge is applied on top of the entire + * drawable being badged. + * @param badgeDensity The optional desired density for the badge as per + * {@link android.util.DisplayMetrics#densityDpi}. If not provided, + * the density of the display is used. + * @return A drawable that combines the original drawable and a badge as + * determined by the system. + */ + public Drawable getBadgedDrawableForUser(Drawable badgedDrawable, UserHandle user, + Rect badgeLocation, int badgeDensity) { + Drawable badgeDrawable = getBadgeForUser(user, badgeDensity); + if (badgeDrawable == null) { + return badgedDrawable; + } + return getBadgedDrawable(badgedDrawable, badgeDrawable, badgeLocation, true); + } + + /** + * If the target user is a managed profile of the calling user or the caller * is itself a managed profile, then this returns a copy of the label with * badging for accessibility services like talkback. E.g. passing in "Email" * and it might return "Work Email" for Email in the work profile. @@ -812,14 +878,20 @@ public class UserManager { * icon to include in a view to distinguish it from the original icon. * * @param user The target user. + * @param density The optional desired density for the badge as per + * {@link android.util.DisplayMetrics#densityDpi}. If not provided + * the density of the current display is used. * @return the drawable or null if no drawable is required. * @hide */ - public Drawable getBadgeForUser(UserHandle user) { + public Drawable getBadgeForUser(UserHandle user, int density) { UserInfo userInfo = getUserIfProfile(user.getIdentifier()); if (userInfo != null && userInfo.isManagedProfile()) { - return Resources.getSystem().getDrawable( - com.android.internal.R.drawable.ic_corp_badge); + if (density <= 0) { + density = mContext.getResources().getDisplayMetrics().densityDpi; + } + return Resources.getSystem().getDrawableForDensity( + com.android.internal.R.drawable.ic_corp_badge, density); } return null; } @@ -847,20 +919,57 @@ public class UserManager { return null; } - private Drawable getMergedDrawable(Drawable icon, Drawable badge) { - final int width = icon.getIntrinsicWidth(); - final int height = icon.getIntrinsicHeight(); - Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); + private Drawable getBadgedDrawable(Drawable badgedDrawable, Drawable badgeDrawable, + Rect badgeLocation, boolean tryBadgeInPlace) { + final int badgedWidth = badgedDrawable.getIntrinsicWidth(); + final int badgedHeight = badgedDrawable.getIntrinsicHeight(); + final boolean canBadgeInPlace = tryBadgeInPlace + && (badgedDrawable instanceof BitmapDrawable) + && ((BitmapDrawable) badgedDrawable).getBitmap().isMutable(); + + final Bitmap bitmap; + if (canBadgeInPlace) { + bitmap = ((BitmapDrawable) badgedDrawable).getBitmap(); + } else { + bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Config.ARGB_8888); + } Canvas canvas = new Canvas(bitmap); - icon.setBounds(0, 0, width, height); - icon.draw(canvas); - badge.setBounds(0, 0, width, height); - badge.draw(canvas); - BitmapDrawable merged = new BitmapDrawable(bitmap); - if (icon instanceof BitmapDrawable) { - merged.setTargetDensity(((BitmapDrawable) icon).getBitmap().getDensity()); + + if (!canBadgeInPlace) { + badgedDrawable.setBounds(0, 0, badgedWidth, badgedHeight); + badgedDrawable.draw(canvas); } - return merged; + + if (badgeLocation != null) { + if (badgeLocation.left < 0 || badgeLocation.top < 0 + || badgeLocation.right > badgedWidth || badgeLocation.bottom > badgedHeight) { + throw new IllegalArgumentException("Badge location " + badgeLocation + + " not in badged drawable bounds " + + new Rect(0, 0, badgedWidth, badgedHeight)); + } + badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height()); + + canvas.save(); + canvas.translate(badgeLocation.left, badgeLocation.top); + badgeDrawable.draw(canvas); + canvas.restore(); + } else { + badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight); + badgeDrawable.draw(canvas); + } + + if (!canBadgeInPlace) { + BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap); + + if (badgedDrawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) badgedDrawable; + mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity()); + } + + return mergedDrawable; + } + + return badgedDrawable; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 0a9e062f2f6e..7ec0cc5862e1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1145,7 +1145,7 @@ public abstract class BaseStatusBar extends SystemUI implements if (profileIcon != null) { Drawable profileDrawable - = mUserManager.getBadgeForUser(entry.notification.getUser()); + = mUserManager.getBadgeForUser(entry.notification.getUser(), 0); if (profileDrawable != null) { profileIcon.setImageDrawable(profileDrawable); profileIcon.setVisibility(View.VISIBLE); diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index bdaf9ecd0cc7..e9d0c46a8502 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -2732,13 +2732,16 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } // Take a note we no longer have state for this user. - final int index = mLoadedUserIds.indexOfKey(userId); - if (index >= 0) { - mLoadedUserIds.removeAt(index); + final int userIndex = mLoadedUserIds.indexOfKey(userId); + if (userIndex >= 0) { + mLoadedUserIds.removeAt(userIndex); } // Remove the widget id counter. - mNextAppWidgetIds.removeAt(userId); + final int nextIdIndex = mNextAppWidgetIds.indexOfKey(userId); + if (nextIdIndex >= 0) { + mNextAppWidgetIds.removeAt(nextIdIndex); + } } } |