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.notification; 18 19 import android.app.ActivityOptions; 20 import android.app.Notification; 21 import android.app.PendingIntent; 22 import android.content.Context; 23 import android.graphics.drawable.BitmapDrawable; 24 import android.graphics.drawable.Drawable; 25 import android.graphics.drawable.Icon; 26 import android.os.Bundle; 27 import android.service.notification.StatusBarNotification; 28 import android.view.View; 29 30 import com.android.launcher3.AbstractFloatingView; 31 import com.android.launcher3.Launcher; 32 import com.android.launcher3.LauncherAppState; 33 import com.android.launcher3.graphics.IconPalette; 34 import com.android.launcher3.popup.PopupContainerWithArrow; 35 import com.android.launcher3.util.PackageUserKey; 36 37 /** 38 * An object that contains relevant information from a {@link StatusBarNotification}. This should 39 * only be created when we need to show the notification contents on the UI; until then, a 40 * {@link com.android.launcher3.badge.BadgeInfo} with only the notification key should 41 * be passed around, and then this can be constructed using the StatusBarNotification from 42 * {@link NotificationListener#getNotificationsForKeys(java.util.List)}. 43 */ 44 public class NotificationInfo implements View.OnClickListener { 45 46 public final PackageUserKey packageUserKey; 47 public final String notificationKey; 48 public final CharSequence title; 49 public final CharSequence text; 50 public final PendingIntent intent; 51 public final boolean autoCancel; 52 public final boolean dismissable; 53 54 private int mBadgeIcon; 55 private Drawable mIconDrawable; 56 private int mIconColor; 57 private boolean mIsIconLarge; 58 59 /** 60 * Extracts the data that we need from the StatusBarNotification. 61 */ NotificationInfo(Context context, StatusBarNotification statusBarNotification)62 public NotificationInfo(Context context, StatusBarNotification statusBarNotification) { 63 packageUserKey = PackageUserKey.fromNotification(statusBarNotification); 64 notificationKey = statusBarNotification.getKey(); 65 Notification notification = statusBarNotification.getNotification(); 66 title = notification.extras.getCharSequence(Notification.EXTRA_TITLE); 67 text = notification.extras.getCharSequence(Notification.EXTRA_TEXT); 68 69 mBadgeIcon = notification.getBadgeIconType(); 70 // Load the icon. Since it is backed by ashmem, we won't copy the entire bitmap 71 // into our process as long as we don't touch it and it exists in systemui. 72 Icon icon = mBadgeIcon == Notification.BADGE_ICON_SMALL ? null : notification.getLargeIcon(); 73 if (icon == null) { 74 // Use the small icon. 75 icon = notification.getSmallIcon(); 76 mIconDrawable = icon.loadDrawable(context); 77 mIconColor = statusBarNotification.getNotification().color; 78 mIsIconLarge = false; 79 } else { 80 // Use the large icon. 81 mIconDrawable = icon.loadDrawable(context); 82 mIsIconLarge = true; 83 } 84 if (mIconDrawable == null) { 85 mIconDrawable = new BitmapDrawable(context.getResources(), LauncherAppState 86 .getInstance(context).getIconCache() 87 .getDefaultIcon(statusBarNotification.getUser())); 88 mBadgeIcon = Notification.BADGE_ICON_NONE; 89 } 90 intent = notification.contentIntent; 91 autoCancel = (notification.flags & Notification.FLAG_AUTO_CANCEL) != 0; 92 dismissable = (notification.flags & Notification.FLAG_ONGOING_EVENT) == 0; 93 } 94 95 @Override onClick(View view)96 public void onClick(View view) { 97 if (intent == null) { 98 return; 99 } 100 final Launcher launcher = Launcher.getLauncher(view.getContext()); 101 Bundle activityOptions = ActivityOptions.makeClipRevealAnimation( 102 view, 0, 0, view.getWidth(), view.getHeight()).toBundle(); 103 try { 104 intent.send(null, 0, null, null, null, null, activityOptions); 105 launcher.getUserEventDispatcher().logNotificationLaunch(view, intent); 106 } catch (PendingIntent.CanceledException e) { 107 e.printStackTrace(); 108 } 109 if (autoCancel) { 110 launcher.getPopupDataProvider().cancelNotification(notificationKey); 111 } 112 AbstractFloatingView.closeOpenContainer(launcher, AbstractFloatingView 113 .TYPE_POPUP_CONTAINER_WITH_ARROW); 114 } 115 getIconForBackground(Context context, int background)116 public Drawable getIconForBackground(Context context, int background) { 117 if (mIsIconLarge) { 118 // Only small icons should be tinted. 119 return mIconDrawable; 120 } 121 mIconColor = IconPalette.resolveContrastColor(context, mIconColor, background); 122 Drawable icon = mIconDrawable.mutate(); 123 // DrawableContainer ignores the color filter if it's already set, so clear it first to 124 // get it set and invalidated properly. 125 icon.setTintList(null); 126 icon.setTint(mIconColor); 127 return icon; 128 } 129 isIconLarge()130 public boolean isIconLarge() { 131 return mIsIconLarge; 132 } 133 shouldShowIconInBadge()134 public boolean shouldShowIconInBadge() { 135 // If the icon we're using for this notification matches what the Notification 136 // specified should show in the badge, then return true. 137 return mIsIconLarge && mBadgeIcon == Notification.BADGE_ICON_LARGE 138 || !mIsIconLarge && mBadgeIcon == Notification.BADGE_ICON_SMALL; 139 } 140 } 141