Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java +94 −10 Original line number Diff line number Diff line Loading @@ -16,12 +16,18 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; Loading @@ -36,7 +42,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Notification; import android.app.Person; import android.content.Context; import android.graphics.drawable.Icon; import android.os.AsyncTask; import android.os.CancellationSignal; import android.os.Handler; Loading Loading @@ -66,6 +74,7 @@ import com.android.systemui.statusbar.notification.promoted.shared.model.Promote import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction; import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder; Loading Loading @@ -155,8 +164,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase { @Test public void testIncreasedHeadsUpBeingUsed() { BindParams params = new BindParams(); params.usesIncreasedHeadsUpHeight = true; BindParams params = new BindParams(false, false, /* usesIncreasedHeadsUpHeight */ true, REDACTION_TYPE_NONE); Notification.Builder builder = spy(mBuilder); mNotificationInflater.inflateNotificationViews( mRow.getEntry(), Loading @@ -166,14 +175,15 @@ public class NotificationContentInflaterTest extends SysuiTestCase { FLAG_CONTENT_VIEW_ALL, builder, mContext, mContext, mSmartReplyStateInflater); verify(builder).createHeadsUpContentView(true); } @Test public void testIncreasedHeightBeingUsed() { BindParams params = new BindParams(); params.usesIncreasedHeight = true; BindParams params = new BindParams(false, /* usesIncreasedHeight */ true, false, REDACTION_TYPE_NONE); Notification.Builder builder = spy(mBuilder); mNotificationInflater.inflateNotificationViews( mRow.getEntry(), Loading @@ -183,6 +193,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { FLAG_CONTENT_VIEW_ALL, builder, mContext, mContext, mSmartReplyStateInflater); verify(builder).createContentView(true); } Loading @@ -207,7 +218,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getEntry().getSbn().getNotification().contentView = new RemoteViews(mContext.getPackageName(), com.android.systemui.res.R.layout.status_bar); inflateAndWait(true /* expectingException */, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow); REDACTION_TYPE_NONE, mRow); assertTrue(mRow.getPrivateLayout().getChildCount() == 0); verify(mRow, times(0)).onNotificationUpdated(); } Loading @@ -227,7 +238,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getEntry(), mRow, FLAG_CONTENT_VIEW_ALL, new BindParams(), new BindParams(false, false, false, REDACTION_TYPE_NONE), false /* forceInflate */, null /* callback */); Assert.assertNull(mRow.getEntry().getRunningTask()); Loading Loading @@ -287,7 +298,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(), R.layout.custom_view_dark)); RemoteViews decoratedMediaView = mBuilder.createContentView(); Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!", assertFalse("The decorated media style doesn't allow a view to be reapplied!", NotificationContentInflater.canReapplyRemoteView(mediaView, decoratedMediaView)); } Loading Loading @@ -385,7 +396,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getPrivateLayout().removeAllViews(); mRow.getEntry().getSbn().getNotification().contentView = new RemoteViews(mContext.getPackageName(), R.layout.invalid_notification_height); inflateAndWait(true, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow); inflateAndWait(true, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, mRow); assertEquals(0, mRow.getPrivateLayout().getChildCount()); verify(mRow, times(0)).onNotificationUpdated(); } Loading Loading @@ -455,16 +467,88 @@ public class NotificationContentInflaterTest extends SysuiTestCase { assertNull(mRow.getEntry().getPromotedNotificationContentModel()); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testSensitiveContentPublicView_messageStyle() throws Exception { String displayName = "Display Name"; String messageText = "Message Text"; String contentText = "Content Text"; Icon personIcon = Icon.createWithResource(mContext, com.android.systemui.res.R.drawable.ic_person); Person testPerson = new Person.Builder() .setName(displayName) .setIcon(personIcon) .build(); Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(testPerson); messagingStyle.addMessage(new Notification.MessagingStyle.Message(messageText, System.currentTimeMillis(), testPerson)); messagingStyle.setConversationType(Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL); messagingStyle.setShortcutIcon(personIcon); Notification messageNotif = new Notification.Builder(mContext).setSmallIcon( com.android.systemui.res.R.drawable.ic_person).setStyle(messagingStyle).build(); ExpandableNotificationRow row = mHelper.createRow(messageNotif); inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, row); NotificationContentView publicView = row.getPublicLayout(); assertNotNull(publicView); // The display name should be included, but not the content or message text assertFalse(hasText(publicView, messageText)); assertFalse(hasText(publicView, contentText)); assertTrue(hasText(publicView, displayName)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testSensitiveContentPublicView_nonMessageStyle() throws Exception { String contentTitle = "Content Title"; String contentText = "Content Text"; Notification notif = new Notification.Builder(mContext).setSmallIcon( com.android.systemui.res.R.drawable.ic_person) .setContentTitle(contentTitle) .setContentText(contentText) .build(); ExpandableNotificationRow row = mHelper.createRow(notif); inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, row); NotificationContentView publicView = row.getPublicLayout(); assertNotNull(publicView); assertFalse(hasText(publicView, contentText)); assertTrue(hasText(publicView, contentTitle)); // The standard public view should not use the content title or text inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_PUBLIC, row); publicView = row.getPublicLayout(); assertFalse(hasText(publicView, contentText)); assertFalse(hasText(publicView, contentTitle)); } private static boolean hasText(ViewGroup parent, CharSequence text) { for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); if (child instanceof ViewGroup) { if (hasText((ViewGroup) child, text)) { return true; } } else if (child instanceof TextView) { return ((TextView) child).getText().toString().contains(text); } } return false; } private static void inflateAndWait(NotificationContentInflater inflater, @InflationFlag int contentToInflate, ExpandableNotificationRow row) throws Exception { inflateAndWait(false /* expectingException */, inflater, contentToInflate, row); inflateAndWait(false /* expectingException */, inflater, contentToInflate, REDACTION_TYPE_NONE, row); } private static void inflateAndWait(boolean expectingException, NotificationContentInflater inflater, @InflationFlag int contentToInflate, @RedactionType int redactionType, ExpandableNotificationRow row) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(1); final ExceptionHolder exceptionHolder = new ExceptionHolder(); Loading Loading @@ -492,7 +576,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { row.getEntry(), row, contentToInflate, new BindParams(), new BindParams(false, false, false, redactionType), false /* forceInflate */, callback /* callback */); assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS)); Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt +124 −14 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.row import android.app.Notification import android.app.Person import android.content.Context import android.graphics.drawable.Icon import android.os.AsyncTask import android.os.Build import android.os.CancellationSignal Loading @@ -34,6 +35,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT import com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.notification.ConversationNotificationProcessor import com.android.systemui.statusbar.notification.collection.NotificationEntry Loading @@ -45,6 +50,7 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag Loading Loading @@ -138,14 +144,14 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @Test fun testIncreasedHeadsUpBeingUsed() { val params = BindParams() params.usesIncreasedHeadsUpHeight = true val params = BindParams(false, false, /* usesIncreasedHeadsUpHeight */ true, REDACTION_TYPE_NONE) val builder = spy(builder) notificationInflater.inflateNotificationViews( row.entry, row, params, true /* inflateSynchronously */, true, /* inflateSynchronously */ FLAG_CONTENT_VIEW_ALL, builder, mContext, Loading @@ -157,14 +163,13 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @Test fun testIncreasedHeightBeingUsed() { val params = BindParams() params.usesIncreasedHeight = true val params = BindParams(false, /* usesIncreasedHeight */ true, false, REDACTION_TYPE_NONE) val builder = spy(builder) notificationInflater.inflateNotificationViews( row.entry, row, params, true /* inflateSynchronously */, true, /* inflateSynchronously */ FLAG_CONTENT_VIEW_ALL, builder, mContext, Loading Loading @@ -193,15 +198,18 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { row.entry.sbn.notification.contentView = RemoteViews(mContext.packageName, R.layout.status_bar) inflateAndWait( true /* expectingException */, true, /* expectingException */ notificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, row, ) Assert.assertTrue(row.privateLayout.childCount == 0) verify(row, times(0)).onNotificationUpdated() } @Test fun testInflationOfSensitiveContentPublicView() {} @Test fun testAsyncTaskRemoved() { row.entry.abortTask() Loading @@ -217,8 +225,8 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { row.entry, row, FLAG_CONTENT_VIEW_ALL, BindParams(), false /* forceInflate */, BindParams(false, false, false, REDACTION_TYPE_NONE), false, /* forceInflate */ null, /* callback */ ) Assert.assertNull(row.entry.runningTask) Loading Loading @@ -431,7 +439,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { mContext.packageName, com.android.systemui.tests.R.layout.invalid_notification_height, ) inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, row) inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, row) Assert.assertEquals(0, row.privateLayout.childCount.toLong()) verify(row, times(0)).onNotificationUpdated() } Loading @@ -440,7 +448,13 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @Test fun testInflatePublicSingleLineView() { row.publicLayout.removeAllViews() inflateAndWait(false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, row) inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, REDACTION_TYPE_NONE, row, ) Assert.assertNotNull(row.publicLayout.mSingleLineView) Assert.assertTrue(row.publicLayout.mSingleLineView is HybridNotificationView) } Loading @@ -461,6 +475,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, REDACTION_TYPE_NONE, messagingRow, ) Assert.assertNotNull(messagingRow.publicLayout.mSingleLineView) Loading Loading @@ -530,6 +545,80 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { Assert.assertNull(row.entry.promotedNotificationContentModel) } @Test @Throws(java.lang.Exception::class) @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) fun testSensitiveContentPublicView_messageStyle() { val displayName = "Display Name" val messageText = "Message Text" val contentText = "Content Text" val personIcon = Icon.createWithResource(mContext, R.drawable.ic_person) val testPerson = Person.Builder().setName(displayName).setIcon(personIcon).build() val messagingStyle = Notification.MessagingStyle(testPerson) messagingStyle.addMessage( Notification.MessagingStyle.Message(messageText, System.currentTimeMillis(), testPerson) ) messagingStyle.setConversationType(Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL) messagingStyle.setShortcutIcon(personIcon) val messageNotif = Notification.Builder(mContext) .setSmallIcon(R.drawable.ic_person) .setStyle(messagingStyle) .build() val newRow: ExpandableNotificationRow = testHelper.createRow(messageNotif) inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, newRow, ) // The display name should be included, but not the content or message text val publicView = newRow.publicLayout Assert.assertNotNull(publicView) Assert.assertFalse(hasText(publicView, messageText)) Assert.assertFalse(hasText(publicView, contentText)) Assert.assertTrue(hasText(publicView, displayName)) } @Test @Throws(java.lang.Exception::class) @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) fun testSensitiveContentPublicView_nonMessageStyle() { val contentTitle = "Content Title" val contentText = "Content Text" val notif = Notification.Builder(mContext) .setSmallIcon(R.drawable.ic_person) .setContentTitle(contentTitle) .setContentText(contentText) .build() val newRow: ExpandableNotificationRow = testHelper.createRow(notif) inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, newRow, ) var publicView = newRow.publicLayout Assert.assertNotNull(publicView) Assert.assertFalse(hasText(publicView, contentText)) Assert.assertTrue(hasText(publicView, contentTitle)) // The standard public view should not use the content title or text inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_PUBLIC, newRow, ) publicView = newRow.publicLayout Assert.assertFalse(hasText(publicView, contentText)) Assert.assertFalse(hasText(publicView, contentTitle)) } private class ExceptionHolder { var exception: Exception? = null } Loading Loading @@ -568,13 +657,20 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @InflationFlag contentToInflate: Int, row: ExpandableNotificationRow, ) { inflateAndWait(false /* expectingException */, inflater, contentToInflate, row) inflateAndWait( false /* expectingException */, inflater, contentToInflate, REDACTION_TYPE_NONE, row, ) } private fun inflateAndWait( expectingException: Boolean, inflater: NotificationRowContentBinderImpl, @InflationFlag contentToInflate: Int, @RedactionType redactionType: Int, row: ExpandableNotificationRow, ) { val countDownLatch = CountDownLatch(1) Loading Loading @@ -603,12 +699,26 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { row.entry, row, contentToInflate, BindParams(), false /* forceInflate */, BindParams(false, false, false, redactionType), false, /* forceInflate */ callback, /* callback */ ) Assert.assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS)) exceptionHolder.exception?.let { throw it } } fun hasText(parent: ViewGroup, text: CharSequence): Boolean { for (i in 0 until parent.childCount) { val child = parent.getChildAt(i) if (child is ViewGroup) { if (hasText(child, text)) { return true } } else if (child is TextView) { return child.text.toString().contains(text) } } return false } } } packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +9 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; Loading Loading @@ -186,6 +187,9 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC); if (AsyncHybridViewInflation.isEnabled()) { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_SINGLE_LINE); if (LockscreenOtpRedaction.isSingleLineViewEnabled()) { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE); } } mRowContentBindStage.requestRebind(entry, null); } Loading Loading @@ -256,10 +260,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { params.requireContentViews(FLAG_CONTENT_VIEW_EXPANDED); params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); params.setUseMinimized(isMinimized); // TODO b/358403414: use the different types of redaction boolean needsRedaction = inflaterParams.getRedactionType() != REDACTION_TYPE_NONE; int redactionType = inflaterParams.getRedactionType(); if (needsRedaction) { params.setRedactionType(redactionType); if (redactionType != REDACTION_TYPE_NONE) { params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC); } else { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC); Loading @@ -276,8 +280,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { } if (LockscreenOtpRedaction.isSingleLineViewEnabled()) { if (inflaterParams.isChildInGroup() && needsRedaction) { if (inflaterParams.isChildInGroup() && redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) { params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE); } else { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE); Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +61 −25 File changed.Preview size limit exceeded, changes collapsed. Show changes packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java +18 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -141,20 +143,33 @@ public interface NotificationRowContentBinder { */ class BindParams { public BindParams(boolean minimized, boolean increasedHeight, boolean increasedHeadsUpHeight, int redaction) { isMinimized = minimized; usesIncreasedHeight = increasedHeight; usesIncreasedHeadsUpHeight = increasedHeadsUpHeight; redactionType = redaction; } /** * Bind a minimized version of the content views. */ public boolean isMinimized; public final boolean isMinimized; /** * Use increased height when binding contracted view. */ public boolean usesIncreasedHeight; public final boolean usesIncreasedHeight; /** * Use increased height when binding heads up views. */ public boolean usesIncreasedHeadsUpHeight; public final boolean usesIncreasedHeadsUpHeight; /** * Controls the type of public view to show, if a public view is requested */ public final @RedactionType int redactionType; } /** Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java +94 −10 Original line number Diff line number Diff line Loading @@ -16,12 +16,18 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; Loading @@ -36,7 +42,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Notification; import android.app.Person; import android.content.Context; import android.graphics.drawable.Icon; import android.os.AsyncTask; import android.os.CancellationSignal; import android.os.Handler; Loading Loading @@ -66,6 +74,7 @@ import com.android.systemui.statusbar.notification.promoted.shared.model.Promote import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction; import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder; Loading Loading @@ -155,8 +164,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase { @Test public void testIncreasedHeadsUpBeingUsed() { BindParams params = new BindParams(); params.usesIncreasedHeadsUpHeight = true; BindParams params = new BindParams(false, false, /* usesIncreasedHeadsUpHeight */ true, REDACTION_TYPE_NONE); Notification.Builder builder = spy(mBuilder); mNotificationInflater.inflateNotificationViews( mRow.getEntry(), Loading @@ -166,14 +175,15 @@ public class NotificationContentInflaterTest extends SysuiTestCase { FLAG_CONTENT_VIEW_ALL, builder, mContext, mContext, mSmartReplyStateInflater); verify(builder).createHeadsUpContentView(true); } @Test public void testIncreasedHeightBeingUsed() { BindParams params = new BindParams(); params.usesIncreasedHeight = true; BindParams params = new BindParams(false, /* usesIncreasedHeight */ true, false, REDACTION_TYPE_NONE); Notification.Builder builder = spy(mBuilder); mNotificationInflater.inflateNotificationViews( mRow.getEntry(), Loading @@ -183,6 +193,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { FLAG_CONTENT_VIEW_ALL, builder, mContext, mContext, mSmartReplyStateInflater); verify(builder).createContentView(true); } Loading @@ -207,7 +218,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getEntry().getSbn().getNotification().contentView = new RemoteViews(mContext.getPackageName(), com.android.systemui.res.R.layout.status_bar); inflateAndWait(true /* expectingException */, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow); REDACTION_TYPE_NONE, mRow); assertTrue(mRow.getPrivateLayout().getChildCount() == 0); verify(mRow, times(0)).onNotificationUpdated(); } Loading @@ -227,7 +238,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getEntry(), mRow, FLAG_CONTENT_VIEW_ALL, new BindParams(), new BindParams(false, false, false, REDACTION_TYPE_NONE), false /* forceInflate */, null /* callback */); Assert.assertNull(mRow.getEntry().getRunningTask()); Loading Loading @@ -287,7 +298,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(), R.layout.custom_view_dark)); RemoteViews decoratedMediaView = mBuilder.createContentView(); Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!", assertFalse("The decorated media style doesn't allow a view to be reapplied!", NotificationContentInflater.canReapplyRemoteView(mediaView, decoratedMediaView)); } Loading Loading @@ -385,7 +396,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getPrivateLayout().removeAllViews(); mRow.getEntry().getSbn().getNotification().contentView = new RemoteViews(mContext.getPackageName(), R.layout.invalid_notification_height); inflateAndWait(true, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow); inflateAndWait(true, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, mRow); assertEquals(0, mRow.getPrivateLayout().getChildCount()); verify(mRow, times(0)).onNotificationUpdated(); } Loading Loading @@ -455,16 +467,88 @@ public class NotificationContentInflaterTest extends SysuiTestCase { assertNull(mRow.getEntry().getPromotedNotificationContentModel()); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testSensitiveContentPublicView_messageStyle() throws Exception { String displayName = "Display Name"; String messageText = "Message Text"; String contentText = "Content Text"; Icon personIcon = Icon.createWithResource(mContext, com.android.systemui.res.R.drawable.ic_person); Person testPerson = new Person.Builder() .setName(displayName) .setIcon(personIcon) .build(); Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(testPerson); messagingStyle.addMessage(new Notification.MessagingStyle.Message(messageText, System.currentTimeMillis(), testPerson)); messagingStyle.setConversationType(Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL); messagingStyle.setShortcutIcon(personIcon); Notification messageNotif = new Notification.Builder(mContext).setSmallIcon( com.android.systemui.res.R.drawable.ic_person).setStyle(messagingStyle).build(); ExpandableNotificationRow row = mHelper.createRow(messageNotif); inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, row); NotificationContentView publicView = row.getPublicLayout(); assertNotNull(publicView); // The display name should be included, but not the content or message text assertFalse(hasText(publicView, messageText)); assertFalse(hasText(publicView, contentText)); assertTrue(hasText(publicView, displayName)); } @Test @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) public void testSensitiveContentPublicView_nonMessageStyle() throws Exception { String contentTitle = "Content Title"; String contentText = "Content Text"; Notification notif = new Notification.Builder(mContext).setSmallIcon( com.android.systemui.res.R.drawable.ic_person) .setContentTitle(contentTitle) .setContentText(contentText) .build(); ExpandableNotificationRow row = mHelper.createRow(notif); inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, row); NotificationContentView publicView = row.getPublicLayout(); assertNotNull(publicView); assertFalse(hasText(publicView, contentText)); assertTrue(hasText(publicView, contentTitle)); // The standard public view should not use the content title or text inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_PUBLIC, row); publicView = row.getPublicLayout(); assertFalse(hasText(publicView, contentText)); assertFalse(hasText(publicView, contentTitle)); } private static boolean hasText(ViewGroup parent, CharSequence text) { for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); if (child instanceof ViewGroup) { if (hasText((ViewGroup) child, text)) { return true; } } else if (child instanceof TextView) { return ((TextView) child).getText().toString().contains(text); } } return false; } private static void inflateAndWait(NotificationContentInflater inflater, @InflationFlag int contentToInflate, ExpandableNotificationRow row) throws Exception { inflateAndWait(false /* expectingException */, inflater, contentToInflate, row); inflateAndWait(false /* expectingException */, inflater, contentToInflate, REDACTION_TYPE_NONE, row); } private static void inflateAndWait(boolean expectingException, NotificationContentInflater inflater, @InflationFlag int contentToInflate, @RedactionType int redactionType, ExpandableNotificationRow row) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(1); final ExceptionHolder exceptionHolder = new ExceptionHolder(); Loading Loading @@ -492,7 +576,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { row.getEntry(), row, contentToInflate, new BindParams(), new BindParams(false, false, false, redactionType), false /* forceInflate */, callback /* callback */); assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS)); Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt +124 −14 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.row import android.app.Notification import android.app.Person import android.content.Context import android.graphics.drawable.Icon import android.os.AsyncTask import android.os.Build import android.os.CancellationSignal Loading @@ -34,6 +35,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT import com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.notification.ConversationNotificationProcessor import com.android.systemui.statusbar.notification.collection.NotificationEntry Loading @@ -45,6 +50,7 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag Loading Loading @@ -138,14 +144,14 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @Test fun testIncreasedHeadsUpBeingUsed() { val params = BindParams() params.usesIncreasedHeadsUpHeight = true val params = BindParams(false, false, /* usesIncreasedHeadsUpHeight */ true, REDACTION_TYPE_NONE) val builder = spy(builder) notificationInflater.inflateNotificationViews( row.entry, row, params, true /* inflateSynchronously */, true, /* inflateSynchronously */ FLAG_CONTENT_VIEW_ALL, builder, mContext, Loading @@ -157,14 +163,13 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @Test fun testIncreasedHeightBeingUsed() { val params = BindParams() params.usesIncreasedHeight = true val params = BindParams(false, /* usesIncreasedHeight */ true, false, REDACTION_TYPE_NONE) val builder = spy(builder) notificationInflater.inflateNotificationViews( row.entry, row, params, true /* inflateSynchronously */, true, /* inflateSynchronously */ FLAG_CONTENT_VIEW_ALL, builder, mContext, Loading Loading @@ -193,15 +198,18 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { row.entry.sbn.notification.contentView = RemoteViews(mContext.packageName, R.layout.status_bar) inflateAndWait( true /* expectingException */, true, /* expectingException */ notificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, row, ) Assert.assertTrue(row.privateLayout.childCount == 0) verify(row, times(0)).onNotificationUpdated() } @Test fun testInflationOfSensitiveContentPublicView() {} @Test fun testAsyncTaskRemoved() { row.entry.abortTask() Loading @@ -217,8 +225,8 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { row.entry, row, FLAG_CONTENT_VIEW_ALL, BindParams(), false /* forceInflate */, BindParams(false, false, false, REDACTION_TYPE_NONE), false, /* forceInflate */ null, /* callback */ ) Assert.assertNull(row.entry.runningTask) Loading Loading @@ -431,7 +439,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { mContext.packageName, com.android.systemui.tests.R.layout.invalid_notification_height, ) inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, row) inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, row) Assert.assertEquals(0, row.privateLayout.childCount.toLong()) verify(row, times(0)).onNotificationUpdated() } Loading @@ -440,7 +448,13 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @Test fun testInflatePublicSingleLineView() { row.publicLayout.removeAllViews() inflateAndWait(false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, row) inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, REDACTION_TYPE_NONE, row, ) Assert.assertNotNull(row.publicLayout.mSingleLineView) Assert.assertTrue(row.publicLayout.mSingleLineView is HybridNotificationView) } Loading @@ -461,6 +475,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, REDACTION_TYPE_NONE, messagingRow, ) Assert.assertNotNull(messagingRow.publicLayout.mSingleLineView) Loading Loading @@ -530,6 +545,80 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { Assert.assertNull(row.entry.promotedNotificationContentModel) } @Test @Throws(java.lang.Exception::class) @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) fun testSensitiveContentPublicView_messageStyle() { val displayName = "Display Name" val messageText = "Message Text" val contentText = "Content Text" val personIcon = Icon.createWithResource(mContext, R.drawable.ic_person) val testPerson = Person.Builder().setName(displayName).setIcon(personIcon).build() val messagingStyle = Notification.MessagingStyle(testPerson) messagingStyle.addMessage( Notification.MessagingStyle.Message(messageText, System.currentTimeMillis(), testPerson) ) messagingStyle.setConversationType(Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL) messagingStyle.setShortcutIcon(personIcon) val messageNotif = Notification.Builder(mContext) .setSmallIcon(R.drawable.ic_person) .setStyle(messagingStyle) .build() val newRow: ExpandableNotificationRow = testHelper.createRow(messageNotif) inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, newRow, ) // The display name should be included, but not the content or message text val publicView = newRow.publicLayout Assert.assertNotNull(publicView) Assert.assertFalse(hasText(publicView, messageText)) Assert.assertFalse(hasText(publicView, contentText)) Assert.assertTrue(hasText(publicView, displayName)) } @Test @Throws(java.lang.Exception::class) @EnableFlags(LockscreenOtpRedaction.FLAG_NAME) fun testSensitiveContentPublicView_nonMessageStyle() { val contentTitle = "Content Title" val contentText = "Content Text" val notif = Notification.Builder(mContext) .setSmallIcon(R.drawable.ic_person) .setContentTitle(contentTitle) .setContentText(contentText) .build() val newRow: ExpandableNotificationRow = testHelper.createRow(notif) inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_SENSITIVE_CONTENT, newRow, ) var publicView = newRow.publicLayout Assert.assertNotNull(publicView) Assert.assertFalse(hasText(publicView, contentText)) Assert.assertTrue(hasText(publicView, contentTitle)) // The standard public view should not use the content title or text inflateAndWait( false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC, REDACTION_TYPE_PUBLIC, newRow, ) publicView = newRow.publicLayout Assert.assertFalse(hasText(publicView, contentText)) Assert.assertFalse(hasText(publicView, contentTitle)) } private class ExceptionHolder { var exception: Exception? = null } Loading Loading @@ -568,13 +657,20 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { @InflationFlag contentToInflate: Int, row: ExpandableNotificationRow, ) { inflateAndWait(false /* expectingException */, inflater, contentToInflate, row) inflateAndWait( false /* expectingException */, inflater, contentToInflate, REDACTION_TYPE_NONE, row, ) } private fun inflateAndWait( expectingException: Boolean, inflater: NotificationRowContentBinderImpl, @InflationFlag contentToInflate: Int, @RedactionType redactionType: Int, row: ExpandableNotificationRow, ) { val countDownLatch = CountDownLatch(1) Loading Loading @@ -603,12 +699,26 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { row.entry, row, contentToInflate, BindParams(), false /* forceInflate */, BindParams(false, false, false, redactionType), false, /* forceInflate */ callback, /* callback */ ) Assert.assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS)) exceptionHolder.exception?.let { throw it } } fun hasText(parent: ViewGroup, text: CharSequence): Boolean { for (i in 0 until parent.childCount) { val child = parent.getChildAt(i) if (child is ViewGroup) { if (hasText(child, text)) { return true } } else if (child is TextView) { return child.text.toString().contains(text) } } return false } } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +9 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; Loading Loading @@ -186,6 +187,9 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC); if (AsyncHybridViewInflation.isEnabled()) { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_SINGLE_LINE); if (LockscreenOtpRedaction.isSingleLineViewEnabled()) { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE); } } mRowContentBindStage.requestRebind(entry, null); } Loading Loading @@ -256,10 +260,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { params.requireContentViews(FLAG_CONTENT_VIEW_EXPANDED); params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); params.setUseMinimized(isMinimized); // TODO b/358403414: use the different types of redaction boolean needsRedaction = inflaterParams.getRedactionType() != REDACTION_TYPE_NONE; int redactionType = inflaterParams.getRedactionType(); if (needsRedaction) { params.setRedactionType(redactionType); if (redactionType != REDACTION_TYPE_NONE) { params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC); } else { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC); Loading @@ -276,8 +280,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { } if (LockscreenOtpRedaction.isSingleLineViewEnabled()) { if (inflaterParams.isChildInGroup() && needsRedaction) { if (inflaterParams.isChildInGroup() && redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) { params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE); } else { params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE); Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +61 −25 File changed.Preview size limit exceeded, changes collapsed. Show changes
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java +18 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -141,20 +143,33 @@ public interface NotificationRowContentBinder { */ class BindParams { public BindParams(boolean minimized, boolean increasedHeight, boolean increasedHeadsUpHeight, int redaction) { isMinimized = minimized; usesIncreasedHeight = increasedHeight; usesIncreasedHeadsUpHeight = increasedHeadsUpHeight; redactionType = redaction; } /** * Bind a minimized version of the content views. */ public boolean isMinimized; public final boolean isMinimized; /** * Use increased height when binding contracted view. */ public boolean usesIncreasedHeight; public final boolean usesIncreasedHeight; /** * Use increased height when binding heads up views. */ public boolean usesIncreasedHeadsUpHeight; public final boolean usesIncreasedHeadsUpHeight; /** * Controls the type of public view to show, if a public view is requested */ public final @RedactionType int redactionType; } /** Loading