summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml10
-rw-r--r--packages/SystemUI/res/values/strings.xml6
-rw-r--r--packages/SystemUI/res/values/styles.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java156
5 files changed, 204 insertions, 6 deletions
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 759d1ed0393f..b1cb6cf91cb8 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -29,6 +29,7 @@
<!-- Package Info -->
<RelativeLayout
+ android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
@@ -140,6 +141,12 @@
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"
android:layout_width="wrap_content"
@@ -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"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 89e6da38ffa7..4bd997d9b989 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index d65e37d3e93e..1470dfa4d05d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -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>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index afe906c28ea5..b1ad30c940fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -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);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index b8d9b192aac4..01664b28dba1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -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
@@ -213,6 +216,27 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@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);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -324,6 +348,18 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@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 {
int originalImportance = mNotificationChannel.getImportance();
@@ -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
@@ -416,6 +485,40 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@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);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -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());
+ }
}