1 /* 2 * Copyright (C) 2017 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 com.android.launcher3.badge; 18 19 import android.content.Context; 20 import android.graphics.Bitmap; 21 import android.graphics.BitmapShader; 22 import android.graphics.Canvas; 23 import android.graphics.Shader; 24 import android.graphics.drawable.Drawable; 25 import android.support.annotation.Nullable; 26 27 import com.android.launcher3.notification.NotificationInfo; 28 import com.android.launcher3.notification.NotificationKeyData; 29 import com.android.launcher3.util.PackageUserKey; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 /** 35 * Contains data to be used in an icon badge. 36 */ 37 public class BadgeInfo { 38 39 public static final int MAX_COUNT = 999; 40 41 /** Used to link this BadgeInfo to icons on the workspace and all apps */ 42 private PackageUserKey mPackageUserKey; 43 44 /** 45 * The keys of the notifications that this badge represents. These keys can later be 46 * used to retrieve {@link NotificationInfo}'s. 47 */ 48 private List<NotificationKeyData> mNotificationKeys; 49 50 /** 51 * The current sum of the counts in {@link #mNotificationKeys}, 52 * updated whenever a key is added or removed. 53 */ 54 private int mTotalCount; 55 56 /** This will only be initialized if the badge should display the notification icon. */ 57 private NotificationInfo mNotificationInfo; 58 59 /** 60 * When retrieving the notification icon, we draw it into this shader, which can be clipped 61 * as necessary when drawn in a badge. 62 */ 63 private Shader mNotificationIcon; 64 BadgeInfo(PackageUserKey packageUserKey)65 public BadgeInfo(PackageUserKey packageUserKey) { 66 mPackageUserKey = packageUserKey; 67 mNotificationKeys = new ArrayList<>(); 68 } 69 70 /** 71 * Returns whether the notification was added or its count changed. 72 */ addOrUpdateNotificationKey(NotificationKeyData notificationKey)73 public boolean addOrUpdateNotificationKey(NotificationKeyData notificationKey) { 74 int indexOfPrevKey = mNotificationKeys.indexOf(notificationKey); 75 NotificationKeyData prevKey = indexOfPrevKey == -1 ? null 76 : mNotificationKeys.get(indexOfPrevKey); 77 if (prevKey != null) { 78 if (prevKey.count == notificationKey.count) { 79 return false; 80 } 81 // Notification was updated with a new count. 82 mTotalCount -= prevKey.count; 83 mTotalCount += notificationKey.count; 84 prevKey.count = notificationKey.count; 85 return true; 86 } 87 boolean added = mNotificationKeys.add(notificationKey); 88 if (added) { 89 mTotalCount += notificationKey.count; 90 } 91 return added; 92 } 93 94 /** 95 * Returns whether the notification was removed (false if it didn't exist). 96 */ removeNotificationKey(NotificationKeyData notificationKey)97 public boolean removeNotificationKey(NotificationKeyData notificationKey) { 98 boolean removed = mNotificationKeys.remove(notificationKey); 99 if (removed) { 100 mTotalCount -= notificationKey.count; 101 } 102 return removed; 103 } 104 getNotificationKeys()105 public List<NotificationKeyData> getNotificationKeys() { 106 return mNotificationKeys; 107 } 108 getNotificationCount()109 public int getNotificationCount() { 110 return Math.min(mTotalCount, MAX_COUNT); 111 } 112 setNotificationToShow(@ullable NotificationInfo notificationInfo)113 public void setNotificationToShow(@Nullable NotificationInfo notificationInfo) { 114 mNotificationInfo = notificationInfo; 115 mNotificationIcon = null; 116 } 117 hasNotificationToShow()118 public boolean hasNotificationToShow() { 119 return mNotificationInfo != null; 120 } 121 122 /** 123 * Returns a shader to set on a Paint that will draw the notification icon in a badge. 124 * 125 * The shader is cached until {@link #setNotificationToShow(NotificationInfo)} is called. 126 */ getNotificationIconForBadge(Context context, int badgeColor, int badgeSize, int badgePadding)127 public @Nullable Shader getNotificationIconForBadge(Context context, int badgeColor, 128 int badgeSize, int badgePadding) { 129 if (mNotificationInfo == null) { 130 return null; 131 } 132 if (mNotificationIcon == null) { 133 Drawable icon = mNotificationInfo.getIconForBackground(context, badgeColor) 134 .getConstantState().newDrawable(); 135 int iconSize = badgeSize - badgePadding * 2; 136 icon.setBounds(0, 0, iconSize, iconSize); 137 Bitmap iconBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888); 138 Canvas canvas = new Canvas(iconBitmap); 139 canvas.translate(badgePadding, badgePadding); 140 icon.draw(canvas); 141 mNotificationIcon = new BitmapShader(iconBitmap, Shader.TileMode.CLAMP, 142 Shader.TileMode.CLAMP); 143 } 144 return mNotificationIcon; 145 } 146 isIconLarge()147 public boolean isIconLarge() { 148 return mNotificationInfo != null && mNotificationInfo.isIconLarge(); 149 } 150 151 /** 152 * Whether newBadge represents the same PackageUserKey as this badge, and icons with 153 * this badge should be invalidated. So, for instance, if a badge has 3 notifications 154 * and one of those notifications is updated, this method should return false because 155 * the badge still says "3" and the contents of those notifications are only retrieved 156 * upon long-click. This method always returns true when adding or removing notifications, 157 * or if the badge has a notification icon to show. 158 */ shouldBeInvalidated(BadgeInfo newBadge)159 public boolean shouldBeInvalidated(BadgeInfo newBadge) { 160 return mPackageUserKey.equals(newBadge.mPackageUserKey) 161 && (getNotificationCount() != newBadge.getNotificationCount() 162 || hasNotificationToShow()); 163 } 164 } 165