Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 957591ac authored by Ibrahim Yilmaz's avatar Ibrahim Yilmaz Committed by Android (Google) Code Review
Browse files

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
parents b25e7187 bee51838
Loading
Loading
Loading
Loading
+53 −30
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ public class ConversationLayout extends FrameLayout
    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 @@ public class ConversationLayout extends FrameLayout
     */
    @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,9 +432,35 @@ public class ConversationLayout extends FrameLayout
     */
    @NonNull
    public Runnable setDataAsync(Bundle 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
    public void setImageResolver(ImageResolver resolver) {
        mImageResolver = resolver;
@@ -460,17 +488,12 @@ public class ConversationLayout extends FrameLayout
        }
    }

    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 @@ public class ConversationLayout extends FrameLayout

        // 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);
+70 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+52 −21
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ public class MessagingLayout extends FrameLayout
    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 @@ public class MessagingLayout extends FrameLayout
     */
    @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 @@ public class MessagingLayout extends FrameLayout
                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,9 +203,34 @@ public class MessagingLayout extends FrameLayout
     */
    @NonNull
    public Runnable setDataAsync(Bundle 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
    public void setImageResolver(ImageResolver resolver) {
        mImageResolver = resolver;
@@ -218,17 +253,13 @@ public class MessagingLayout extends FrameLayout
        }
    }

    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);
+6 −0
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ import android.content.Context
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 @@ class PrecomputedTextViewFactory @Inject constructor() : NotifRemoteViewsFactory
            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
        }
    }