Merge "Bubbles Policy: remove phonecalls" into rvc-dev am: ef7b53424b
Change-Id: I183dc3c12d66273d2a28d76a7b1d2831c85cda97
This commit is contained in:
@@ -15,9 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.server.notification;
|
package com.android.server.notification;
|
||||||
|
|
||||||
import static android.app.Notification.CATEGORY_CALL;
|
|
||||||
import static android.app.Notification.FLAG_BUBBLE;
|
import static android.app.Notification.FLAG_BUBBLE;
|
||||||
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
|
|
||||||
|
|
||||||
import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
|
import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
|
||||||
import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
|
import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
|
||||||
@@ -25,7 +23,6 @@ import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Person;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
@@ -34,8 +31,6 @@ import android.util.Slog;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.FrameworkStatsLog;
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether a bubble can be shown for this notification
|
* Determines whether a bubble can be shown for this notification
|
||||||
*/
|
*/
|
||||||
@@ -152,41 +147,13 @@ public class BubbleExtractor implements NotificationSignalExtractor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point the bubble must fulfill communication policy
|
|
||||||
|
|
||||||
// Communication always needs a person
|
|
||||||
ArrayList<Person> peopleList = notification.extras != null
|
|
||||||
? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)
|
|
||||||
: null;
|
|
||||||
// Message style requires a person & it's not included in the list
|
|
||||||
boolean isMessageStyle = Notification.MessagingStyle.class.equals(
|
boolean isMessageStyle = Notification.MessagingStyle.class.equals(
|
||||||
notification.getNotificationStyle());
|
notification.getNotificationStyle());
|
||||||
if (!isMessageStyle && (peopleList == null || peopleList.isEmpty())) {
|
if (!isMessageStyle) {
|
||||||
logBubbleError(r.getKey(), "Must have a person and be "
|
logBubbleError(r.getKey(), "must be Notification.MessageStyle");
|
||||||
+ "Notification.MessageStyle or Notification.CATEGORY_CALL");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// Communication is a message or a call
|
|
||||||
boolean isCall = CATEGORY_CALL.equals(notification.category);
|
|
||||||
boolean hasForegroundService = (notification.flags & FLAG_FOREGROUND_SERVICE) != 0;
|
|
||||||
if (hasForegroundService && !isCall) {
|
|
||||||
logBubbleError(r.getKey(),
|
|
||||||
"foreground services must be Notification.CATEGORY_CALL to bubble");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (isMessageStyle) {
|
|
||||||
return true;
|
|
||||||
} else if (isCall) {
|
|
||||||
if (hasForegroundService) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
logBubbleError(r.getKey(), "calls require foreground service");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
logBubbleError(r.getKey(), "Must be "
|
|
||||||
+ "Notification.MessageStyle or Notification.CATEGORY_CALL");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -243,7 +243,6 @@ import com.android.internal.util.ArrayUtils;
|
|||||||
import com.android.internal.util.CollectionUtils;
|
import com.android.internal.util.CollectionUtils;
|
||||||
import com.android.internal.util.DumpUtils;
|
import com.android.internal.util.DumpUtils;
|
||||||
import com.android.internal.util.FastXmlSerializer;
|
import com.android.internal.util.FastXmlSerializer;
|
||||||
import com.android.internal.util.FunctionalUtils;
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
import com.android.internal.util.function.TriPredicate;
|
import com.android.internal.util.function.TriPredicate;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package com.android.server.notification;
|
|||||||
|
|
||||||
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
||||||
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
|
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
|
||||||
import static android.app.Notification.CATEGORY_CALL;
|
|
||||||
import static android.app.Notification.FLAG_AUTO_CANCEL;
|
import static android.app.Notification.FLAG_AUTO_CANCEL;
|
||||||
import static android.app.Notification.FLAG_BUBBLE;
|
import static android.app.Notification.FLAG_BUBBLE;
|
||||||
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
|
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
|
||||||
@@ -5236,141 +5235,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
nr.getSbn().getKey()).getNotification().isBubbleNotification());
|
nr.getSbn().getKey()).getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
|
|
||||||
// Bubbles are allowed!
|
|
||||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
|
|
||||||
|
|
||||||
// Give it bubble metadata
|
|
||||||
Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
|
|
||||||
// Give it a person
|
|
||||||
Person person = new Person.Builder()
|
|
||||||
.setName("bubblebot")
|
|
||||||
.build();
|
|
||||||
// Make it a phone call
|
|
||||||
Notification.Builder nb = new Notification.Builder(mContext,
|
|
||||||
mTestNotificationChannel.getId())
|
|
||||||
.setCategory(CATEGORY_CALL)
|
|
||||||
.addPerson(person)
|
|
||||||
.setContentTitle("foo")
|
|
||||||
.setBubbleMetadata(data)
|
|
||||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
|
||||||
|
|
||||||
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
|
|
||||||
"testFlagBubbleNotifs_flag_phonecall", mUid, 0,
|
|
||||||
nb.build(), new UserHandle(mUid), null, 0);
|
|
||||||
// Make sure it has foreground service
|
|
||||||
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
|
|
||||||
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
|
||||||
|
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
|
||||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
// yes phone call, yes person, yes foreground service, yes bubble
|
|
||||||
assertTrue(mService.getNotificationRecord(
|
|
||||||
sbn.getKey()).getNotification().isBubbleNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
|
|
||||||
// Bubbles are allowed!
|
|
||||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
|
|
||||||
|
|
||||||
// Give it bubble metadata
|
|
||||||
Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
|
|
||||||
// Give it a person
|
|
||||||
Person person = new Person.Builder()
|
|
||||||
.setName("bubblebot")
|
|
||||||
.build();
|
|
||||||
// Make it a phone call
|
|
||||||
Notification.Builder nb = new Notification.Builder(mContext,
|
|
||||||
mTestNotificationChannel.getId())
|
|
||||||
.setCategory(CATEGORY_CALL)
|
|
||||||
.addPerson(person)
|
|
||||||
.setContentTitle("foo")
|
|
||||||
.setBubbleMetadata(data)
|
|
||||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
|
||||||
|
|
||||||
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
|
|
||||||
nb.build(), new UserHandle(mUid), null, 0);
|
|
||||||
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
|
||||||
|
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
|
||||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
// yes phone call, yes person, NO foreground service, no bubble
|
|
||||||
assertFalse(mService.getNotificationRecord(
|
|
||||||
sbn.getKey()).getNotification().isBubbleNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
|
|
||||||
// Bubbles are allowed!
|
|
||||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
|
|
||||||
|
|
||||||
// Give it bubble metadata
|
|
||||||
Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
|
|
||||||
// Make it a phone call
|
|
||||||
Notification.Builder nb = new Notification.Builder(mContext,
|
|
||||||
mTestNotificationChannel.getId())
|
|
||||||
.setCategory(CATEGORY_CALL)
|
|
||||||
.setContentTitle("foo")
|
|
||||||
.setBubbleMetadata(data)
|
|
||||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
|
||||||
|
|
||||||
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
|
|
||||||
"testFlagBubbleNotifs_noFlag_phonecall_noPerson", mUid, 0,
|
|
||||||
nb.build(), new UserHandle(mUid), null, 0);
|
|
||||||
// Make sure it has foreground service
|
|
||||||
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
|
|
||||||
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
|
||||||
|
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
|
||||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
// yes phone call, yes foreground service, BUT NO person, no bubble
|
|
||||||
assertFalse(mService.getNotificationRecord(
|
|
||||||
sbn.getKey()).getNotification().isBubbleNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
|
|
||||||
// Bubbles are allowed!
|
|
||||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
|
|
||||||
|
|
||||||
// Give it bubble metadata
|
|
||||||
Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
|
|
||||||
// Give it a person
|
|
||||||
Person person = new Person.Builder()
|
|
||||||
.setName("bubblebot")
|
|
||||||
.build();
|
|
||||||
// No category
|
|
||||||
Notification.Builder nb = new Notification.Builder(mContext,
|
|
||||||
mTestNotificationChannel.getId())
|
|
||||||
.addPerson(person)
|
|
||||||
.setContentTitle("foo")
|
|
||||||
.setBubbleMetadata(data)
|
|
||||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
|
||||||
|
|
||||||
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
|
|
||||||
"testFlagBubbleNotifs_noFlag_phonecall_noCategory", mUid, 0,
|
|
||||||
nb.build(), new UserHandle(mUid), null, 0);
|
|
||||||
// Make sure it has foreground service
|
|
||||||
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
|
|
||||||
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
|
||||||
|
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
|
||||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
// yes person, yes foreground service, BUT NO call, no bubble
|
|
||||||
assertFalse(mService.getNotificationRecord(
|
|
||||||
sbn.getKey()).getNotification().isBubbleNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
|
public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
|
||||||
// Bubbles are NOT allowed!
|
// Bubbles are NOT allowed!
|
||||||
@@ -5431,77 +5295,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
nr.getSbn().getKey()).getNotification().isBubbleNotification());
|
nr.getSbn().getKey()).getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
|
|
||||||
// Bubbles are not allowed!
|
|
||||||
setUpPrefsForBubbles(PKG, mUid, false /* global */, true /* app */, true /* channel */);
|
|
||||||
|
|
||||||
// Give it bubble metadata
|
|
||||||
Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
|
|
||||||
// Give it a person
|
|
||||||
Person person = new Person.Builder()
|
|
||||||
.setName("bubblebot")
|
|
||||||
.build();
|
|
||||||
// Make it a phone call
|
|
||||||
Notification.Builder nb = new Notification.Builder(mContext,
|
|
||||||
mTestNotificationChannel.getId())
|
|
||||||
.setCategory(CATEGORY_CALL)
|
|
||||||
.addPerson(person)
|
|
||||||
.setContentTitle("foo")
|
|
||||||
.setBubbleMetadata(data)
|
|
||||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
|
||||||
|
|
||||||
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
|
|
||||||
"testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0,
|
|
||||||
nb.build(), new UserHandle(mUid), null, 0);
|
|
||||||
// Make sure it has foreground service
|
|
||||||
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
|
|
||||||
|
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
|
|
||||||
sbn.getId(), sbn.getNotification(), sbn.getUserId());
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
// yes phone call, yes person, yes foreground service, but not allowed, no bubble
|
|
||||||
assertFalse(mService.getNotificationRecord(
|
|
||||||
sbn.getKey()).getNotification().isBubbleNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
|
|
||||||
// Bubbles are allowed, but not on channel.
|
|
||||||
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, false /* channel */);
|
|
||||||
|
|
||||||
// Give it bubble metadata
|
|
||||||
Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
|
|
||||||
// Give it a person
|
|
||||||
Person person = new Person.Builder()
|
|
||||||
.setName("bubblebot")
|
|
||||||
.build();
|
|
||||||
// Make it a phone call
|
|
||||||
Notification.Builder nb = new Notification.Builder(mContext,
|
|
||||||
mTestNotificationChannel.getId())
|
|
||||||
.setCategory(CATEGORY_CALL)
|
|
||||||
.addPerson(person)
|
|
||||||
.setContentTitle("foo")
|
|
||||||
.setBubbleMetadata(data)
|
|
||||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
|
||||||
|
|
||||||
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
|
|
||||||
"testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", mUid, 0,
|
|
||||||
nb.build(), new UserHandle(mUid), null, 0);
|
|
||||||
// Make sure it has foreground service
|
|
||||||
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
|
|
||||||
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
|
||||||
|
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
|
|
||||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
// yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
|
|
||||||
assertFalse(mService.getNotificationRecord(
|
|
||||||
sbn.getKey()).getNotification().isBubbleNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
|
public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
|
||||||
final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
|
final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
|
||||||
|
|||||||
Reference in New Issue
Block a user