Merge "Enable 'real bubbles' and fix our tests"
This commit is contained in:
@@ -22,12 +22,16 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
import static com.android.systemui.bubbles.BubbleMovementHelper.EDGE_OVERLAP;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.Log;
|
||||
@@ -35,8 +39,6 @@ import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
@@ -88,6 +90,8 @@ public class BubbleController {
|
||||
// Bubbles get added to the status bar view
|
||||
private final StatusBarWindowController mStatusBarWindowController;
|
||||
|
||||
private INotificationManager mNotificationManagerService;
|
||||
|
||||
// Used for determining view rect for touch interaction
|
||||
private Rect mTempRect = new Rect();
|
||||
|
||||
@@ -124,6 +128,13 @@ public class BubbleController {
|
||||
mStatusBarWindowController = statusBarWindowController;
|
||||
|
||||
mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
|
||||
|
||||
try {
|
||||
mNotificationManagerService = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getServiceOrThrow(Context.NOTIFICATION_SERVICE));
|
||||
} catch (ServiceManager.ServiceNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,7 +279,7 @@ public class BubbleController {
|
||||
private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
|
||||
@Override
|
||||
public void onPendingEntryAdded(NotificationEntry entry) {
|
||||
if (shouldAutoBubble(mContext, entry)) {
|
||||
if (shouldAutoBubble(mContext, entry) || shouldBubble(entry)) {
|
||||
entry.setIsBubble(true);
|
||||
}
|
||||
}
|
||||
@@ -367,19 +378,38 @@ public class BubbleController {
|
||||
return new Point(EDGE_OVERLAP, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the notification has been developer configured to bubble and is allowed by the user.
|
||||
*/
|
||||
private boolean shouldBubble(NotificationEntry entry) {
|
||||
StatusBarNotification n = entry.notification;
|
||||
boolean canAppOverlay = false;
|
||||
try {
|
||||
canAppOverlay = mNotificationManagerService.areAppOverlaysAllowedForPackage(
|
||||
n.getPackageName(), n.getUid());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Error calling NoMan to determine if app can overlay", e);
|
||||
}
|
||||
|
||||
boolean canChannelOverlay = mNotificationEntryManager.getNotificationData().getChannel(
|
||||
entry.key).canOverlayApps();
|
||||
boolean hasOverlayIntent = n.getNotification().getAppOverlayIntent() != null;
|
||||
return hasOverlayIntent && canChannelOverlay && canAppOverlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the notification should bubble or not.
|
||||
*/
|
||||
private static boolean shouldAutoBubble(Context context, NotificationEntry entry) {
|
||||
private boolean shouldAutoBubble(Context context, NotificationEntry entry) {
|
||||
if (entry.isBubbleDismissed()) {
|
||||
return false;
|
||||
}
|
||||
StatusBarNotification n = entry.notification;
|
||||
|
||||
boolean autoBubbleMessages = shouldAutoBubbleMessages(context) || DEBUG_ENABLE_AUTO_BUBBLE;
|
||||
boolean autoBubbleOngoing = shouldAutoBubbleOngoing(context) || DEBUG_ENABLE_AUTO_BUBBLE;
|
||||
boolean autoBubbleAll = shouldAutoBubbleAll(context) || DEBUG_ENABLE_AUTO_BUBBLE;
|
||||
|
||||
StatusBarNotification n = entry.notification;
|
||||
boolean hasRemoteInput = false;
|
||||
if (n.getNotification().actions != null) {
|
||||
for (Notification.Action action : n.getNotification().actions) {
|
||||
|
||||
@@ -74,7 +74,8 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
private ExpandableNotificationRow mRow;
|
||||
private ExpandableNotificationRow mRow2;
|
||||
|
||||
private final NotificationData mNotificationData = new NotificationData();
|
||||
@Mock
|
||||
private NotificationData mNotificationData;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -93,6 +94,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
|
||||
// Return non-null notification data from the NEM
|
||||
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
|
||||
when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel);
|
||||
|
||||
mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController);
|
||||
|
||||
@@ -102,11 +104,6 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
mEntryListener = mEntryListenerCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsBubble() {
|
||||
assertTrue(mRow.getEntry().isBubble());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddBubble() {
|
||||
mBubbleController.addBubble(mRow.getEntry());
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
package com.android.systemui.statusbar;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Instrumentation;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
@@ -86,8 +89,7 @@ public class NotificationTestHelper {
|
||||
* @throws Exception
|
||||
*/
|
||||
public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception {
|
||||
return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */,
|
||||
false /* isBubble */);
|
||||
return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,8 +100,7 @@ public class NotificationTestHelper {
|
||||
* @throws Exception
|
||||
*/
|
||||
public ExpandableNotificationRow createRow(Notification notification) throws Exception {
|
||||
return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */,
|
||||
false /* isBubble */);
|
||||
return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,8 +113,7 @@ public class NotificationTestHelper {
|
||||
*/
|
||||
public ExpandableNotificationRow createRow(@InflationFlag int extraInflationFlags)
|
||||
throws Exception {
|
||||
return generateRow(createNotification(), PKG, UID, extraInflationFlags,
|
||||
false /* isBubble */);
|
||||
return generateRow(createNotification(), PKG, UID, extraInflationFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,20 +134,21 @@ public class NotificationTestHelper {
|
||||
return createGroup(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retursn an {@link ExpandableNotificationRow} that should be a bubble.
|
||||
*/
|
||||
public ExpandableNotificationRow createBubble() throws Exception {
|
||||
return createRow(PKG, UID, false /* isGroupSummary */, null /* groupKey */,
|
||||
true /* isBubble */);
|
||||
}
|
||||
|
||||
private ExpandableNotificationRow createGroupSummary(String groupkey) throws Exception {
|
||||
return createRow(PKG, UID, true /* isGroupSummary */, groupkey, false);
|
||||
return createRow(PKG, UID, true /* isGroupSummary */, groupkey);
|
||||
}
|
||||
|
||||
private ExpandableNotificationRow createGroupChild(String groupkey) throws Exception {
|
||||
return createRow(PKG, UID, false /* isGroupSummary */, groupkey, false);
|
||||
return createRow(PKG, UID, false /* isGroupSummary */, groupkey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
|
||||
*/
|
||||
public ExpandableNotificationRow createBubble() throws Exception {
|
||||
Notification n = createNotification(false /* isGroupSummary */,
|
||||
null /* groupKey */, true /* isBubble */);
|
||||
return generateRow(n, PKG, UID, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,7 +158,6 @@ public class NotificationTestHelper {
|
||||
* @param uid uid used for creating a {@link StatusBarNotification}
|
||||
* @param isGroupSummary whether the notification row is a group summary
|
||||
* @param groupKey the group key for the notification group used across notifications
|
||||
* @param isBubble
|
||||
* @return a row with that's either a standalone notification or a group notification if the
|
||||
* groupKey is non-null
|
||||
* @throws Exception
|
||||
@@ -166,10 +166,10 @@ public class NotificationTestHelper {
|
||||
String pkg,
|
||||
int uid,
|
||||
boolean isGroupSummary,
|
||||
@Nullable String groupKey, boolean isBubble)
|
||||
@Nullable String groupKey)
|
||||
throws Exception {
|
||||
Notification notif = createNotification(isGroupSummary, groupKey);
|
||||
return generateRow(notif, pkg, uid, 0 /* inflationFlags */, isBubble);
|
||||
return generateRow(notif, pkg, uid, 0 /* inflationFlags */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,8 +188,20 @@ public class NotificationTestHelper {
|
||||
* @param groupKey the group key for the notification group used across notifications
|
||||
* @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 */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a notification with the given parameters.
|
||||
*
|
||||
* @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
|
||||
* @return a notification that is in the group specified or standalone if unspecified
|
||||
*/
|
||||
private Notification createNotification(boolean isGroupSummary,
|
||||
@Nullable String groupKey) {
|
||||
@Nullable String groupKey, boolean isBubble) {
|
||||
Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
|
||||
R.drawable.ic_person)
|
||||
.setCustomContentView(new RemoteViews(mContext.getPackageName(),
|
||||
@@ -207,6 +219,10 @@ public class NotificationTestHelper {
|
||||
if (!TextUtils.isEmpty(groupKey)) {
|
||||
notificationBuilder.setGroup(groupKey);
|
||||
}
|
||||
if (isBubble) {
|
||||
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
|
||||
notificationBuilder.setAppOverlayIntent(bubbleIntent);
|
||||
}
|
||||
return notificationBuilder.build();
|
||||
}
|
||||
|
||||
@@ -214,7 +230,17 @@ public class NotificationTestHelper {
|
||||
Notification notification,
|
||||
String pkg,
|
||||
int uid,
|
||||
@InflationFlag int extraInflationFlags, boolean isBubble)
|
||||
@InflationFlag int extraInflationFlags)
|
||||
throws Exception {
|
||||
return generateRow(notification, pkg, uid, extraInflationFlags, IMPORTANCE_DEFAULT);
|
||||
}
|
||||
|
||||
private ExpandableNotificationRow generateRow(
|
||||
Notification notification,
|
||||
String pkg,
|
||||
int uid,
|
||||
@InflationFlag int extraInflationFlags,
|
||||
int importance)
|
||||
throws Exception {
|
||||
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
|
||||
mContext.LAYOUT_INFLATER_SERVICE);
|
||||
@@ -242,9 +268,8 @@ public class NotificationTestHelper {
|
||||
entry.setRow(row);
|
||||
entry.createIcons(mContext, sbn);
|
||||
entry.channel = new NotificationChannel(
|
||||
notification.getChannelId(), notification.getChannelId(), IMPORTANCE_DEFAULT);
|
||||
notification.getChannelId(), notification.getChannelId(), importance);
|
||||
entry.channel.setBlockableSystem(true);
|
||||
entry.setIsBubble(isBubble);
|
||||
row.setEntry(entry);
|
||||
row.getNotificationInflater().addInflationFlags(extraInflationFlags);
|
||||
NotificationInflaterTest.runThenWaitForInflation(
|
||||
|
||||
@@ -2317,8 +2317,8 @@ public class NotificationManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public boolean areAppOverlaysAllowedForPackage(String pkg, int uid) {
|
||||
checkCallerIsSystemOrSameApp(pkg);
|
||||
|
||||
enforceSystemOrSystemUIOrSamePackage("Caller not system or systemui or same package",
|
||||
pkg);
|
||||
return mPreferencesHelper.areAppOverlaysAllowed(pkg, uid);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user