From 8a0101bade3f817d925bd931d0b83bc454dedea4 Mon Sep 17 00:00:00 2001 From: Kenny Guy Date: Thu, 8 May 2014 23:34:12 +0100 Subject: [PATCH] Badge notification from managed profiles. Add a method to the UserManager to provide access to bitmap of badge for managed profile. Overlay the icon view in notification templates with the badge from the UserManager. Notifications with custom views won't be badged. Bug: 12641490 Change-Id: I1f2aae927e75fc8a955e4d5bbc3cc81127d87069 (cherry picked from commit 0f4ab980227e8c298bfcd34dd85aad0febad528c) --- core/java/android/app/Notification.java | 26 +++++++++++ core/java/android/os/UserManager.java | 41 +++++++++++++++--- core/res/res/drawable-hdpi/ic_corp_badge.png | Bin 2211 -> 0 bytes core/res/res/drawable-xhdpi/ic_corp_badge.png | Bin 2989 -> 0 bytes .../res/res/drawable-xxhdpi/ic_corp_badge.png | Bin 2285 -> 0 bytes core/res/res/drawable/ic_corp_badge.xml | 34 +++++++++++++++ core/res/res/drawable/ic_corp_icon_badge.xml | 40 +++++++++++++++++ .../notification_template_quantum_base.xml | 9 ++++ ...notification_template_quantum_big_base.xml | 9 ++++ ...notification_template_quantum_big_text.xml | 9 ++++ .../notification_template_quantum_inbox.xml | 9 ++++ core/res/res/values/ids.xml | 1 + core/res/res/values/symbols.xml | 2 + .../systemui/statusbar/BaseStatusBar.java | 19 +++++++- .../statusbar/phone/PhoneStatusBar.java | 1 - 15 files changed, 191 insertions(+), 9 deletions(-) delete mode 100644 core/res/res/drawable-hdpi/ic_corp_badge.png delete mode 100644 core/res/res/drawable-xhdpi/ic_corp_badge.png delete mode 100644 core/res/res/drawable-xxhdpi/ic_corp_badge.png create mode 100644 core/res/res/drawable/ic_corp_badge.xml create mode 100644 core/res/res/drawable/ic_corp_icon_badge.xml diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 8dba1dcc778c6..5ac2a33938556 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -21,7 +21,10 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.session.MediaSessionToken; import android.net.Uri; @@ -32,6 +35,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; @@ -2305,7 +2309,23 @@ public class Notification implements Parcelable return this; } + private Bitmap getProfileBadge() { + UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + Drawable badge = userManager.getBadgeForUser(android.os.Process.myUserHandle()); + if (badge == null) { + return null; + } + final int width = badge.getIntrinsicWidth(); + final int height = badge.getIntrinsicHeight(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + badge.setBounds(0, 0, width, height); + badge.draw(canvas); + return bitmap; + } + private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) { + Bitmap profileIcon = getProfileBadge(); RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); boolean showLine3 = false; boolean showLine2 = false; @@ -2313,6 +2333,12 @@ public class Notification implements Parcelable if (mPriority < PRIORITY_LOW) { // TODO: Low priority presentation } + if (profileIcon != null) { + contentView.setImageViewBitmap(R.id.profile_icon, profileIcon); + contentView.setViewVisibility(R.id.profile_icon, View.VISIBLE); + } else { + contentView.setViewVisibility(R.id.profile_icon, View.GONE); + } if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); processLargeIcon(mLargeIcon, contentView); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index ee219e3d5d368..f7a89ba5452c5 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -690,18 +690,47 @@ 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 drawable to use as a small + * icon to include in a view to distinguish it from the original icon. + * + * @param user The target user. + * @return the drawable or null if no drawable is required. + * @hide + */ + public Drawable getBadgeForUser(UserHandle user) { + UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + if (userInfo != null && userInfo.isManagedProfile()) { + return Resources.getSystem().getDrawable( + com.android.internal.R.drawable.ic_corp_badge); + } + return null; + } + private int getBadgeResIdForUser(int userHandle) { // Return the framework-provided badge. - List userProfiles = getProfiles(getUserHandle()); - for (UserInfo user : userProfiles) { - if (user.id == userHandle - && user.isManagedProfile()) { - return com.android.internal.R.drawable.ic_corp_badge; - } + UserInfo userInfo = getUserIfProfile(userHandle); + if (userInfo != null && userInfo.isManagedProfile()) { + return com.android.internal.R.drawable.ic_corp_icon_badge; } return 0; } + /** + * @return UserInfo for userHandle if it exists and is a profile of the current + * user or null. + */ + private UserInfo getUserIfProfile(int userHandle) { + List userProfiles = getProfiles(getUserHandle()); + for (UserInfo user : userProfiles) { + if (user.id == userHandle) { + return user; + } + } + return null; + } + private Drawable getMergedDrawable(Drawable icon, Drawable badge) { final int width = icon.getIntrinsicWidth(); final int height = icon.getIntrinsicHeight(); diff --git a/core/res/res/drawable-hdpi/ic_corp_badge.png b/core/res/res/drawable-hdpi/ic_corp_badge.png deleted file mode 100644 index f6473757242f67754cf3c1d760dc5edbc7a1ca41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2211 zcmb`Ji9Zt#AIG;jHsp#$$jBAd$R3kn7>q+-I&#tfU;# zkmDD*nVefI$1<}=qWYCb&)@L8zMs$M{rZ0Xf$ulX$pI}csvrsg0K{#qQ7(tP`Nt69 z!~9qfX?zGE-UW>WG>s~494^AXSI{WH!Jnz?fUL~z#E@Bo0A%pU^*MJ4iwB{;815K@Bw%aZe|)m@)* zKj|HAkolbGtVR3sx`2CZtNXv(jSUv7Y_PUd^#BhzP5c%sk13F%oLG%iSrC4cdo`&kC}m9ds30Ne4Z8+z zJ;;itR%i=}+z8;2(KjMdvHNi~e{n2tI1tuXvSR87+9QaxZ)fC{lLmbvH(?~PA|@x< zB)_PB`&Kdgb4d6%YaqM`d_^BOrd-ON5yPHw0&A#^my_>uX;{6tvEoJdA(Gsr<=#L9 z3*{NBGN9Y@13}xhtu&X^Bd&OB#8gX|%^&e>mU=FfNqg!J$$vj}synbIC(Xh$o4sm8 zi-O7yZ

