1 /* 2 * Copyright (C) 2019 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 android.app.stubs; 18 19 import android.app.Activity; 20 import android.app.Notification; 21 import android.app.Notification.BubbleMetadata; 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.content.LocusId; 28 import android.graphics.drawable.Icon; 29 import android.os.Bundle; 30 import android.os.SystemClock; 31 32 /** 33 * Used by NotificationManagerBubbleTest for testing policy around bubbles, this activity is able to 34 * send a bubble. 35 */ 36 public class SendBubbleActivity extends Activity { 37 38 // Should be same as what NotificationManagerBubbleTest is using 39 private static final String NOTIFICATION_CHANNEL_ID = "NotificationManagerTest"; 40 private static final String SHARE_SHORTCUT_ID = "shareShortcut"; 41 42 public static final String BUBBLE_ACTIVITY_OPENED = 43 "android.app.stubs.BUBBLE_ACTIVITY_OPENED"; 44 public static final int BUBBLE_NOTIF_ID = 1; 45 46 private volatile boolean mIsStopped; 47 48 @Override onCreate(Bundle savedInstanceState)49 public void onCreate(Bundle savedInstanceState) { 50 super.onCreate(savedInstanceState); 51 setContentView(R.layout.main); 52 53 Intent i = new Intent(BUBBLE_ACTIVITY_OPENED); 54 sendBroadcast(i); 55 } 56 57 /** 58 * Sends a notification that has bubble metadata but the rest of the notification isn't 59 * configured correctly so the system won't allow it to bubble. 60 */ sendInvalidBubble(int notifId, boolean autoExpand)61 public void sendInvalidBubble(int notifId, boolean autoExpand) { 62 Context context = getApplicationContext(); 63 64 PendingIntent pendingIntent = PendingIntent.getActivity(context, notifId, 65 new Intent().setPackage(context.getPackageName()), 66 PendingIntent.FLAG_MUTABLE); 67 Notification n = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID) 68 .setSmallIcon(R.drawable.black) 69 .setWhen(System.currentTimeMillis()) 70 .setContentTitle("notify#" + notifId) 71 .setContentText("This is #" + notifId + "notification ") 72 .setContentIntent(pendingIntent) 73 .setBubbleMetadata(getBubbleMetadata(notifId, autoExpand, 74 false /* suppressNotification */, 75 false /* suppressBubble */, 76 false /* useShortcut */)) 77 .build(); 78 79 NotificationManager noMan = (NotificationManager) context.getSystemService( 80 Context.NOTIFICATION_SERVICE); 81 noMan.notify(notifId, n); 82 } 83 84 /** Sends a notification that is properly configured to bubble. */ sendBubble(int notifId, boolean autoExpand, boolean suppressNotification)85 public void sendBubble(int notifId, boolean autoExpand, boolean suppressNotification) { 86 sendBubble(notifId, autoExpand, suppressNotification, false /* suppressBubble */, 87 false /* useShortcut */, true /* setLocusId */); 88 } 89 90 /** Sends a notification that is properly configured to bubble. */ sendBubble(int notifId, boolean autoExpand, boolean suppressNotification, boolean suppressBubble)91 public void sendBubble(int notifId, boolean autoExpand, boolean suppressNotification, 92 boolean suppressBubble) { 93 sendBubble(notifId, autoExpand, suppressNotification, suppressBubble, 94 false /* useShortcut */, true /* setLocusId */); 95 } 96 97 /** Sends a notification that is properly configured to bubble. */ sendBubble(int notifId, boolean autoExpand, boolean suppressNotification, boolean suppressBubble, boolean useShortcut, boolean setLocusId)98 public void sendBubble(int notifId, boolean autoExpand, boolean suppressNotification, 99 boolean suppressBubble, boolean useShortcut, boolean setLocusId) { 100 Context context = getApplicationContext(); 101 // Give it a person 102 Person person = new Person.Builder() 103 .setName("bubblebot" + notifId) 104 .build(); 105 // Make it messaging style 106 Notification.Builder nb = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID) 107 .setSmallIcon(R.drawable.black) 108 .setContentTitle("Bubble Chat") 109 .setShortcutId(SHARE_SHORTCUT_ID) 110 .setStyle(new Notification.MessagingStyle(person) 111 .setConversationTitle("Bubble Chat") 112 .addMessage("Hello?", 113 SystemClock.currentThreadTimeMillis() - 300000, person) 114 .addMessage("Is it me you're looking for?", 115 SystemClock.currentThreadTimeMillis(), person) 116 ) 117 .setBubbleMetadata(getBubbleMetadata(notifId, 118 autoExpand, 119 suppressNotification, 120 suppressBubble, 121 useShortcut)); 122 123 if (setLocusId) { 124 nb.setLocusId(new LocusId(String.valueOf(notifId))); 125 } 126 127 NotificationManager noMan = (NotificationManager) context.getSystemService( 128 Context.NOTIFICATION_SERVICE); 129 noMan.notify(notifId, nb.build()); 130 } 131 getBubbleMetadata(int notifId, boolean autoExpand, boolean suppressNotification, boolean suppressBubble, boolean useShortcut)132 private BubbleMetadata getBubbleMetadata(int notifId, boolean autoExpand, 133 boolean suppressNotification, 134 boolean suppressBubble, 135 boolean useShortcut) { 136 if (useShortcut) { 137 return new Notification.BubbleMetadata.Builder(SHARE_SHORTCUT_ID) 138 .setAutoExpandBubble(autoExpand) 139 .setSuppressableBubble(suppressBubble) 140 .setSuppressNotification(suppressNotification) 141 .build(); 142 } else { 143 Context context = getApplicationContext(); 144 final Intent intent = new Intent(context, BubbledActivity.class); 145 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 146 intent.setAction(Intent.ACTION_MAIN); 147 final PendingIntent pendingIntent = 148 PendingIntent.getActivity(context, notifId, intent, 149 PendingIntent.FLAG_MUTABLE); 150 151 return new Notification.BubbleMetadata.Builder(pendingIntent, 152 Icon.createWithResource(context, R.drawable.black)) 153 .setAutoExpandBubble(autoExpand) 154 .setSuppressNotification(suppressNotification) 155 .setSuppressableBubble(suppressBubble) 156 .build(); 157 } 158 } 159 160 /** Waits for the activity to be stopped. Do not call this method on main thread. */ waitForStopped()161 public void waitForStopped() { 162 synchronized (this) { 163 while (!mIsStopped) { 164 try { 165 wait(5000 /* timeout */); 166 } catch (InterruptedException ignored) { 167 } 168 } 169 } 170 } 171 172 @Override onStart()173 protected void onStart() { 174 super.onStart(); 175 mIsStopped = false; 176 } 177 178 @Override onStop()179 protected void onStop() { 180 super.onStop(); 181 synchronized (this) { 182 mIsStopped = true; 183 notifyAll(); 184 } 185 } 186 } 187