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

Commit c3e922b0 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Fix up bubble actions

- Remove them from the non-conversation controls
- Make sure to turn on bubbles globally if a person
is bubbled

Test: atest
Bug: 137397357
Change-Id: I5ae102d739acf4d821af8380287cdf21bca7abd9
parent dcd70d6e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.os.Handler;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -127,6 +128,8 @@ public class NotificationConversationInfo extends LinearLayout implements
            mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
        } else {
            mBubbleController.onUserCreatedBubbleFromNotification(mEntry);
            Settings.Global.putInt(
                    mContext.getContentResolver(), Settings.Global.NOTIFICATION_BUBBLES, 1);
        }
        closeControls(v, true);
    };
+3 −67
Original line number Diff line number Diff line
@@ -65,8 +65,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.BubbleExperimentConfig;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
@@ -102,7 +100,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    // standard controls
    private static final int ACTION_ALERT = 5;

    private TextView mBubbleDescriptionView;
    private TextView mPriorityDescriptionView;
    private TextView mSilentDescriptionView;

@@ -120,7 +117,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    private Set<NotificationChannel> mUniqueChannelsInRow;
    private NotificationChannel mSingleNotificationChannel;
    private int mStartingChannelImportance;
    private boolean mStartedAsBubble;
    private boolean mWasShownHighPriority;
    private boolean mPressedApply;
    private boolean mPresentingChannelEditorDialog = false;
@@ -130,14 +126,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
     * level; non-null once the user takes an action which indicates an explicit preference.
     */
    @Nullable private Integer mChosenImportance;
    /**
     * The last bubble setting chosen by the user. Null if the user has not chosen a bubble level;
     * non-null once the user takes an action which indicates an explicit preference.
     */
    @Nullable private Boolean mChosenBubbleEnabled;
    private boolean mIsSingleDefaultChannel;
    private boolean mIsNonblockable;
    private boolean mIsBubbleable;
    private NotificationEntry mEntry;
    private StatusBarNotification mSbn;
    private AnimatorSet mExpandAnimation;
@@ -149,8 +139,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    private NotificationGuts mGutsContainer;
    private Drawable mPkgIcon;

    private BubbleController mBubbleController;

    /** Whether this view is being shown as part of the blocking helper. */
    private boolean mIsForBlockingHelper;

@@ -167,9 +155,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    private OnClickListener mOnAlert = v -> {
        mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
        mChosenImportance = IMPORTANCE_DEFAULT;
        if (mStartedAsBubble) {
            mChosenBubbleEnabled = false;
        }
        applyAlertingBehavior(BEHAVIOR_ALERTING, true /* userTriggered */);
    };

@@ -177,18 +162,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    private OnClickListener mOnSilent = v -> {
        mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
        mChosenImportance = IMPORTANCE_LOW;
        if (mStartedAsBubble) {
            mChosenBubbleEnabled = false;
        }
        applyAlertingBehavior(BEHAVIOR_SILENT, true /* userTriggered */);
    };

    /** Used by standard ui (in an experiment) {@see BubbleExperimentConfig#allowNotifBubbleMenu} */
    private OnClickListener mOnBubble = v -> {
        mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
        mChosenBubbleEnabled = true;
        applyAlertingBehavior(BEHAVIOR_BUBBLE, true /* userTriggered */);
    };

    // used by standard ui
    private OnClickListener mOnDismissSettings = v -> {
@@ -255,7 +231,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    protected void onFinishInflate() {
        super.onFinishInflate();

        mBubbleDescriptionView = findViewById(R.id.bubble_summary);
        mPriorityDescriptionView = findViewById(R.id.alert_summary);
        mSilentDescriptionView = findViewById(R.id.silence_summary);
    }
@@ -320,7 +295,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        mMetricsLogger = Dependency.get(MetricsLogger.class);
        mVisualStabilityManager = visualStabilityManager;
        mChannelEditorDialogController = Dependency.get(ChannelEditorDialogController.class);
        mBubbleController = Dependency.get(BubbleController.class);
        mPackageName = pkg;
        mUniqueChannelsInRow = uniqueChannelsInRow;
        mNumUniqueChannelsInRow = uniqueChannelsInRow.size();
@@ -352,9 +326,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
                    && numTotalChannels == 1;
        }

        mIsBubbleable = mEntry.getBubbleMetadata() != null;
        mStartedAsBubble = mEntry.isBubble();

        bindHeader();
        bindChannelDetails();

@@ -402,7 +373,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
            findViewById(R.id.non_configurable_text).setVisibility(GONE);
            findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE);
            findViewById(R.id.interruptiveness_settings).setVisibility(VISIBLE);
            findViewById(R.id.bubble).setVisibility(mIsBubbleable ? VISIBLE : GONE);
        }

        View turnOffButton = findViewById(R.id.turn_off_notifications);
