summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java84
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java40
4 files changed, 139 insertions, 14 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 0e691fbb0f4e..22c019f950e7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -26,6 +26,7 @@ import static com.android.systemui.statusbar.notification.NotificationAlertingMa
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
@@ -64,6 +65,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.lang.annotation.Retention;
+import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -340,6 +342,9 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
// It's new
mStackView.addBubble(notif);
}
+ if (shouldAutoExpand(notif)) {
+ mStackView.setExpandedBubble(notif);
+ }
updateVisibility();
}
@@ -522,6 +527,23 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|| autoBubbleAll;
}
+ private boolean shouldAutoExpand(NotificationEntry entry) {
+ Notification.BubbleMetadata metadata = entry.getBubbleMetadata();
+ return metadata != null && metadata.getAutoExpandBubble()
+ && isForegroundApp(entry.notification.getPackageName());
+ }
+
+ /**
+ * Return true if the applications with the package name is running in foreground.
+ *
+ * @param pkgName application package name.
+ */
+ private boolean isForegroundApp(String pkgName) {
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ List<RunningTaskInfo> tasks = am.getRunningTasks(1 /* maxNum */);
+ return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
+ }
+
/**
* This task stack listener is responsible for responding to tasks moved to the front
* which are on the default (main) display. When this happens, expanded bubbles must be
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index c9b550cd6e64..f666d60d6282 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.bubbles;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -26,8 +28,13 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
+import android.app.Notification;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.WindowManager;
@@ -36,6 +43,7 @@ import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -55,6 +63,9 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -83,6 +94,7 @@ public class BubbleControllerTest extends SysuiTestCase {
private ExpandableNotificationRow mRow;
private ExpandableNotificationRow mRow2;
private ExpandableNotificationRow mNoChannelRow;
+ private ExpandableNotificationRow mAutoExpandRow;
@Mock
private NotificationData mNotificationData;
@@ -104,7 +116,6 @@ public class BubbleControllerTest extends SysuiTestCase {
mStatusBarView = new FrameLayout(mContext);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
-
// Bubbles get added to status bar window view
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters);
@@ -115,6 +126,9 @@ public class BubbleControllerTest extends SysuiTestCase {
mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
mNoChannelRow = mNotificationTestHelper.createBubble(mDeleteIntent);
+ Notification.BubbleMetadata metadata = getBuilder().setAutoExpandBubble(true).build();
+ mAutoExpandRow = mNotificationTestHelper.createBubble(metadata,
+ "com.android.systemui.tests");
// Return non-null notification data from the NEM
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
@@ -303,6 +317,63 @@ public class BubbleControllerTest extends SysuiTestCase {
}
@Test
+ public void testAutoExpandFailsNotForeground() {
+ assertFalse(mBubbleController.isStackExpanded());
+
+ // Add the auto expand bubble
+ mEntryListener.onPendingEntryAdded(mAutoExpandRow.getEntry());
+ mBubbleController.updateBubble(mAutoExpandRow.getEntry(), true /* updatePosition */);
+
+ // Expansion shouldn't change
+ verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
+ mAutoExpandRow.getEntry().key);
+ assertFalse(mBubbleController.isStackExpanded());
+
+ // # of bubbles should change
+ verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
+ }
+
+ @Test
+ public void testAutoExpandSucceedsForeground() {
+ final CountDownLatch latch = new CountDownLatch(1);
+ BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ latch.countDown();
+ }
+ };
+ IntentFilter filter = new IntentFilter(BubblesTestActivity.BUBBLE_ACTIVITY_OPENED);
+ mContext.registerReceiver(receiver, filter);
+
+ assertFalse(mBubbleController.isStackExpanded());
+
+ // Make ourselves foreground
+ Intent i = new Intent(mContext, BubblesTestActivity.class);
+ i.setFlags(FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(i);
+
+ try {
+ latch.await(100, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Add the auto expand bubble
+ mEntryListener.onPendingEntryAdded(mAutoExpandRow.getEntry());
+ mBubbleController.updateBubble(mAutoExpandRow.getEntry(), true /* updatePosition */);
+
+ // Expansion should change
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
+ mAutoExpandRow.getEntry().key);
+ assertTrue(mBubbleController.isStackExpanded());
+
+ // # of bubbles should change
+ verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
+ mContext.unregisterReceiver(receiver);
+ }
+
+
+ @Test
public void testMarkNewNotificationAsBubble() {
mEntryListener.onPendingEntryAdded(mRow.getEntry());
assertTrue(mRow.getEntry().isBubble());
@@ -349,4 +420,15 @@ public class BubbleControllerTest extends SysuiTestCase {
return entry.notification.getNotification().getBubbleMetadata() != null;
}
}
+
+ /**
+ * @return basic {@link android.app.Notification.BubbleMetadata.Builder}
+ */
+ private Notification.BubbleMetadata.Builder getBuilder() {
+ Intent target = new Intent(mContext, BubblesTestActivity.class);
+ PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0);
+ return new Notification.BubbleMetadata.Builder()
+ .setIntent(bubbleIntent)
+ .setIcon(Icon.createWithResource(mContext, R.drawable.android));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java
index ea472da910f2..43d2ad1dfe0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java
@@ -17,6 +17,7 @@
package com.android.systemui.bubbles;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
import com.android.systemui.R;
@@ -26,9 +27,15 @@ import com.android.systemui.R;
*/
public class BubblesTestActivity extends Activity {
+ public static final String BUBBLE_ACTIVITY_OPENED =
+ "com.android.systemui.bubbles.BUBBLE_ACTIVITY_OPENED";
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
+
+ Intent i = new Intent(BUBBLE_ACTIVITY_OPENED);
+ sendBroadcast(i);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 1bcf8803b5cf..8c5f6f24ee79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -151,24 +151,41 @@ public class NotificationTestHelper {
/**
* Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
+ *
+ * @param deleteIntent the intent to assign to {@link BubbleMetadata#deleteIntent}
*/
- public ExpandableNotificationRow createBubble() throws Exception {
- return createBubble(null);
+ public ExpandableNotificationRow createBubble(@Nullable PendingIntent deleteIntent)
+ throws Exception {
+ Notification n = createNotification(false /* isGroupSummary */,
+ null /* groupKey */, makeBubbleMetadata(deleteIntent));
+ return generateRow(n, PKG, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
}
/**
* Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
*
- * @param deleteIntent the intent to assign to {@link BubbleMetadata#deleteIntent}
+ * @param bubbleMetadata the {@link BubbleMetadata} to use
*/
- public ExpandableNotificationRow createBubble(@Nullable PendingIntent deleteIntent)
+ public ExpandableNotificationRow createBubble(BubbleMetadata bubbleMetadata)
throws Exception {
Notification n = createNotification(false /* isGroupSummary */,
- null /* groupKey */, true /* isBubble */, deleteIntent);
+ null /* groupKey */, bubbleMetadata);
return generateRow(n, PKG, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
}
/**
+ * Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
+ *
+ * @param bubbleMetadata the {@link BubbleMetadata} to use
+ */
+ public ExpandableNotificationRow createBubble(BubbleMetadata bubbleMetadata, String pkg)
+ throws Exception {
+ Notification n = createNotification(false /* isGroupSummary */,
+ null /* groupKey */, bubbleMetadata);
+ return generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
+ }
+
+ /**
* Creates a notification row with the given details.
*
* @param pkg package used for creating a {@link StatusBarNotification}
@@ -207,8 +224,7 @@ public class NotificationTestHelper {
* @return a notification that is in the group specified or standalone if unspecified
*/
private Notification createNotification(boolean isGroupSummary, @Nullable String groupKey) {
- return createNotification(isGroupSummary, groupKey, false /* isBubble */,
- null /* bubbleDeleteIntent */);
+ return createNotification(isGroupSummary, groupKey, null /* bubble metadata */);
}
/**
@@ -216,12 +232,11 @@ public class NotificationTestHelper {
*
* @param isGroupSummary whether the notification is a group summary
* @param groupKey the group key for the notification group used across notifications
- * @param isBubble whether this notification should bubble
+ * @param bubbleMetadata the bubble metadata to use for this notification if it exists.
* @return a notification that is in the group specified or standalone if unspecified
*/
private Notification createNotification(boolean isGroupSummary,
- @Nullable String groupKey, boolean isBubble,
- @Nullable PendingIntent bubbleDeleteIntent) {
+ @Nullable String groupKey, @Nullable BubbleMetadata bubbleMetadata) {
Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
R.drawable.ic_person)
.setCustomContentView(new RemoteViews(mContext.getPackageName(),
@@ -239,9 +254,8 @@ public class NotificationTestHelper {
if (!TextUtils.isEmpty(groupKey)) {
notificationBuilder.setGroup(groupKey);
}
- if (isBubble) {
- BubbleMetadata metadata = makeBubbleMetadata(bubbleDeleteIntent);
- notificationBuilder.setBubbleMetadata(metadata);
+ if (bubbleMetadata != null) {
+ notificationBuilder.setBubbleMetadata(bubbleMetadata);
}
return notificationBuilder.build();
}