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

Commit 874b0091 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Don't allow foreground notis to be blocked inline." into pi-dev

parents b87b0327 e0341487
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

    <!-- Package Info -->
    <RelativeLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipChildren="false"
@@ -139,6 +140,12 @@
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                style="@style/TextAppearance.NotificationInfo.Button"/>
            <TextView
                android:id="@+id/minimize"
                android:text="@string/inline_minimize_button"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                style="@style/TextAppearance.NotificationInfo.Button" />
            <TextView
                android:id="@+id/keep"
                android:text="@string/inline_keep_button"
@@ -157,10 +164,11 @@
        android:visibility="gone"
        android:orientation="horizontal" >
        <TextView
            android:id="@+id/confirmation_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/notification_channel_disabled"
            style="@style/TextAppearance.NotificationInfo.Secondary.Warning"/>
            style="@style/TextAppearance.NotificationInfo.Confirmation"/>
        <TextView
            android:id="@+id/undo"
            android:layout_width="wrap_content"
+6 −0
Original line number Diff line number Diff line
@@ -1526,6 +1526,9 @@
    <!-- Notification Inline Controls: Shown when a channel's notifications are currently blocked -->
    <string name="notification_channel_disabled">You won\'t see these notifications anymore</string>

    <!-- Notification inline controls: Shown when a channel's notifications are minimized -->
    <string name="notification_channel_minimized">These notifications will be minimized</string>

    <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
    <string name="inline_blocking_helper">You usually dismiss these notifications.
    \nKeep showing them?</string>
@@ -1539,6 +1542,9 @@
    <!-- Notification inline controls: keep getting notifications button -->
    <string name="inline_keep_button">Keep showing</string>

    <!-- Notification inline controls: minimize notifications button -->
    <string name="inline_minimize_button">Minimize</string>

    <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
    <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>

+6 −0
Original line number Diff line number Diff line
@@ -459,6 +459,12 @@
        <item name="android:alpha">0.87</item>
    </style>

    <style name="TextAppearance.NotificationInfo.Confirmation">
        <item name="android:textColor">?android:attr/textColorPrimary</item>
        <item name="android:textSize">14sp</item>
        <item name="android:alpha">0.87</item>
    </style>

    <style name="TextAppearance.NotificationInfo.Secondary">
        <item name="android:textColor">?android:attr/textColorPrimary</item>
        <item name="android:textSize">14sp</item>
+27 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar;

import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;

import android.animation.Animator;
@@ -39,6 +40,7 @@ import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -73,6 +75,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    private boolean mNonblockable;
    private StatusBarNotification mSbn;
    private AnimatorSet mExpandAnimation;
    private boolean mIsForeground;

    private CheckSaveListener mCheckSaveListener;
    private OnSettingsClickListener mOnSettingsClickListener;
@@ -84,7 +87,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        closeControls(v);
    };

    private OnClickListener mOnStopNotifications = v -> {
    private OnClickListener mOnStopMinNotifications = v -> {
        swapContent(false);
    };

@@ -150,6 +153,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        mSingleNotificationChannel = notificationChannel;
        mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
        mNegativeUserSentiment = negativeUserSentiment;
        mIsForeground =
                (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;

        int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
                pkg, mAppUid, false /* includeDeleted */);
@@ -290,14 +295,23 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G

    private void bindButtons() {
        View block =  findViewById(R.id.block);
        block.setOnClickListener(mOnStopNotifications);
        block.setOnClickListener(mOnStopMinNotifications);
        TextView keep = findViewById(R.id.keep);
        keep.setOnClickListener(mOnKeepShowing);
        findViewById(R.id.undo).setOnClickListener(mOnUndo);
        View minimize = findViewById(R.id.minimize);
        minimize.setOnClickListener(mOnStopMinNotifications);

        if (mNonblockable) {
            keep.setText(R.string.notification_done);
            block.setVisibility(GONE);
            minimize.setVisibility(GONE);
        } else if (mIsForeground) {
            block.setVisibility(GONE);
            minimize.setVisibility(VISIBLE);
        } else if (!mIsForeground) {
            block.setVisibility(VISIBLE);
            minimize.setVisibility(GONE);
        }

        // app settings link
@@ -306,7 +320,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
                mSbn.getId(), mSbn.getTag());
        if (settingsIntent != null
                && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
            settingsLinkView.setVisibility(View.VISIBLE);
            settingsLinkView.setVisibility(VISIBLE);
            settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
                    mSbn.getNotification().getSettingsText()));
            settingsLinkView.setOnClickListener((View view) -> {
@@ -322,14 +336,21 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
            mExpandAnimation.cancel();
        }

        View prompt = findViewById(R.id.prompt);
        ViewGroup confirmation = findViewById(R.id.confirmation);
        TextView confirmationText = findViewById(R.id.confirmation_text);
        View header = findViewById(R.id.header);

        if (showPrompt) {
            mChosenImportance = mStartingUserImportance;
        } else if (mIsForeground) {
            mChosenImportance = IMPORTANCE_MIN;
            confirmationText.setText(R.string.notification_channel_minimized);
        } else {
            mChosenImportance = IMPORTANCE_NONE;
            confirmationText.setText(R.string.notification_channel_disabled);
        }

        View prompt = findViewById(R.id.prompt);
        View confirmation = findViewById(R.id.confirmation);
        ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
                prompt.getAlpha(), showPrompt ? 1f : 0f);
        promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
