Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef7b5342 authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge "Bubbles Policy: remove phonecalls" into rvc-dev

parents 9c493f47 97c9ee87
Loading
Loading
Loading
Loading
+3 −36
Original line number Diff line number Diff line
@@ -15,9 +15,7 @@
*/
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_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_NOT_RESIZABLE;
@@ -25,7 +23,6 @@ import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR
import android.app.ActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Person;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -34,8 +31,6 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;

import java.util.ArrayList;

/**
 * Determines whether a bubble can be shown for this notification
 */
@@ -152,42 +147,14 @@ public class BubbleExtractor implements NotificationSignalExtractor {
                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(
                    notification.getNotificationStyle());
            if (!isMessageStyle && (peopleList == null || peopleList.isEmpty())) {
                logBubbleError(r.getKey(), "Must have a person and be "
                        + "Notification.MessageStyle or Notification.CATEGORY_CALL");
                return false;
            }

            // 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");
            if (!isMessageStyle) {
                logBubbleError(r.getKey(), "must be Notification.MessageStyle");
                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;
        }

        /**
         * @return whether the user has enabled the provided notification to bubble, does not
+0 −1
Original line number Diff line number Diff line
@@ -243,7 +243,6 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.TriPredicate;
+0 −207
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.server.notification;

import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
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_BUBBLE;
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
@@ -5236,141 +5235,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                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
    public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
        // Bubbles are NOT allowed!
@@ -5431,77 +5295,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                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
    public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
        final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);