@@ -416,14 +386,10 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G

        View silent = findViewById(R.id.silence);
        View alert = findViewById(R.id.alert);
        View bubble = findViewById(R.id.bubble);
        silent.setOnClickListener(mOnSilent);
        alert.setOnClickListener(mOnAlert);
        bubble.setOnClickListener(mOnBubble);

        int behavior = mStartedAsBubble
                ? BEHAVIOR_BUBBLE
                : mWasShownHighPriority
        int behavior = mWasShownHighPriority
                        ? BEHAVIOR_ALERTING
                        : BEHAVIOR_SILENT;
        applyAlertingBehavior(behavior, false /* userTriggered */);
@@ -587,14 +553,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
                }
            }

            if (mChosenBubbleEnabled != null && mStartedAsBubble != mChosenBubbleEnabled) {
                if (mChosenBubbleEnabled) {
                    mBubbleController.onUserCreatedBubbleFromNotification(mEntry);
                } else {
                    mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
                }
            }

            Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
            bgHandler.post(
                    new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
@@ -630,7 +588,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
            TransitionManager.beginDelayedTransition(this, transition);
        }

        View bubble = findViewById(R.id.bubble);
        View alert = findViewById(R.id.alert);
        View silence = findViewById(R.id.silence);

@@ -638,33 +595,18 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
            case BEHAVIOR_ALERTING:
                mPriorityDescriptionView.setVisibility(VISIBLE);
                mSilentDescriptionView.setVisibility(GONE);
                mBubbleDescriptionView.setVisibility(GONE);
                post(() -> {
                    alert.setSelected(true);
                    silence.setSelected(false);
                    bubble.setSelected(false);
                });
                break;

            case BEHAVIOR_SILENT:
                mSilentDescriptionView.setVisibility(VISIBLE);
                mPriorityDescriptionView.setVisibility(GONE);
                mBubbleDescriptionView.setVisibility(GONE);
                post(() -> {
                    alert.setSelected(false);
                    silence.setSelected(true);
                    bubble.setSelected(false);
                });
                break;

            case BEHAVIOR_BUBBLE:
                mBubbleDescriptionView.setVisibility(VISIBLE);
                mSilentDescriptionView.setVisibility(GONE);
                mPriorityDescriptionView.setVisibility(GONE);
                post(() -> {
                    alert.setSelected(false);
                    silence.setSelected(false);
                    bubble.setSelected(true);
                });
                break;

@@ -673,9 +615,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        }

        boolean isAChange = mWasShownHighPriority != (behavior == BEHAVIOR_ALERTING);
        boolean isABubbleChange = mStartedAsBubble != (behavior == BEHAVIOR_BUBBLE);
        TextView done = findViewById(R.id.done);
        done.setText((isAChange || isABubbleChange)
        done.setText(isAChange
                ? R.string.inline_ok_button
                : R.string.inline_done_button);
    }
@@ -684,7 +625,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        switch (action) {
            case ACTION_UNDO:
                mChosenImportance = mStartingChannelImportance;
                mChosenBubbleEnabled = mStartedAsBubble;
                break;
            case ACTION_DELIVER_SILENTLY:
                mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
@@ -767,9 +707,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        if (mChosenImportance != null) {
            mStartingChannelImportance = mChosenImportance;
        }
        if (mChosenBubbleEnabled != null) {
            mStartedAsBubble = mChosenBubbleEnabled;
        }
        mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;

        if (mIsForBlockingHelper) {
@@ -969,9 +906,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    }

    @Retention(SOURCE)
    @IntDef({BEHAVIOR_ALERTING, BEHAVIOR_SILENT, BEHAVIOR_BUBBLE})
    @IntDef({BEHAVIOR_ALERTING, BEHAVIOR_SILENT})
    private @interface AlertingBehavior {}
    private static final int BEHAVIOR_ALERTING = 0;
    private static final int BEHAVIOR_SILENT = 1;
    private static final int BEHAVIOR_BUBBLE = 2;
}
+2 −179
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.systemui.statusbar.notification.row;