@@ -339,6 +360,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G

        prompt.setVisibility(showPrompt ? VISIBLE : GONE);
        confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
        header.setVisibility(showPrompt ? VISIBLE : GONE);

        mExpandAnimation = new AnimatorSet();
        mExpandAnimation.playTogether(promptAnim, confirmAnim);
+156 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar;

import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
import static android.view.View.GONE;
@@ -147,6 +149,7 @@ public class NotificationInfoTest extends SysuiTestCase {
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
        final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
        assertTrue(textView.getText().toString().contains("App Name"));
        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
    }

    @Test
@@ -212,6 +215,27 @@ public class NotificationInfoTest extends SysuiTestCase {
        assertEquals(VISIBLE, textView.getVisibility());
    }

    @Test
    public void testBindNotification_BlockButton() throws Exception {
       mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
        final View block = mNotificationInfo.findViewById(R.id.block);
        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
        assertEquals(VISIBLE, block.getVisibility());
        assertEquals(GONE, minimize.getVisibility());
    }

    @Test
    public void testBindNotification_MinButton() throws Exception {
        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
        final View block = mNotificationInfo.findViewById(R.id.block);
        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
        assertEquals(GONE, block.getVisibility());
        assertEquals(VISIBLE, minimize.getVisibility());
    }

    @Test
    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
@@ -323,6 +347,18 @@ public class NotificationInfoTest extends SysuiTestCase {
                anyString(), eq(TEST_UID), any());
    }

    @Test
    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedMin()
            throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.findViewById(R.id.minimize).performClick();
        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), any());
    }

    @Test
    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
            throws Exception {
@@ -377,6 +413,39 @@ public class NotificationInfoTest extends SysuiTestCase {
                anyString(), eq(TEST_UID), updated.capture());
        assertTrue((updated.getValue().getUserLockedFields()
                & USER_LOCKED_IMPORTANCE) != 0);
        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
    }

    @Test
    public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null,
                null, Collections.singleton(TEST_PACKAGE_NAME));
        mNotificationInfo.findViewById(R.id.minimize).performClick();
        waitForUndoButton();
        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), any());
    }

    @Test
    public void testMinChangedCallsUpdateNotificationChannel() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.findViewById(R.id.minimize).performClick();
        waitForUndoButton();
        mNotificationInfo.handleCloseControls(true, false);

        ArgumentCaptor<NotificationChannel> updated =
                ArgumentCaptor.forClass(NotificationChannel.class);
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), updated.capture());
        assertTrue((updated.getValue().getUserLockedFields()
                & USER_LOCKED_IMPORTANCE) != 0);
        assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
    }

    @Test
@@ -415,6 +484,40 @@ public class NotificationInfoTest extends SysuiTestCase {
        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
    }

    @Test
    public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.findViewById(R.id.minimize).performClick();
        waitForUndoButton();
        mNotificationInfo.findViewById(R.id.undo).performClick();
        waitForStopButton();
        mNotificationInfo.handleCloseControls(true, false);

        ArgumentCaptor<NotificationChannel> updated =
                ArgumentCaptor.forClass(NotificationChannel.class);
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), updated.capture());
        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
    }

    @Test
    public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
                Collections.singleton(TEST_PACKAGE_NAME));

        mNotificationInfo.findViewById(R.id.minimize).performClick();
        waitForUndoButton();
        mNotificationInfo.handleCloseControls(false, false);
        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
    }

    @Test
    public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
@@ -557,4 +660,57 @@ public class NotificationInfoTest extends SysuiTestCase {
    public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
        assertFalse(mNotificationInfo.willBeRemoved());
    }

    @Test
    public void testUndoText_min() throws Exception {
        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
                Collections.singleton(TEST_PACKAGE_NAME));

        mNotificationInfo.findViewById(R.id.minimize).performClick();
        waitForUndoButton();
        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
        assertTrue(confirmationText.getText().toString().contains("minimized"));
    }

    @Test
    public void testUndoText_block() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
                Collections.singleton(TEST_PACKAGE_NAME));

        mNotificationInfo.findViewById(R.id.block).performClick();
        waitForUndoButton();
        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
        assertTrue(confirmationText.getText().toString().contains("won't see"));
    }

    @Test
    public void testNoHeaderOnConfirmation() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
                Collections.singleton(TEST_PACKAGE_NAME));

        mNotificationInfo.findViewById(R.id.block).performClick();
        waitForUndoButton();
        assertEquals(GONE, mNotificationInfo.findViewById(R.id.header).getVisibility());
    }

    @Test
    public void testHeaderOnUndo() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
                Collections.singleton(TEST_PACKAGE_NAME));

        mNotificationInfo.findViewById(R.id.block).performClick();
        waitForUndoButton();
        mNotificationInfo.findViewById(R.id.undo).performClick();
        waitForStopButton();
        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
    }
}