Merge changes from topic "cherrypicker-L54300000962624816:N96600001397456171" into main
* changes:
Enable PrecomputedText in MessagingLayouts
Create data extraction helper for Messaging Layouts
Use PrecomputedText in MessagingLayouts
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 5b6b360..42be784 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -149,6 +149,7 @@
private View mAppNameDivider;
private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this);
private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>();
+ private boolean mPrecomputedTextEnabled = false;
public ConversationLayout(@NonNull Context context) {
super(context);
@@ -389,36 +390,37 @@
*/
@RemotableViewMethod(asyncImpl = "setDataAsync")
public void setData(Bundle extras) {
+ bind(parseMessagingData(extras, /* usePrecomputedText= */ false));
+ }
+
+ @NonNull
+ private MessagingData parseMessagingData(Bundle extras, boolean usePrecomputedText) {
Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
- List<Notification.MessagingStyle.Message> newMessages
- = Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
+ List<Notification.MessagingStyle.Message> newMessages =
+ Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
Parcelable[] histMessages = extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES);
- List<Notification.MessagingStyle.Message> newHistoricMessages
- = Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages);
+ List<Notification.MessagingStyle.Message> newHistoricMessages =
+ Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages);
// mUser now set (would be nice to avoid the side effect but WHATEVER)
final Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON, Person.class);
// Append remote input history to newMessages (again, side effect is lame but WHATEVS)
RemoteInputHistoryItem[] history = (RemoteInputHistoryItem[])
- extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, android.app.RemoteInputHistoryItem.class);
+ extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
+ RemoteInputHistoryItem.class);
addRemoteInputHistoryToMessages(newMessages, history);
boolean showSpinner =
extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
int unreadCount = extras.getInt(Notification.EXTRA_CONVERSATION_UNREAD_MESSAGE_COUNT);
- // convert MessagingStyle.Message to MessagingMessage, re-using ones from a previous binding
- // if they exist
final List<MessagingMessage> newMessagingMessages =
- createMessages(newMessages, /* isHistoric= */false,
- /* usePrecomputedText= */false);
+ createMessages(newMessages, /* isHistoric= */false, usePrecomputedText);
final List<MessagingMessage> newHistoricMessagingMessages =
- createMessages(newHistoricMessages, /* isHistoric= */true,
- /* usePrecomputedText= */false);
- // bind it, baby
- bindViews(user, showSpinner, unreadCount,
- newMessagingMessages,
- newHistoricMessagingMessages);
+ createMessages(newHistoricMessages, /* isHistoric= */true, usePrecomputedText);
+
+ return new MessagingData(user, showSpinner, unreadCount,
+ newHistoricMessagingMessages, newMessagingMessages);
}
/**
@@ -430,7 +432,33 @@
*/
@NonNull
public Runnable setDataAsync(Bundle extras) {
- return () -> setData(extras);
+ if (!mPrecomputedTextEnabled) {
+ return () -> setData(extras);
+ }
+
+ final MessagingData messagingData =
+ parseMessagingData(extras, /* usePrecomputedText= */ true);
+
+ return () -> {
+ finalizeInflate(messagingData.getHistoricMessagingMessages());
+ finalizeInflate(messagingData.getNewMessagingMessages());
+
+ bind(messagingData);
+ };
+ }
+
+ /**
+ * enable/disable precomputed text usage
+ * @hide
+ */
+ public void setPrecomputedTextEnabled(boolean precomputedTextEnabled) {
+ mPrecomputedTextEnabled = precomputedTextEnabled;
+ }
+
+ private void finalizeInflate(List<MessagingMessage> historicMessagingMessages) {
+ for (MessagingMessage messagingMessage : historicMessagingMessages) {
+ messagingMessage.finalizeInflate();
+ }
}
@Override
@@ -460,17 +488,12 @@
}
}
+ private void bind(MessagingData messagingData) {
+ setUser(messagingData.getUser());
+ setUnreadCount(messagingData.getUnreadCount());
- private void bindViews(Person user,
- boolean showSpinner, int unreadCount, List<MessagingMessage> newMessagingMessages,
- List<MessagingMessage> newHistoricMessagingMessages) {
- setUser(user);
- setUnreadCount(unreadCount);
- bind(showSpinner, newMessagingMessages, newHistoricMessagingMessages);
- }
-
- private void bind(boolean showSpinner, List<MessagingMessage> messages,
- List<MessagingMessage> historicMessages) {
+ List<MessagingMessage> messages = messagingData.getNewMessagingMessages();
+ List<MessagingMessage> historicMessages = messagingData.getHistoricMessagingMessages();
// Copy our groups, before they get clobbered
ArrayList<MessagingGroup> oldGroups = new ArrayList<>(mGroups);
@@ -483,7 +506,7 @@
// Let's now create the views and reorder them accordingly
// side-effect: updates mGroups, mAddedGroups
- createGroupViews(groups, senders, showSpinner);
+ createGroupViews(groups, senders, messagingData.getShowSpinner());
// Let's first check which groups were removed altogether and remove them in one animation
removeGroups(oldGroups);
@@ -585,7 +608,7 @@
// When collapsed, we're displaying the image message in a dedicated container
// on the right of the layout instead of inline. Let's add the isolated image there
- MessagingGroup messagingGroup = mGroups.get(mGroups.size() -1);
+ MessagingGroup messagingGroup = mGroups.get(mGroups.size() - 1);
MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
if (isolatedMessage != null) {
newMessage = isolatedMessage.getView();
@@ -1042,7 +1065,7 @@
}
if (visibleChildren > 0 && group.getVisibility() == GONE) {
group.setVisibility(VISIBLE);
- } else if (visibleChildren == 0 && group.getVisibility() != GONE) {
+ } else if (visibleChildren == 0 && group.getVisibility() != GONE) {
group.setVisibility(GONE);
}
}
@@ -1259,7 +1282,7 @@
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
- for (TouchDelegate delegate: mDelegates) {
+ for (TouchDelegate delegate : mDelegates) {
event.setLocation(x, y);
if (delegate.onTouchEvent(event)) {
return true;
diff --git a/core/java/com/android/internal/widget/MessagingData.java b/core/java/com/android/internal/widget/MessagingData.java
new file mode 100644
index 0000000..85b0201
--- /dev/null
+++ b/core/java/com/android/internal/widget/MessagingData.java
@@ -0,0 +1,70 @@
+/*
+ * 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.internal.widget;
+
+import android.app.Person;
+
+import java.util.List;
+
+/**
+ * @hide
+ */
+final class MessagingData {
+ private final Person mUser;
+ private final boolean mShowSpinner;
+ private final List<MessagingMessage> mHistoricMessagingMessages;
+ private final List<MessagingMessage> mNewMessagingMessages;
+ private final int mUnreadCount;
+
+ MessagingData(Person user, boolean showSpinner,
+ List<MessagingMessage> historicMessagingMessages,
+ List<MessagingMessage> newMessagingMessages) {
+ this(user, showSpinner, /* unreadCount= */0,
+ historicMessagingMessages, newMessagingMessages);
+ }
+
+ MessagingData(Person user, boolean showSpinner,
+ int unreadCount,
+ List<MessagingMessage> historicMessagingMessages,
+ List<MessagingMessage> newMessagingMessages) {
+ mUser = user;
+ mShowSpinner = showSpinner;
+ mUnreadCount = unreadCount;
+ mHistoricMessagingMessages = historicMessagingMessages;
+ mNewMessagingMessages = newMessagingMessages;
+ }
+
+ public Person getUser() {
+ return mUser;
+ }
+
+ public boolean getShowSpinner() {
+ return mShowSpinner;
+ }
+
+ public List<MessagingMessage> getHistoricMessagingMessages() {
+ return mHistoricMessagingMessages;
+ }
+
+ public List<MessagingMessage> getNewMessagingMessages() {
+ return mNewMessagingMessages;
+ }
+
+ public int getUnreadCount() {
+ return mUnreadCount;
+ }
+}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 83557cd..b6d7503 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -87,7 +87,7 @@
private ImageResolver mImageResolver;
private CharSequence mConversationTitle;
private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>();
-
+ private boolean mPrecomputedTextEnabled = false;
public MessagingLayout(@NonNull Context context) {
super(context);
}
@@ -162,15 +162,23 @@
*/
@RemotableViewMethod(asyncImpl = "setDataAsync")
public void setData(Bundle extras) {
+ bind(parseMessagingData(extras, /* usePrecomputedText= */false));
+ }
+
+ @NonNull
+ private MessagingData parseMessagingData(Bundle extras, boolean usePrecomputedText) {
Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
- List<Notification.MessagingStyle.Message> newMessages
- = Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
+ List<Notification.MessagingStyle.Message> newMessages =
+ Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
Parcelable[] histMessages = extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES);
- List<Notification.MessagingStyle.Message> newHistoricMessages
- = Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages);
- setUser(extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON, android.app.Person.class));
- RemoteInputHistoryItem[] history = (RemoteInputHistoryItem[])
- extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, android.app.RemoteInputHistoryItem.class);
+ List<Notification.MessagingStyle.Message> newHistoricMessages =
+ Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages);
+ setUser(extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON,
+ Person.class));
+ RemoteInputHistoryItem[] history =
+ (RemoteInputHistoryItem[]) extras.getParcelableArray(
+ Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
+ RemoteInputHistoryItem.class);
addRemoteInputHistoryToMessages(newMessages, history);
final Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON, Person.class);
@@ -178,10 +186,12 @@
extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
final List<MessagingMessage> historicMessagingMessages = createMessages(newHistoricMessages,
- /* isHistoric= */true, /* usePrecomputedText= */ false);
+ /* isHistoric= */true, usePrecomputedText);
final List<MessagingMessage> newMessagingMessages =
- createMessages(newMessages, /* isHistoric= */false, /* usePrecomputedText= */false);
- bindViews(user, showSpinner, historicMessagingMessages, newMessagingMessages);
+ createMessages(newMessages, /* isHistoric */false, usePrecomputedText);
+
+ return new MessagingData(user, showSpinner,
+ historicMessagingMessages, newMessagingMessages);
}
/**
@@ -193,7 +203,32 @@
*/
@NonNull
public Runnable setDataAsync(Bundle extras) {
- return () -> setData(extras);
+ if (!mPrecomputedTextEnabled) {
+ return () -> setData(extras);
+ }
+
+ final MessagingData messagingData =
+ parseMessagingData(extras, /* usePrecomputedText= */true);
+
+ return () -> {
+ finalizeInflate(messagingData.getHistoricMessagingMessages());
+ finalizeInflate(messagingData.getNewMessagingMessages());
+ bind(messagingData);
+ };
+ }
+
+ /**
+ * enable/disable precomputed text usage
+ * @hide
+ */
+ public void setPrecomputedTextEnabled(boolean precomputedTextEnabled) {
+ mPrecomputedTextEnabled = precomputedTextEnabled;
+ }
+
+ private void finalizeInflate(List<MessagingMessage> historicMessagingMessages) {
+ for (MessagingMessage messagingMessage: historicMessagingMessages) {
+ messagingMessage.finalizeInflate();
+ }
}
@Override
@@ -218,17 +253,13 @@
}
}
- private void bindViews(Person user, boolean showSpinner,
- List<MessagingMessage> historicMessagingMessages,
- List<MessagingMessage> newMessagingMessages) {
- setUser(user);
- bind(showSpinner, historicMessagingMessages, newMessagingMessages);
- }
+ private void bind(MessagingData messagingData) {
+ setUser(messagingData.getUser());
- private void bind(boolean showSpinner, List<MessagingMessage> historicMessages,
- List<MessagingMessage> messages) {
+ List<MessagingMessage> historicMessages = messagingData.getHistoricMessagingMessages();
+ List<MessagingMessage> messages = messagingData.getNewMessagingMessages();
ArrayList<MessagingGroup> oldGroups = new ArrayList<>(mGroups);
- addMessagesToGroups(historicMessages, messages, showSpinner);
+ addMessagesToGroups(historicMessages, messages, messagingData.getShowSpinner());
// Let's first check which groups were removed altogether and remove them in one animation
removeGroups(oldGroups);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt
index b002330..c276827 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt
@@ -20,7 +20,9 @@
import android.util.AttributeSet
import android.view.View
import android.widget.TextView
+import com.android.internal.widget.ConversationLayout
import com.android.internal.widget.ImageFloatingTextView
+import com.android.internal.widget.MessagingLayout
import javax.inject.Inject
class PrecomputedTextViewFactory @Inject constructor() : NotifRemoteViewsFactory {
@@ -35,6 +37,10 @@
TextView::class.java.simpleName -> PrecomputedTextView(context, attrs)
ImageFloatingTextView::class.java.name ->
PrecomputedImageFloatingTextView(context, attrs)
+ MessagingLayout::class.java.name ->
+ MessagingLayout(context, attrs).apply { setPrecomputedTextEnabled(true) }
+ ConversationLayout::class.java.name ->
+ ConversationLayout(context, attrs).apply { setPrecomputedTextEnabled(true) }
else -> null
}
}