1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.internal.widget; 18 19 import android.app.ActivityManager; 20 import android.app.Notification; 21 import android.view.View; 22 23 import java.util.Objects; 24 25 /** 26 * A message of a {@link MessagingLayout}. 27 */ 28 public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { 29 30 /** 31 * Prefix for supported image MIME types 32 **/ 33 String IMAGE_MIME_TYPE_PREFIX = "image/"; 34 createMessage(MessagingLayout layout, Notification.MessagingStyle.Message m, ImageResolver resolver)35 static MessagingMessage createMessage(MessagingLayout layout, 36 Notification.MessagingStyle.Message m, ImageResolver resolver) { 37 if (hasImage(m) && !ActivityManager.isLowRamDeviceStatic()) { 38 return MessagingImageMessage.createMessage(layout, m, resolver); 39 } else { 40 return MessagingTextMessage.createMessage(layout, m); 41 } 42 } 43 dropCache()44 static void dropCache() { 45 MessagingTextMessage.dropCache(); 46 MessagingImageMessage.dropCache(); 47 } 48 hasImage(Notification.MessagingStyle.Message m)49 static boolean hasImage(Notification.MessagingStyle.Message m) { 50 return m.getDataUri() != null 51 && m.getDataMimeType() != null 52 && m.getDataMimeType().startsWith(IMAGE_MIME_TYPE_PREFIX); 53 } 54 55 /** 56 * Set a message for this view. 57 * @return true if setting the message worked 58 */ setMessage(Notification.MessagingStyle.Message message)59 default boolean setMessage(Notification.MessagingStyle.Message message) { 60 getState().setMessage(message); 61 return true; 62 } 63 getMessage()64 default Notification.MessagingStyle.Message getMessage() { 65 return getState().getMessage(); 66 } 67 sameAs(Notification.MessagingStyle.Message message)68 default boolean sameAs(Notification.MessagingStyle.Message message) { 69 Notification.MessagingStyle.Message ownMessage = getMessage(); 70 if (!Objects.equals(message.getText(), ownMessage.getText())) { 71 return false; 72 } 73 if (!Objects.equals(message.getSender(), ownMessage.getSender())) { 74 return false; 75 } 76 boolean hasRemoteInputHistoryChanged = message.isRemoteInputHistory() 77 != ownMessage.isRemoteInputHistory(); 78 // When the remote input history has changed, we want to regard messages equal even when 79 // the timestamp changes. The main reason is that the message that the system inserts 80 // will have a different time set than the one that the app will update us with and we 81 // still want to reuse that message. 82 if (!hasRemoteInputHistoryChanged 83 && !Objects.equals(message.getTimestamp(), ownMessage.getTimestamp())) { 84 return false; 85 } 86 if (!Objects.equals(message.getDataMimeType(), ownMessage.getDataMimeType())) { 87 return false; 88 } 89 if (!Objects.equals(message.getDataUri(), ownMessage.getDataUri())) { 90 return false; 91 } 92 return true; 93 } 94 sameAs(MessagingMessage message)95 default boolean sameAs(MessagingMessage message) { 96 return sameAs(message.getMessage()); 97 } 98 removeMessage()99 default void removeMessage() { 100 getGroup().removeMessage(this); 101 } 102 setMessagingGroup(MessagingGroup group)103 default void setMessagingGroup(MessagingGroup group) { 104 getState().setGroup(group); 105 } 106 setIsHistoric(boolean isHistoric)107 default void setIsHistoric(boolean isHistoric) { 108 getState().setIsHistoric(isHistoric); 109 } 110 getGroup()111 default MessagingGroup getGroup() { 112 return getState().getGroup(); 113 } 114 setIsHidingAnimated(boolean isHiding)115 default void setIsHidingAnimated(boolean isHiding) { 116 getState().setIsHidingAnimated(isHiding); 117 } 118 119 @Override isHidingAnimated()120 default boolean isHidingAnimated() { 121 return getState().isHidingAnimated(); 122 } 123 124 @Override hideAnimated()125 default void hideAnimated() { 126 setIsHidingAnimated(true); 127 getGroup().performRemoveAnimation(getView(), () -> setIsHidingAnimated(false)); 128 } 129 hasOverlappingRendering()130 default boolean hasOverlappingRendering() { 131 return false; 132 } 133 recycle()134 default void recycle() { 135 getState().recycle(); 136 } 137 getView()138 default View getView() { 139 return (View) this; 140 } 141 setColor(int textColor)142 default void setColor(int textColor) {} 143 getState()144 MessagingMessageState getState(); 145 setVisibility(int visibility)146 void setVisibility(int visibility); 147 getVisibility()148 int getVisibility(); 149 } 150