Qr$9F2qTu?6ZkMq<*ab!0umsvfV%T5o%NWV^>GrEWS`@ht7_P_aJe|C@5|Ke+Hiy#Hq74nZJM7w` zv(-Ek{U!S-4AyuBJ59Xz`3KzlldQE)CL{Vpq4Dc&4OUSa%u1qxFPk%)wcYrPbAtiRSB1$@k%EF8~l9hM}%hP)xMwJg>rl!{i7VaT4(i!0zm zrQ9g@@E{5Co=x=^v-I!?5zgwr~p`Znt$9FH%nbSH^2gkXN@S@qZe zJBwJm6$8`Cd6g=j$FksQ&oI}h|EOLAN*H-eQ!y$Q-PK4@sh!>KOFMx~9aqWihgXsp zbV>DexdSFd$1mhMys?bk7WZVEp!nLL!C^<|dz9BjY3N-0@wrwT>;9XOTK_y*a+V?P z`itmB^iF}5_I%*Cj*dT~rr&jX(w*pJ#MTOS1xIuXMRJKApFFU?--IP#YzHR^h2Uwc z-FWilDtB$@aMSgFiEh*1D2<&U7Q2ZtbjkTIsREs7=8)9l^QC88h@tw-HgRfQ*QRwk z~CTRy_@L!Yxc}A zAx*UzPLSJXTWmVj&CgyNy3;24x5&)3Y4YlHMv0K?31^dgr!TY%_&%Cp0WSOs1+q2P zF$>w!mf+7e^L6^O1e;;)AC57D{8-Ip(_amXjF#59Y4ah&(JnSq<{9O?98t`2Gn)RD z3ri&QH+?%1`YWKP)q;m diff --git a/core/res/res/drawable-xhdpi/ic_corp_badge.png b/core/res/res/drawable-xhdpi/ic_corp_badge.png deleted file mode 100644 index 80d848df99127ede2e2b3bdd53a875c423cf60b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2989 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 E2hPSx#sB~S diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml new file mode 100644 index 0000000000000..532571245d55c --- /dev/null +++ b/core/res/res/drawable/ic_corp_badge.xml @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/core/res/res/drawable/ic_corp_icon_badge.xml b/core/res/res/drawable/ic_corp_icon_badge.xml new file mode 100644 index 0000000000000..7bfab4c55a0db --- /dev/null +++ b/core/res/res/drawable/ic_corp_icon_badge.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml index 789bf32e33f7f..4265f9da9d340 100644 --- a/core/res/res/layout/notification_template_quantum_base.xml +++ b/core/res/res/layout/notification_template_quantum_base.xml @@ -120,6 +120,15 @@ android:gravity="center" android:paddingStart="8dp" /> + diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml index 8cb55494d48ca..95a4c82774cd1 100644 --- a/core/res/res/layout/notification_template_quantum_big_base.xml +++ b/core/res/res/layout/notification_template_quantum_big_base.xml @@ -127,6 +127,15 @@ android:gravity="center" android:paddingStart="8dp" /> + + diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml index a071d59fa5968..3851dd3624d40 100644 --- a/core/res/res/layout/notification_template_quantum_inbox.xml +++ b/core/res/res/layout/notification_template_quantum_inbox.xml @@ -249,6 +249,15 @@ android:gravity="center" android:paddingStart="8dp" /> + diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index c966a12b7c9b4..639091e142847 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -23,6 +23,7 @@ + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 61b6a0d92c762..80eceb5ecd66c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -217,6 +217,7 @@ + @@ -1119,6 +1120,7 @@ + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 06cc476d02951..d1484e130bdae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -992,7 +992,10 @@ public abstract class BaseStatusBar extends SystemUI implements title.setText(entry.notification.getPackageName()); } - final ImageView icon = (ImageView) publicViewLocal.findViewById(com.android.internal.R.id.icon); + final ImageView icon = (ImageView) publicViewLocal.findViewById( + com.android.internal.R.id.icon); + final ImageView profileIcon = (ImageView) publicViewLocal.findViewById( + com.android.internal.R.id.profile_icon); final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(), entry.notification.getUser(), @@ -1008,7 +1011,19 @@ public abstract class BaseStatusBar extends SystemUI implements com.android.internal.R.drawable.notification_icon_legacy_bg_inset); } - final TextView text = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.text); + if (profileIcon != null) { + Drawable profileDrawable + = mUserManager.getBadgeForUser(entry.notification.getUser()); + if (profileDrawable != null) { + profileIcon.setImageDrawable(profileDrawable); + profileIcon.setVisibility(View.VISIBLE); + } else { + profileIcon.setVisibility(View.GONE); + } + } + + final TextView text = (TextView) publicViewLocal.findViewById( + com.android.internal.R.id.text); text.setText("Unlock your device to see this notification."); // TODO: fill out "time" as well diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index e55de947c75d4..d9005d89925b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1185,7 +1185,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, Entry ent = mNotificationData.get(i); if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue; - // TODO How do we want to badge notifcations from profiles. if (!notificationIsForCurrentProfiles(ent.notification)) continue; final int vis = ent.notification.getNotification().visibility;