import static android.app.Notification.FLAG_BUBBLE;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
@@ -50,13 +49,10 @@ import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings;
@@ -76,9 +72,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.BubblesTestActivity;
import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -116,8 +109,6 @@ public class NotificationInfoTest extends SysuiTestCase {
    private Set<NotificationChannel> mDefaultNotificationChannelSet = new HashSet<>();
    private StatusBarNotification mSbn;
    private NotificationEntry mEntry;
    private StatusBarNotification mBubbleSbn;
    private NotificationEntry mBubbleEntry;

    @Rule
    public MockitoRule mockito = MockitoJUnit.rule();
@@ -131,8 +122,6 @@ public class NotificationInfoTest extends SysuiTestCase {
    private NotificationBlockingHelperManager mBlockingHelperManager;
    @Mock
    private VisualStabilityManager mVisualStabilityManager;
    @Mock
    private BubbleController mBubbleController;

    @Before
    public void setUp() throws Exception {
@@ -143,7 +132,6 @@ public class NotificationInfoTest extends SysuiTestCase {

        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
        mDependency.injectTestDependency(BubbleController.class, mBubbleController);
        // Inflate the layout
        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
@@ -185,15 +173,6 @@ public class NotificationInfoTest extends SysuiTestCase {
                new Notification(), UserHandle.CURRENT, null, 0);
        mEntry = new NotificationEntryBuilder().setSbn(mSbn).build();

        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0,
                new Intent(mContext, BubblesTestActivity.class), 0);
        mBubbleSbn = new SbnBuilder(mSbn).setBubbleMetadata(
                new Notification.BubbleMetadata.Builder()
                        .setIntent(bubbleIntent)
                        .setIcon(Icon.createWithResource(mContext, R.drawable.android)).build())
                .build();
        mBubbleEntry = new NotificationEntryBuilder().setSbn(mBubbleSbn).build();

        Settings.Secure.putInt(mContext.getContentResolver(),
                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
    }
@@ -765,7 +744,7 @@ public class NotificationInfoTest extends SysuiTestCase {
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                mEntry,
                null,
                null,
                null,
@@ -785,7 +764,7 @@ public class NotificationInfoTest extends SysuiTestCase {
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                mEntry,
                null,
                null,
                null,
@@ -796,162 +775,6 @@ public class NotificationInfoTest extends SysuiTestCase {
        assertTrue(mNotificationInfo.findViewById(R.id.silence).isSelected());
    }

    @Test
    public void testBindNotification_bubbleIsSelected() throws Exception {
        mBubbleEntry.getSbn().getNotification().flags |= FLAG_BUBBLE;
        mNotificationInfo.bindNotification(
                mMockPackageManager,
                mMockINotificationManager,
                mVisualStabilityManager,
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                null,
                null,
                null,
                true,
                false,
                IMPORTANCE_DEFAULT,
                true);

        View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
        assertEquals(View.VISIBLE, bubbleView.getVisibility());
        assertTrue(bubbleView.isSelected());
    }

    @Test
    public void testBindNotification_whenCanBubble() throws Exception {
        mNotificationInfo.bindNotification(
                mMockPackageManager,
                mMockINotificationManager,
                mVisualStabilityManager,
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                null,
                null,
                null,
                true,
                false,
                IMPORTANCE_DEFAULT,
                true);

        View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
        assertEquals(View.VISIBLE, bubbleView.getVisibility());
        assertFalse(bubbleView.isSelected());
    }

    @Test
    public void testBindNotification_whenCantBubble() throws Exception {
        mNotificationInfo.bindNotification(
                mMockPackageManager,
                mMockINotificationManager,
                mVisualStabilityManager,
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mEntry,
                null,
                null,
                null,
                true,
                false,
                IMPORTANCE_DEFAULT,
                true);
        View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
        assertEquals(View.GONE, bubbleView.getVisibility());
    }

    @Test
    public void testBubble_promotesBubble() throws Exception {
        mNotificationInfo.bindNotification(
                mMockPackageManager,
                mMockINotificationManager,
                mVisualStabilityManager,
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                null,
                null,
                null,
                true,
                false,
                IMPORTANCE_DEFAULT,
                true);

        assertFalse(mBubbleEntry.isBubble());

        // Promote it
        mNotificationInfo.findViewById(R.id.bubble).performClick();
        mNotificationInfo.findViewById(R.id.done).performClick();
        mNotificationInfo.handleCloseControls(true, false);

        verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
    }

    @Test
    public void testAlert_demotesBubble() throws Exception {
        mBubbleEntry.getSbn().getNotification().flags |= FLAG_BUBBLE;

        mNotificationInfo.bindNotification(
                mMockPackageManager,
                mMockINotificationManager,
                mVisualStabilityManager,
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                null,
                null,
                null,
                true,
                false,
                IMPORTANCE_DEFAULT,
                true);

        assertTrue(mBubbleEntry.isBubble());

        // Demote it
        mNotificationInfo.findViewById(R.id.alert).performClick();
        mNotificationInfo.findViewById(R.id.done).performClick();
        mNotificationInfo.handleCloseControls(true, false);

        verify(mBubbleController, times(1)).onUserDemotedBubbleFromNotification(mBubbleEntry);
    }

    @Test
    public void testSilence_demotesBubble() throws Exception {
        mBubbleEntry.getSbn().getNotification().flags |= FLAG_BUBBLE;

        mNotificationInfo.bindNotification(
                mMockPackageManager,
                mMockINotificationManager,
                mVisualStabilityManager,
                TEST_PACKAGE_NAME,
                mNotificationChannel,
                mNotificationChannelSet,
                mBubbleEntry,
                null,
                null,
                null,
                true,
                false,
                IMPORTANCE_DEFAULT,
                true);

        assertTrue(mBubbleEntry.isBubble());

        // Demote it
        mNotificationInfo.findViewById(R.id.silence).performClick();
        mNotificationInfo.findViewById(R.id.done).performClick();
        mNotificationInfo.handleCloseControls(true, false);

        verify(mBubbleController, times(1)).onUserDemotedBubbleFromNotification(mBubbleEntry);
    }

    @Test
    public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
        mNotificationInfo.bindNotification(