diff options
5 files changed, 87 insertions, 33 deletions
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 7dda91d7b25e..5b6b36043684 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -410,9 +410,11 @@ public class ConversationLayout extends FrameLayout // convert MessagingStyle.Message to MessagingMessage, re-using ones from a previous binding // if they exist final List<MessagingMessage> newMessagingMessages = - createMessages(newMessages, false /* isHistoric */); + createMessages(newMessages, /* isHistoric= */false, + /* usePrecomputedText= */false); final List<MessagingMessage> newHistoricMessagingMessages = - createMessages(newHistoricMessages, true /* isHistoric */); + createMessages(newHistoricMessages, /* isHistoric= */true, + /* usePrecomputedText= */false); // bind it, baby bindViews(user, showSpinner, unreadCount, newMessagingMessages, @@ -981,15 +983,17 @@ public class ConversationLayout extends FrameLayout * @param newMessages the messages to parse. */ private List<MessagingMessage> createMessages( - List<Notification.MessagingStyle.Message> newMessages, boolean historic) { + List<Notification.MessagingStyle.Message> newMessages, boolean isHistoric, + boolean usePrecomputedText) { List<MessagingMessage> result = new ArrayList<>(); for (int i = 0; i < newMessages.size(); i++) { Notification.MessagingStyle.Message m = newMessages.get(i); MessagingMessage message = findAndRemoveMatchingMessage(m); if (message == null) { - message = MessagingMessage.createMessage(this, m, mImageResolver); + message = MessagingMessage.createMessage(this, m, + mImageResolver, usePrecomputedText); } - message.setIsHistoric(historic); + message.setIsHistoric(isHistoric); result.add(message); } return result; diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java index 098bce14e619..c132d6a90f6c 100644 --- a/core/java/com/android/internal/widget/MessagingImageMessage.java +++ b/core/java/com/android/internal/widget/MessagingImageMessage.java @@ -93,8 +93,9 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage } @Override - public boolean setMessage(Notification.MessagingStyle.Message message) { - MessagingMessage.super.setMessage(message); + public boolean setMessage(Notification.MessagingStyle.Message message, + boolean usePrecomputedText) { + MessagingMessage.super.setMessage(message, usePrecomputedText); Drawable drawable; try { Uri uri = message.getDataUri(); @@ -114,32 +115,42 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage } mDrawable = drawable; mAspectRatio = ((float) mDrawable.getIntrinsicWidth()) / intrinsicHeight; - setImageDrawable(drawable); - setContentDescription(message.getText()); + if (!usePrecomputedText) { + finalizeInflate(); + } return true; } static MessagingMessage createMessage(IMessagingLayout layout, - Notification.MessagingStyle.Message m, ImageResolver resolver) { + Notification.MessagingStyle.Message m, ImageResolver resolver, + boolean usePrecomputedText) { MessagingLinearLayout messagingLinearLayout = layout.getMessagingLinearLayout(); MessagingImageMessage createdMessage = sInstancePool.acquire(); if (createdMessage == null) { createdMessage = (MessagingImageMessage) LayoutInflater.from( layout.getContext()).inflate( - R.layout.notification_template_messaging_image_message, - messagingLinearLayout, - false); + R.layout.notification_template_messaging_image_message, + messagingLinearLayout, + false); createdMessage.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR); } createdMessage.setImageResolver(resolver); - boolean created = createdMessage.setMessage(m); - if (!created) { + // MessagingImageMessage does not use usePrecomputedText. + boolean populated = createdMessage.setMessage(m, /* usePrecomputedText= */false); + if (!populated) { createdMessage.recycle(); - return MessagingTextMessage.createMessage(layout, m); + return MessagingTextMessage.createMessage(layout, m, usePrecomputedText); } return createdMessage; } + + @Override + public void finalizeInflate() { + setImageDrawable(mDrawable); + setContentDescription(getMessage().getText()); + } + private void setImageResolver(ImageResolver resolver) { mImageResolver = resolver; } diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index 8345c5cc9ef9..83557cd8a719 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -178,9 +178,9 @@ public class MessagingLayout extends FrameLayout extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false); final List<MessagingMessage> historicMessagingMessages = createMessages(newHistoricMessages, - true /* isHistoric */); + /* isHistoric= */true, /* usePrecomputedText= */ false); final List<MessagingMessage> newMessagingMessages = - createMessages(newMessages, false /* isHistoric */); + createMessages(newMessages, /* isHistoric= */false, /* usePrecomputedText= */false); bindViews(user, showSpinner, historicMessagingMessages, newMessagingMessages); } @@ -518,15 +518,17 @@ public class MessagingLayout extends FrameLayout * @param newMessages the messages to parse. */ private List<MessagingMessage> createMessages( - List<Notification.MessagingStyle.Message> newMessages, boolean historic) { + List<Notification.MessagingStyle.Message> newMessages, boolean isHistoric, + boolean usePrecomputedText) { List<MessagingMessage> result = new ArrayList<>(); for (int i = 0; i < newMessages.size(); i++) { Notification.MessagingStyle.Message m = newMessages.get(i); MessagingMessage message = findAndRemoveMatchingMessage(m); if (message == null) { - message = MessagingMessage.createMessage(this, m, mImageResolver); + message = MessagingMessage.createMessage(this, m, + mImageResolver, usePrecomputedText); } - message.setIsHistoric(historic); + message.setIsHistoric(isHistoric); result.add(message); } return result; diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java index 5ecd3b82053d..ad90a63ab187 100644 --- a/core/java/com/android/internal/widget/MessagingMessage.java +++ b/core/java/com/android/internal/widget/MessagingMessage.java @@ -34,11 +34,12 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { String IMAGE_MIME_TYPE_PREFIX = "image/"; static MessagingMessage createMessage(IMessagingLayout layout, - Notification.MessagingStyle.Message m, ImageResolver resolver) { + Notification.MessagingStyle.Message m, ImageResolver resolver, + boolean usePrecomputedText) { if (hasImage(m) && !ActivityManager.isLowRamDeviceStatic()) { - return MessagingImageMessage.createMessage(layout, m, resolver); + return MessagingImageMessage.createMessage(layout, m, resolver, usePrecomputedText); } else { - return MessagingTextMessage.createMessage(layout, m); + return MessagingTextMessage.createMessage(layout, m, usePrecomputedText); } } @@ -55,9 +56,11 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { /** * Set a message for this view. + * * @return true if setting the message worked */ - default boolean setMessage(Notification.MessagingStyle.Message message) { + default boolean setMessage(Notification.MessagingStyle.Message message, + boolean usePrecomputedText) { getState().setMessage(message); return true; } @@ -151,4 +154,10 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { void setVisibility(int visibility); int getVisibility(); + + /** + * Finalize inflation of the MessagingMessages, which should be called on Main Thread. + * @hide + */ + void finalizeInflate(); } diff --git a/core/java/com/android/internal/widget/MessagingTextMessage.java b/core/java/com/android/internal/widget/MessagingTextMessage.java index 19791dbad31e..bd62aad15b34 100644 --- a/core/java/com/android/internal/widget/MessagingTextMessage.java +++ b/core/java/com/android/internal/widget/MessagingTextMessage.java @@ -23,7 +23,9 @@ import android.annotation.StyleRes; import android.app.Notification; import android.content.Context; import android.text.Layout; +import android.text.PrecomputedText; import android.util.AttributeSet; +import android.util.Log; import android.view.LayoutInflater; import android.widget.RemoteViews; @@ -35,10 +37,13 @@ import com.android.internal.R; @RemoteViews.RemoteView public class MessagingTextMessage extends ImageFloatingTextView implements MessagingMessage { + private static final String TAG = "MessagingTextMessage"; private static final MessagingPool<MessagingTextMessage> sInstancePool = new MessagingPool<>(20); private final MessagingMessageState mState = new MessagingMessageState(this); + private PrecomputedText mPrecomputedText = null; + public MessagingTextMessage(@NonNull Context context) { super(context); } @@ -63,25 +68,32 @@ public class MessagingTextMessage extends ImageFloatingTextView implements Messa } @Override - public boolean setMessage(Notification.MessagingStyle.Message message) { - MessagingMessage.super.setMessage(message); - setText(message.getText()); + public boolean setMessage(Notification.MessagingStyle.Message message, + boolean usePrecomputedText) { + MessagingMessage.super.setMessage(message, usePrecomputedText); + if (usePrecomputedText) { + mPrecomputedText = PrecomputedText.create(message.getText(), getTextMetricsParams()); + } else { + setText(message.getText()); + mPrecomputedText = null; + } + return true; } static MessagingMessage createMessage(IMessagingLayout layout, - Notification.MessagingStyle.Message m) { + Notification.MessagingStyle.Message m, boolean usePrecomputedText) { MessagingLinearLayout messagingLinearLayout = layout.getMessagingLinearLayout(); MessagingTextMessage createdMessage = sInstancePool.acquire(); if (createdMessage == null) { createdMessage = (MessagingTextMessage) LayoutInflater.from( layout.getContext()).inflate( - R.layout.notification_template_messaging_text_message, - messagingLinearLayout, - false); + R.layout.notification_template_messaging_text_message, + messagingLinearLayout, + false); createdMessage.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR); } - createdMessage.setMessage(m); + createdMessage.setMessage(m, usePrecomputedText); return createdMessage; } @@ -135,4 +147,20 @@ public class MessagingTextMessage extends ImageFloatingTextView implements Messa public void setColor(int color) { setTextColor(color); } + + @Override + public void finalizeInflate() { + try { + setText(mPrecomputedText != null ? mPrecomputedText + : getState().getMessage().getText()); + } catch (IllegalArgumentException exception) { + Log.wtf( + /* tag = */ TAG, + /* msg = */ "PrecomputedText setText failed for TextView:" + this, + /* tr = */ exception + ); + mPrecomputedText = null; + setText(getState().getMessage().getText()); + } + } } |