Merge "Create a redacted single line view" into main
diff --git a/packages/SystemUI/res/drawable/ic_redacted_notification_single_line_icon.xml b/packages/SystemUI/res/drawable/ic_redacted_notification_single_line_icon.xml
new file mode 100644
index 0000000..8146c16
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_redacted_notification_single_line_icon.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?android:attr/colorAccent"
+ android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+ <path
+ android:fillColor="?android:attr/colorAccent"
+ android:pathData="M18,8h-1.5V5.5C16.5,3.01 14.49,1 12,1S7.5,3.01 7.5,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9.5,5.5C9.5,4.12 10.62,3 12,3c1.38,0 2.5,1.12 2.5,2.5V8h-5V5.5zM18,20H6V10h1.5h9H18V20z"/>
+</vector>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 19eebf5..159fb2e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3713,6 +3713,11 @@
<!-- Education toast text for All Apps [CHAR_LIMIT=100] -->
<string name="all_apps_edu_toast_content">To view all your apps, press the action key on your keyboard</string>
+ <!-- Title of the one line view of a redacted notification -->
+ <string name="redacted_notification_single_line_title">Redacted</string>
+ <!-- Main text of the one line view of a redacted notification -->
+ <string name="redacted_notification_single_line_text">Unlock to view</string>
+
<!-- Education notification title for Back [CHAR_LIMIT=100] -->
<string name="back_edu_notification_title">Use your touchpad to go back</string>
<!-- Education notification text for Back [CHAR_LIMIT=100] -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index bb26f92..7244f8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar;
import static android.app.Flags.keyguardPrivateNotifications;
-import static android.app.Flags.redactSensitiveContentNotificationsOnLockscreen;
import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
@@ -72,6 +71,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ListenerSet;
@@ -655,7 +655,7 @@
!userAllowsPrivateNotificationsInPublic(mCurrentUserId);
boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId);
boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId);
- boolean isNotifSensitive = redactSensitiveContentNotificationsOnLockscreen()
+ boolean isNotifSensitive = LockscreenOtpRedaction.isEnabled()
&& ent.getRanking() != null && ent.getRanking().hasSensitiveContent();
// redact notifications if the current user is redacting notifications or the notification
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 4a895c0..c52632e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -20,6 +20,7 @@
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;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER;
@@ -54,6 +55,7 @@
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import javax.inject.Inject;
@@ -253,10 +255,11 @@
params.requireContentViews(FLAG_CONTENT_VIEW_EXPANDED);
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
params.setUseMinimized(isMinimized);
-
- if (screenshareNotificationHiding()
+ boolean needsRedaction = screenshareNotificationHiding()
? inflaterParams.getNeedsRedaction()
- : mNotificationLockscreenUserManager.needsRedaction(entry)) {
+ : mNotificationLockscreenUserManager.needsRedaction(entry);
+
+ if (needsRedaction) {
params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
} else {
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
@@ -272,6 +275,14 @@
}
}
+ if (LockscreenOtpRedaction.isEnabled()) {
+ if (inflaterParams.isChildInGroup() && needsRedaction) {
+ params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+ } else {
+ params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+ }
+ }
+
if (AsyncGroupHeaderViewInflation.isEnabled()) {
if (inflaterParams.isGroupSummary()) {
params.requireContentViews(FLAG_GROUP_SUMMARY_HEADER);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 06af980..9d13a17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -102,6 +102,7 @@
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationCompactMessagingTemplateViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
@@ -997,6 +998,9 @@
}
mNotificationParent = isChildInGroup ? parent : null;
mPrivateLayout.setIsChildInGroup(isChildInGroup);
+ if (LockscreenOtpRedaction.isEnabled()) {
+ mPublicLayout.setIsChildInGroup(isChildInGroup);
+ }
updateBackgroundForGroupState();
updateClickAndFocus();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index ba1cfcc..0738a03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -46,7 +46,7 @@
import java.util.Objects;
/**
- * A hybrid view which may contain information about one ore more conversations.
+ * A hybrid view which may contain information about one or more conversations.
*/
public class HybridConversationNotificationView extends HybridNotificationView {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index af5117e..8c80fd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -56,8 +56,8 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor;
-import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder;
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder;
import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
@@ -196,8 +196,8 @@
result = inflateSmartReplyViews(result, reInflateFlags, entry, row.getContext(),
packageContext, row.getExistingSmartReplyState(), smartRepliesInflater, mLogger);
+ boolean isConversation = entry.getRanking().isConversation();
if (AsyncHybridViewInflation.isEnabled()) {
- boolean isConversation = entry.getRanking().isConversation();
Notification.MessagingStyle messagingStyle = null;
if (isConversation) {
messagingStyle = mConversationProcessor
@@ -210,8 +210,22 @@
builder,
row.getContext()
);
- result.mInflatedSingleLineViewHolder =
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ result.mInflatedSingleLineView =
+ SingleLineViewInflater.inflatePrivateSingleLineView(
+ isConversation,
+ reInflateFlags,
+ entry,
+ row.getContext(),
+ mLogger
+ );
+ }
+
+ if (LockscreenOtpRedaction.isEnabled()) {
+ result.mPublicInflatedSingleLineViewModel =
+ SingleLineViewInflater.inflateRedactedSingleLineViewModel(row.getContext(),
+ isConversation);
+ result.mPublicInflatedSingleLineView =
+ SingleLineViewInflater.inflatePublicSingleLineView(
isConversation,
reInflateFlags,
entry,
@@ -291,6 +305,16 @@
row.getPrivateLayout().setHeadsUpInflatedSmartReplies(null);
});
break;
+ case FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE:
+ if (LockscreenOtpRedaction.isEnabled()) {
+ row.getPublicLayout()
+ .performWhenContentInactive(VISIBLE_TYPE_SINGLELINE, () -> {
+ row.getPublicLayout().setSingleLineView(null);
+ mRemoteViewCache.removeCachedView(entry,
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+ });
+ }
+ break;
case FLAG_CONTENT_VIEW_PUBLIC:
row.getPublicLayout().performWhenContentInactive(VISIBLE_TYPE_CONTRACTED, () -> {
row.getPublicLayout().setContractedChild(null);
@@ -334,6 +358,10 @@
row.getPublicLayout().removeContentInactiveRunnable(VISIBLE_TYPE_CONTRACTED);
}
if (AsyncHybridViewInflation.isEnabled()
+ && (contentViews & FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE) != 0) {
+ row.getPublicLayout().removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE);
+ }
+ if (LockscreenOtpRedaction.isEnabled()
&& (contentViews & FLAG_CONTENT_VIEW_SINGLE_LINE) != 0) {
row.getPrivateLayout().removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE);
}
@@ -935,19 +963,21 @@
if (AsyncHybridViewInflation.isEnabled()
&& (reInflateFlags & FLAG_CONTENT_VIEW_SINGLE_LINE) != 0) {
- HybridNotificationView viewHolder = result.mInflatedSingleLineViewHolder;
+ HybridNotificationView view = result.mInflatedSingleLineView;
SingleLineViewModel viewModel = result.mInflatedSingleLineViewModel;
- if (viewHolder != null && viewModel != null) {
- if (viewModel.isConversation()) {
- SingleLineConversationViewBinder.bind(
- result.mInflatedSingleLineViewModel,
- result.mInflatedSingleLineViewHolder
- );
- } else {
- SingleLineViewBinder.bind(result.mInflatedSingleLineViewModel,
- result.mInflatedSingleLineViewHolder);
- }
- privateLayout.setSingleLineView(result.mInflatedSingleLineViewHolder);
+ if (view != null && viewModel != null) {
+ SingleLineViewBinder.bind(viewModel, view);
+ privateLayout.setSingleLineView(result.mInflatedSingleLineView);
+ }
+ }
+
+ if (LockscreenOtpRedaction.isEnabled()
+ && (reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE) != 0) {
+ HybridNotificationView view = result.mPublicInflatedSingleLineView;
+ SingleLineViewModel viewModel = result.mPublicInflatedSingleLineViewModel;
+ if (view != null && viewModel != null) {
+ SingleLineViewBinder.bind(viewModel, view);
+ publicLayout.setSingleLineView(result.mPublicInflatedSingleLineView);
}
}
@@ -1211,8 +1241,22 @@
recoveredBuilder,
mContext
);
- result.mInflatedSingleLineViewHolder =
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ result.mInflatedSingleLineView =
+ SingleLineViewInflater.inflatePrivateSingleLineView(
+ isConversation,
+ mReInflateFlags,
+ mEntry,
+ mContext,
+ mLogger
+ );
+ }
+
+ if (LockscreenOtpRedaction.isEnabled()) {
+ result.mPublicInflatedSingleLineViewModel =
+ SingleLineViewInflater.inflateRedactedSingleLineViewModel(mContext,
+ isConversation);
+ result.mPublicInflatedSingleLineView =
+ SingleLineViewInflater.inflatePublicSingleLineView(
isConversation,
mReInflateFlags,
mEntry,
@@ -1347,8 +1391,13 @@
// ViewModel for SingleLineView, holds the UI State
SingleLineViewModel mInflatedSingleLineViewModel;
+ // ViewModel for public SingleLineView, holds the UI State
+ SingleLineViewModel mPublicInflatedSingleLineViewModel;
// Inflated SingleLineViewHolder, SingleLineView that lacks the UI State
- HybridNotificationView mInflatedSingleLineViewHolder;
+ HybridNotificationView mInflatedSingleLineView;
+ // Inflated SingleLineViewHolder, SingleLineView that lacks the UI State for the public
+ // single line view
+ HybridNotificationView mPublicInflatedSingleLineView;
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 3f46902..7119145 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -113,7 +113,8 @@
private View mContractedChild;
private View mExpandedChild;
private View mHeadsUpChild;
- private HybridNotificationView mSingleLineView;
+ @VisibleForTesting
+ protected HybridNotificationView mSingleLineView;
@Nullable public DisposableHandle mContractedBinderHandle;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
index fe0ee52..07384af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
@@ -89,6 +89,7 @@
FLAG_CONTENT_VIEW_SINGLE_LINE,
FLAG_GROUP_SUMMARY_HEADER,
FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER,
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
FLAG_CONTENT_VIEW_ALL})
@interface InflationFlag {}
/**
@@ -105,7 +106,7 @@
*/
int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2;
/**
- * The public view. This is a version of the contracted view that hides sensitive
+ * The public view. This is a version of the contracted view that hides sensitive
* information and is used on the lock screen if we determine that the notification's
* content should be hidden.
*/
@@ -126,7 +127,14 @@
*/
int FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER = 1 << 6;
- int FLAG_CONTENT_VIEW_ALL = (1 << 7) - 1;
+ /**
+ * The public single line view. This is a version of the contracted view that hides sensitive
+ * information and is used on the lock screen if we determine that the notification's
+ * content should be hidden, and the notification is shown as a child in a group.
+ */
+ int FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE = 1 << 7;
+
+ int FLAG_CONTENT_VIEW_ALL = (1 << 8) - 1;
/**
* Parameters for content view binding
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
index 492d802..a5cd2a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
@@ -55,6 +55,7 @@
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.FLAG_CONTENT_VIEW_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER
@@ -63,11 +64,11 @@
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.shared.HeadsUpStatusBarModel
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction
import com.android.systemui.statusbar.notification.row.shared.NewRemoteViews
import com.android.systemui.statusbar.notification.row.shared.NotificationContentModel
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor
import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel
-import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer
@@ -202,7 +203,19 @@
if (AsyncHybridViewInflation.isEnabled) {
result.inflatedSingleLineView =
result.contentModel.singleLineViewModel?.let { viewModel ->
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ SingleLineViewInflater.inflatePrivateSingleLineView(
+ viewModel.isConversation(),
+ reInflateFlags,
+ entry,
+ systemUIContext,
+ logger,
+ )
+ }
+ }
+ if (LockscreenOtpRedaction.isEnabled) {
+ result.inflatedPublicSingleLineView =
+ result.contentModel.publicSingleLineViewModel?.let { viewModel ->
+ SingleLineViewInflater.inflatePublicSingleLineView(
viewModel.isConversation(),
reInflateFlags,
entry,
@@ -294,6 +307,13 @@
}
}
}
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE -> {
+ if (LockscreenOtpRedaction.isEnabled) {
+ row.publicLayout.performWhenContentInactive(VISIBLE_TYPE_SINGLELINE) {
+ row.publicLayout.setSingleLineView(null)
+ }
+ }
+ }
else -> {}
}
}
@@ -327,6 +347,12 @@
) {
row.privateLayout.removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE)
}
+ if (
+ LockscreenOtpRedaction.isEnabled &&
+ contentViews and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
+ ) {
+ row.publicLayout.removeContentInactiveRunnable(VISIBLE_TYPE_SINGLELINE)
+ }
}
/**
@@ -449,7 +475,7 @@
logger.logAsyncTaskProgress(entry, "inflating single line view")
inflationProgress.inflatedSingleLineView =
inflationProgress.contentModel.singleLineViewModel?.let {
- SingleLineViewInflater.inflateSingleLineViewHolder(
+ SingleLineViewInflater.inflatePrivateSingleLineView(
it.isConversation(),
reInflateFlags,
entry,
@@ -459,6 +485,20 @@
}
}
+ if (LockscreenOtpRedaction.isEnabled) {
+ logger.logAsyncTaskProgress(entry, "inflating public single line view")
+ inflationProgress.inflatedPublicSingleLineView =
+ inflationProgress.contentModel.publicSingleLineViewModel?.let { viewModel ->
+ SingleLineViewInflater.inflatePublicSingleLineView(
+ viewModel.isConversation(),
+ reInflateFlags,
+ entry,
+ context,
+ logger
+ )
+ }
+ }
+
if (reInflateFlags and CONTENT_VIEWS_TO_CREATE_RICH_ONGOING != 0) {
logger.logAsyncTaskProgress(entry, "inflating RON view")
inflationProgress.richOngoingNotificationViewHolder =
@@ -582,6 +622,8 @@
// Inflated SingleLineView that lacks the UI State
var inflatedSingleLineView: HybridNotificationView? = null
+ // Inflated public SingleLineView that lacks the UI State
+ var inflatedPublicSingleLineView: HybridNotificationView? = null
}
@VisibleForTesting
@@ -706,6 +748,18 @@
)
} else null
+ val publicSingleLineViewModel =
+ if (
+ LockscreenOtpRedaction.isEnabled &&
+ reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
+ ) {
+ logger.logAsyncTaskProgress(entry, "inflating public single line view model")
+ SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+ systemUIContext,
+ entry.ranking.isConversation
+ )
+ } else null
+
val headsUpStatusBarModel =
HeadsUpStatusBarModel(
privateText = builder.getHeadsUpStatusBarText(/* publicMode= */ false),
@@ -716,6 +770,7 @@
NotificationContentModel(
headsUpStatusBarModel = headsUpStatusBarModel,
singleLineViewModel = singleLineViewModel,
+ publicSingleLineViewModel = publicSingleLineViewModel,
richOngoingContentModel = richOngoingContentModel,
)
@@ -1405,15 +1460,23 @@
val singleLineView = result.inflatedSingleLineView
val viewModel = result.contentModel.singleLineViewModel
if (singleLineView != null && viewModel != null) {
- if (viewModel.isConversation()) {
- SingleLineConversationViewBinder.bind(viewModel, singleLineView)
- } else {
- SingleLineViewBinder.bind(viewModel, singleLineView)
- }
+ SingleLineViewBinder.bind(viewModel, singleLineView)
row.privateLayout.setSingleLineView(result.inflatedSingleLineView)
}
}
+ if (
+ LockscreenOtpRedaction.isEnabled &&
+ reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
+ ) {
+ val singleLineView = result.inflatedPublicSingleLineView
+ val viewModel = result.contentModel.publicSingleLineViewModel
+ if (singleLineView != null && viewModel != null) {
+ SingleLineViewBinder.bind(viewModel, singleLineView)
+ row.publicLayout.setSingleLineView(result.inflatedPublicSingleLineView)
+ }
+ }
+
// after updating the content model, set the view, then start the new binder
result.richOngoingNotificationViewHolder?.let { viewHolder ->
row.privateLayout.contractedChild = viewHolder.view
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index 463192c..d67947d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -30,6 +30,7 @@
import com.android.internal.widget.PeopleHelper
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewmodel.ConversationAvatar
@@ -107,6 +108,36 @@
)
}
+ @JvmStatic
+ fun inflateRedactedSingleLineViewModel(
+ context: Context,
+ isConversation: Boolean = false
+ ): SingleLineViewModel {
+ val conversationData =
+ if (isConversation) {
+ ConversationData(
+ null,
+ SingleIcon(
+ context.getDrawable(
+ com.android.systemui.res.R.drawable
+ .ic_redacted_notification_single_line_icon
+ )
+ )
+ )
+ } else {
+ null
+ }
+ return SingleLineViewModel(
+ context.getString(
+ com.android.systemui.res.R.string.redacted_notification_single_line_title
+ ),
+ context.getString(
+ com.android.systemui.res.R.string.redacted_notification_single_line_text
+ ),
+ conversationData
+ )
+ }
+
/** load conversation text data from the MessagingStyle of conversation notifications */
private fun MessagingStyle.loadConversationTextData(
systemUiContext: Context
@@ -137,8 +168,8 @@
// We need to find back-up values for those texts if they are needed and empty
return ConversationTextData(
- conversationTitle = conversationTitle
- ?: findBackUpConversationTitle(senderName, systemUiContext),
+ conversationTitle =
+ conversationTitle ?: findBackUpConversationTitle(senderName, systemUiContext),
conversationText = conversationText,
senderName = senderName,
)
@@ -328,12 +359,27 @@
return FacePile(
topIconDrawable = secondLastIcon.loadDrawable(systemUiContext),
bottomIconDrawable = lastIcon.loadDrawable(systemUiContext),
- bottomBackgroundColor = builder.getBackgroundColor(/* isHeader = */ false),
+ bottomBackgroundColor = builder.getBackgroundColor(/* isHeader= */ false),
)
}
@JvmStatic
- fun inflateSingleLineViewHolder(
+ fun inflatePublicSingleLineView(
+ isConversation: Boolean,
+ reinflateFlags: Int,
+ entry: NotificationEntry,
+ context: Context,
+ logger: NotificationRowContentBinderLogger,
+ ): HybridNotificationView? {
+ return if ((reinflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE) == 0) {
+ null
+ } else {
+ inflateSingleLineView(isConversation, reinflateFlags, entry, context, logger)
+ }
+ }
+
+ @JvmStatic
+ fun inflatePrivateSingleLineView(
isConversation: Boolean,
reinflateFlags: Int,
entry: NotificationEntry,
@@ -341,9 +387,21 @@
logger: NotificationRowContentBinderLogger,
): HybridNotificationView? {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return null
- if (reinflateFlags and FLAG_CONTENT_VIEW_SINGLE_LINE == 0) {
- return null
+ return if ((reinflateFlags and FLAG_CONTENT_VIEW_SINGLE_LINE) == 0) {
+ null
+ } else {
+ inflateSingleLineView(isConversation, reinflateFlags, entry, context, logger)
}
+ }
+
+ private fun inflateSingleLineView(
+ isConversation: Boolean,
+ reinflateFlags: Int,
+ entry: NotificationEntry,
+ context: Context,
+ logger: NotificationRowContentBinderLogger,
+ ): HybridNotificationView? {
+ if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return null
logger.logInflateSingleLine(entry, reinflateFlags, isConversation)
logger.logAsyncTaskProgress(entry, "inflating single-line content view")
@@ -356,7 +414,7 @@
if (isConversation)
com.android.systemui.res.R.layout.hybrid_conversation_notification
else com.android.systemui.res.R.layout.hybrid_notification
- view = inflater.inflate(layoutRes, /* root = */ null) as HybridNotificationView
+ view = inflater.inflate(layoutRes, /* root= */ null) as HybridNotificationView
if (view == null) {
Log.wtf(TAG, "Single-line view inflation result is null for entry: ${entry.logKey}")
}
@@ -368,7 +426,7 @@
name: CharSequence?,
uniqueNames: PeopleHelper.NameToPrefixMap? = null
): Icon {
- val layoutColor = getSmallIconColor(/* isHeader = */ false)
+ val layoutColor = getSmallIconColor(/* isHeader= */ false)
if (!name.isNullOrEmpty()) {
val symbol = uniqueNames?.getPrefix(name) ?: ""
return peopleHelper.createAvatarSymbol(
@@ -379,7 +437,7 @@
}
// If name is null, create default avatar with background color
// TODO(b/319829062): Investigate caching default icon for color
- return peopleHelper.createAvatarSymbol(/* name = */ "", /* symbol = */ "", layoutColor)
+ return peopleHelper.createAvatarSymbol(/* name= */ "", /* symbol= */ "", layoutColor)
}
private fun Person.getKeyOrName(): CharSequence? = if (key == null) name else key
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/LockscreenOtpRedaction.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/LockscreenOtpRedaction.kt
new file mode 100644
index 0000000..078deb9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/LockscreenOtpRedaction.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.shared
+
+import android.app.Flags
+import android.app.Flags.redactSensitiveContentNotificationsOnLockscreen
+import com.android.systemui.flags.FlagToken
+
+/** Helper for reading or using the async hybrid view inflation flag state. */
+object LockscreenOtpRedaction {
+ const val FLAG_NAME = Flags.FLAG_REDACT_SENSITIVE_CONTENT_NOTIFICATIONS_ON_LOCKSCREEN
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ @JvmStatic
+ inline val isEnabled
+ get() =
+ redactSensitiveContentNotificationsOnLockscreen() && AsyncHybridViewInflation.isEnabled
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt
index 46010a1..0f9a5a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt
@@ -21,6 +21,7 @@
data class NotificationContentModel(
val headsUpStatusBarModel: HeadsUpStatusBarModel,
val singleLineViewModel: SingleLineViewModel? = null,
+ val publicSingleLineViewModel: SingleLineViewModel? = null,
val richOngoingContentModel: RichOngoingContentModel? = null,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineConversationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineConversationViewBinder.kt
deleted file mode 100644
index 69284bd..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineConversationViewBinder.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.ui.viewbinder
-
-import com.android.systemui.statusbar.notification.row.HybridConversationNotificationView
-import com.android.systemui.statusbar.notification.row.HybridNotificationView
-import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
-import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel
-
-object SingleLineConversationViewBinder {
- @JvmStatic
- fun bind(viewModel: SingleLineViewModel, view: HybridNotificationView?) {
- if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return
- if (view !is HybridConversationNotificationView || !viewModel.isConversation()) {
- SingleLineViewBinder.bind(viewModel, view)
- return
- }
-
- viewModel.conversationData?.avatar?.let { view.setAvatar(it) }
- view.setText(
- viewModel.titleText,
- viewModel.contentText,
- viewModel.conversationData?.conversationSenderName
- )
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
index 22e10c1..3b0f1ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
@@ -16,19 +16,32 @@
package com.android.systemui.statusbar.notification.row.ui.viewbinder
+import com.android.systemui.statusbar.notification.row.HybridConversationNotificationView
import com.android.systemui.statusbar.notification.row.HybridNotificationView
+import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel
object SingleLineViewBinder {
@JvmStatic
fun bind(viewModel: SingleLineViewModel?, view: HybridNotificationView?) {
- // bind the title and content text views
- view?.apply {
- bind(
- /* title = */ viewModel?.titleText,
- /* text = */ viewModel?.contentText,
- /* contentView = */ null
+ if (viewModel?.isConversation() == true && view is HybridConversationNotificationView) {
+ if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return
+
+ viewModel.conversationData?.avatar?.let { view.setAvatar(it) }
+ view.setText(
+ viewModel.titleText,
+ viewModel.contentText,
+ viewModel.conversationData?.conversationSenderName
)
+ } else {
+ // bind the title and content text views
+ view?.apply {
+ bind(
+ /* title = */ viewModel?.titleText,
+ /* text = */ viewModel?.contentText,
+ /* contentView = */ null
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
index 54a26f7..3f28164 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row
import android.app.Notification
+import android.app.Person
import android.content.Context
import android.os.AsyncTask
import android.os.Build
@@ -39,6 +40,7 @@
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_SINGLE_LINE
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.HeadsUpStatusBarModel
@@ -561,6 +563,40 @@
verify(row, times(0)).onNotificationUpdated()
}
+ // TODO b/356709333: Add screenshot tests for these views
+ @Test
+ fun testInflatePublicSingleLineView() {
+ row.publicLayout.removeAllViews()
+ inflateAndWait(false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, row)
+ Assert.assertNotNull(row.publicLayout.mSingleLineView)
+ Assert.assertTrue(row.publicLayout.mSingleLineView is HybridNotificationView)
+ }
+
+ @Test
+ fun testInflatePublicSingleLineConversationView() {
+ val testPerson = Person.Builder().setName("Person").build()
+ val messagingBuilder =
+ Notification.Builder(mContext, "no-id")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .setStyle(Notification.MessagingStyle(testPerson))
+
+ val messagingRow = spy(testHelper.createRow(messagingBuilder.build()))
+ messagingRow.publicLayout.removeAllViews()
+ inflateAndWait(
+ false,
+ notificationInflater,
+ FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ messagingRow
+ )
+ Assert.assertNotNull(messagingRow.publicLayout.mSingleLineView)
+ // assert this is the conversation layout
+ Assert.assertTrue(
+ messagingRow.publicLayout.mSingleLineView is HybridConversationNotificationView
+ )
+ }
+
private class ExceptionHolder {
var exception: Exception? = null
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index d7fdce2..75376e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -620,8 +620,12 @@
.setUser(userHandle)
.setPostTime(System.currentTimeMillis())
.setChannel(channel)
+ .updateRanking(rankingBuilder -> rankingBuilder.setIsConversation(
+ notification.isStyle(Notification.MessagingStyle.class)
+ ))
.build();
+
return generateRow(entry, extraInflationFlags);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt
deleted file mode 100644
index 53a1198..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.notification.row
-
-import android.app.Notification
-import android.app.Person
-import android.platform.test.annotations.EnableFlags
-import android.testing.TestableLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
-import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflateSingleLineViewHolder
-import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
-import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder
-import com.android.systemui.util.mockito.mock
-import kotlin.test.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
-class SingleLineConversationViewBinderTest : SysuiTestCase() {
- private lateinit var notificationBuilder: Notification.Builder
- private lateinit var helper: NotificationTestHelper
-
- @Before
- fun setUp() {
- allowTestableLooperAsMainThread()
- helper = NotificationTestHelper(context, mDependency, TestableLooper.get(this))
- notificationBuilder = Notification.Builder(context, CHANNEL_ID)
- notificationBuilder
- .setSmallIcon(R.drawable.ic_corp_icon)
- .setContentTitle(CONTENT_TITLE)
- .setContentText(CONTENT_TEXT)
- }
-
- @Test
- @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
- fun bindGroupConversationSingleLineView() {
- // GIVEN a row with a group conversation notification
- val user =
- Person.Builder()
- // .setIcon(Icon.createWithResource(mContext,
- // R.drawable.ic_account_circle))
- .setName(USER_NAME)
- .build()
- val style =
- Notification.MessagingStyle(user)
- .addMessage(MESSAGE_TEXT, System.currentTimeMillis(), user)
- .addMessage(
- "How about lunch?",
- System.currentTimeMillis(),
- Person.Builder().setName("user2").build()
- )
- .setGroupConversation(true)
- notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
- val notification = notificationBuilder.build()
- val row = helper.createRow(notification)
-
- val viewHolder =
- inflateSingleLineViewHolder(
- isConversation = true,
- reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
- entry = row.entry,
- context = context,
- logger = mock()
- )
- as HybridConversationNotificationView
- val viewModel =
- SingleLineViewInflater.inflateSingleLineViewModel(
- notification = notification,
- messagingStyle = style,
- builder = notificationBuilder,
- systemUiContext = context,
- )
- // WHEN: binds the viewHolder
- SingleLineConversationViewBinder.bind(
- viewModel,
- viewHolder,
- )
-
- // THEN: the single-line conversation view should be bind with view model's corresponding
- // fields
- assertEquals(viewModel.titleText, viewHolder.titleView.text)
- assertEquals(viewModel.contentText, viewHolder.textView.text)
- assertEquals(
- viewModel.conversationData?.conversationSenderName,
- viewHolder.conversationSenderNameView.text
- )
- }
-
- private companion object {
- const val CHANNEL_ID = "CHANNEL_ID"
- const val CONTENT_TITLE = "CONTENT_TITLE"
- const val CONTENT_TEXT = "CONTENT_TEXT"
- const val USER_NAME = "USER_NAME"
- const val MESSAGE_TEXT = "MESSAGE_TEXT"
- const val SHORTCUT_ID = "Shortcut"
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
index ee819c4..6b3fb5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
@@ -16,18 +16,22 @@
package com.android.systemui.statusbar.notification.row
import android.app.Notification
+import android.app.Person
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
-import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflateSingleLineViewHolder
+import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePrivateSingleLineView
+import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePublicSingleLineView
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder
import com.android.systemui.util.mockito.mock
-import org.junit.Assert
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -59,14 +63,25 @@
val notification = notificationBuilder.build()
val row: ExpandableNotificationRow = helper.createRow(notification)
- val viewHolder =
- inflateSingleLineViewHolder(
+ val view =
+ inflatePrivateSingleLineView(
isConversation = false,
reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
entry = row.entry,
context = context,
logger = mock()
)
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = false,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock()
+ )
+ assertNotNull(publicView)
+
val viewModel =
SingleLineViewInflater.inflateSingleLineViewModel(
notification = notification,
@@ -76,16 +91,86 @@
)
// WHEN: binds the viewHolder
- SingleLineViewBinder.bind(viewModel, viewHolder)
+ SingleLineViewBinder.bind(viewModel, view)
// THEN: the single-line view should be bind with viewModel's title and content text
- Assert.assertEquals(viewModel.titleText, viewHolder?.titleView?.text)
- Assert.assertEquals(viewModel.contentText, viewHolder?.textView?.text)
+ assertEquals(viewModel.titleText, view?.titleView?.text)
+ assertEquals(viewModel.contentText, view?.textView?.text)
+ }
+
+ @Test
+ @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
+ fun bindGroupConversationSingleLineView() {
+ // GIVEN a row with a group conversation notification
+ val user =
+ Person.Builder()
+ // .setIcon(Icon.createWithResource(mContext,
+ // R.drawable.ic_account_circle))
+ .setName(USER_NAME)
+ .build()
+ val style =
+ Notification.MessagingStyle(user)
+ .addMessage(MESSAGE_TEXT, System.currentTimeMillis(), user)
+ .addMessage(
+ "How about lunch?",
+ System.currentTimeMillis(),
+ Person.Builder().setName("user2").build()
+ )
+ .setGroupConversation(true)
+ notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
+ val notification = notificationBuilder.build()
+ val row = helper.createRow(notification)
+
+ val view =
+ inflatePrivateSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock()
+ )
+ as HybridConversationNotificationView
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock()
+ )
+ as HybridConversationNotificationView
+ assertNotNull(publicView)
+
+ val viewModel =
+ SingleLineViewInflater.inflateSingleLineViewModel(
+ notification = notification,
+ messagingStyle = style,
+ builder = notificationBuilder,
+ systemUiContext = context,
+ )
+ // WHEN: binds the view
+ SingleLineViewBinder.bind(
+ viewModel,
+ view,
+ )
+
+ // THEN: the single-line conversation view should be bound with view model's corresponding
+ // fields
+ assertEquals(viewModel.titleText, view.titleView.text)
+ assertEquals(viewModel.contentText, view.textView.text)
+ assertEquals(
+ viewModel.conversationData?.conversationSenderName,
+ view.conversationSenderNameView.text
+ )
}
private companion object {
const val CHANNEL_ID = "CHANNEL_ID"
const val CONTENT_TITLE = "A Cool New Feature"
const val CONTENT_TEXT = "Checkout out new feature!"
+ const val USER_NAME = "USER_NAME"
+ const val MESSAGE_TEXT = "MESSAGE_TEXT"
+ const val SHORTCUT_ID = "Shortcut"
}
}