1 /* 2 * Copyright (C) 2022 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.server.wm.flicker.testapp; 18 19 20 import android.app.Notification; 21 import android.app.NotificationChannel; 22 import android.app.NotificationManager; 23 import android.app.PendingIntent; 24 import android.app.Person; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.graphics.Point; 28 import android.graphics.drawable.Icon; 29 import android.os.SystemClock; 30 import android.service.notification.StatusBarNotification; 31 import android.view.WindowManager; 32 33 import java.util.HashMap; 34 35 public class BubbleHelper { 36 37 static final String EXTRA_BUBBLE_NOTIF_ID = "EXTRA_BUBBLE_NOTIF_ID"; 38 static final String CHANNEL_ID = "bubbles"; 39 static final String CHANNEL_NAME = "Bubbles"; 40 static final int DEFAULT_HEIGHT_DP = 300; 41 42 private static BubbleHelper sInstance; 43 44 private final Context mContext; 45 private NotificationManager mNotificationManager; 46 private float mDisplayHeight; 47 48 private HashMap<Integer, BubbleInfo> mBubbleMap = new HashMap<>(); 49 50 private int mNextNotifyId = 0; 51 private int mColourIndex = 0; 52 53 public static class BubbleInfo { 54 public int id; 55 public int height; 56 public Icon icon; 57 BubbleInfo(int id, int height, Icon icon)58 public BubbleInfo(int id, int height, Icon icon) { 59 this.id = id; 60 this.height = height; 61 this.icon = icon; 62 } 63 } 64 getInstance(Context context)65 public static BubbleHelper getInstance(Context context) { 66 if (sInstance == null) { 67 sInstance = new BubbleHelper(context); 68 } 69 return sInstance; 70 } 71 BubbleHelper(Context context)72 private BubbleHelper(Context context) { 73 mContext = context; 74 mNotificationManager = context.getSystemService(NotificationManager.class); 75 76 NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, 77 NotificationManager.IMPORTANCE_DEFAULT); 78 channel.setDescription("Channel that posts bubbles"); 79 channel.setAllowBubbles(true); 80 mNotificationManager.createNotificationChannel(channel); 81 82 Point p = new Point(); 83 WindowManager wm = context.getSystemService(WindowManager.class); 84 wm.getDefaultDisplay().getRealSize(p); 85 mDisplayHeight = p.y; 86 87 } 88 getNextNotifyId()89 private int getNextNotifyId() { 90 int id = mNextNotifyId; 91 mNextNotifyId++; 92 return id; 93 } 94 getIcon()95 private Icon getIcon() { 96 return Icon.createWithResource(mContext, R.drawable.bg); 97 } 98 addNewBubble(boolean autoExpand, boolean suppressNotif)99 public int addNewBubble(boolean autoExpand, boolean suppressNotif) { 100 int id = getNextNotifyId(); 101 BubbleInfo info = new BubbleInfo(id, DEFAULT_HEIGHT_DP, getIcon()); 102 mBubbleMap.put(info.id, info); 103 104 Notification.BubbleMetadata data = getBubbleBuilder(info) 105 .setSuppressNotification(suppressNotif) 106 .setAutoExpandBubble(false) 107 .build(); 108 Notification notification = getNotificationBuilder(info.id) 109 .setBubbleMetadata(data).build(); 110 111 mNotificationManager.notify(info.id, notification); 112 return info.id; 113 } 114 getNotificationBuilder(int id)115 private Notification.Builder getNotificationBuilder(int id) { 116 Person chatBot = new Person.Builder() 117 .setBot(true) 118 .setName("BubbleChat") 119 .setImportant(true) 120 .build(); 121 String shortcutId = "BubbleChat"; 122 return new Notification.Builder(mContext, CHANNEL_ID) 123 .setChannelId(CHANNEL_ID) 124 .setShortcutId(shortcutId) 125 .setContentTitle("BubbleChat") 126 .setContentIntent(PendingIntent.getActivity(mContext, 0, 127 new Intent(mContext, LaunchBubbleActivity.class), 128 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE)) 129 .setStyle(new Notification.MessagingStyle(chatBot) 130 .setConversationTitle("BubbleChat") 131 .addMessage("BubbleChat", 132 SystemClock.currentThreadTimeMillis() - 300000, chatBot) 133 .addMessage("Is it me, " + id + ", you're looking for?", 134 SystemClock.currentThreadTimeMillis(), chatBot) 135 ) 136 .setSmallIcon(R.drawable.ic_bubble); 137 } 138 getBubbleBuilder(BubbleInfo info)139 private Notification.BubbleMetadata.Builder getBubbleBuilder(BubbleInfo info) { 140 Intent target = new Intent(mContext, BubbleActivity.class); 141 target.putExtra(EXTRA_BUBBLE_NOTIF_ID, info.id); 142 PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, info.id, target, 143 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 144 145 return new Notification.BubbleMetadata.Builder() 146 .setIntent(bubbleIntent) 147 .setIcon(info.icon) 148 .setDesiredHeight(info.height); 149 } 150 cancel(int id)151 public void cancel(int id) { 152 mNotificationManager.cancel(id); 153 } 154 cancelAll()155 public void cancelAll() { 156 mNotificationManager.cancelAll(); 157 } 158 cancelLast()159 public void cancelLast() { 160 StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications(); 161 if (activeNotifications.length > 0) { 162 mNotificationManager.cancel( 163 activeNotifications[activeNotifications.length - 1].getId()); 164 } 165 } 166 cancelFirst()167 public void cancelFirst() { 168 StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications(); 169 if (activeNotifications.length > 0) { 170 mNotificationManager.cancel(activeNotifications[0].getId()); 171 } 172 } 173 } 174