1 /* 2 * Copyright 2018 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 package com.android.systemui.statusbar; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.app.Notification; 21 import android.app.RemoteInput; 22 import android.graphics.drawable.Icon; 23 import android.text.TextUtils; 24 25 import androidx.annotation.VisibleForTesting; 26 27 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 28 29 import java.util.Collections; 30 import java.util.List; 31 import java.util.Objects; 32 33 /** 34 * By diffing two entries, determines is view reinflation needed. 35 */ 36 public class NotificationUiAdjustment { 37 38 public final String key; 39 public final List<Notification.Action> smartActions; 40 public final List<CharSequence> smartReplies; 41 public final boolean isConversation; 42 43 @VisibleForTesting NotificationUiAdjustment( String key, List<Notification.Action> smartActions, List<CharSequence> smartReplies, boolean isConversation)44 NotificationUiAdjustment( 45 String key, List<Notification.Action> smartActions, List<CharSequence> smartReplies, 46 boolean isConversation) { 47 this.key = key; 48 this.smartActions = smartActions == null 49 ? Collections.emptyList() 50 : smartActions; 51 this.smartReplies = smartReplies == null 52 ? Collections.emptyList() 53 : smartReplies; 54 this.isConversation = isConversation; 55 } 56 extractFromNotificationEntry( NotificationEntry entry)57 public static NotificationUiAdjustment extractFromNotificationEntry( 58 NotificationEntry entry) { 59 return new NotificationUiAdjustment( 60 entry.getKey(), entry.getSmartActions(), entry.getSmartReplies(), 61 entry.getRanking().isConversation()); 62 } 63 needReinflate( @onNull NotificationUiAdjustment oldAdjustment, @NonNull NotificationUiAdjustment newAdjustment)64 public static boolean needReinflate( 65 @NonNull NotificationUiAdjustment oldAdjustment, 66 @NonNull NotificationUiAdjustment newAdjustment) { 67 if (oldAdjustment == newAdjustment) { 68 return false; 69 } 70 if (oldAdjustment.isConversation != newAdjustment.isConversation) { 71 return true; 72 } 73 if (areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions)) { 74 return true; 75 } 76 if (!newAdjustment.smartReplies.equals(oldAdjustment.smartReplies)) { 77 return true; 78 } 79 return false; 80 } 81 areDifferent( @onNull List<Notification.Action> first, @NonNull List<Notification.Action> second)82 public static boolean areDifferent( 83 @NonNull List<Notification.Action> first, @NonNull List<Notification.Action> second) { 84 if (first == second) { 85 return false; 86 } 87 if (first == null || second == null) { 88 return true; 89 } 90 if (first.size() != second.size()) { 91 return true; 92 } 93 for (int i = 0; i < first.size(); i++) { 94 Notification.Action firstAction = first.get(i); 95 Notification.Action secondAction = second.get(i); 96 97 if (!TextUtils.equals(firstAction.title, secondAction.title)) { 98 return true; 99 } 100 101 if (areDifferent(firstAction.getIcon(), secondAction.getIcon())) { 102 return true; 103 } 104 105 if (!Objects.equals(firstAction.actionIntent, secondAction.actionIntent)) { 106 return true; 107 } 108 109 if (areDifferent(firstAction.getRemoteInputs(), secondAction.getRemoteInputs())) { 110 return true; 111 } 112 } 113 return false; 114 } 115 areDifferent(@ullable Icon first, @Nullable Icon second)116 private static boolean areDifferent(@Nullable Icon first, @Nullable Icon second) { 117 if (first == second) { 118 return false; 119 } 120 if (first == null || second == null) { 121 return true; 122 } 123 return !first.sameAs(second); 124 } 125 areDifferent( @ullable RemoteInput[] first, @Nullable RemoteInput[] second)126 private static boolean areDifferent( 127 @Nullable RemoteInput[] first, @Nullable RemoteInput[] second) { 128 if (first == second) { 129 return false; 130 } 131 if (first == null || second == null) { 132 return true; 133 } 134 if (first.length != second.length) { 135 return true; 136 } 137 for (int i = 0; i < first.length; i++) { 138 RemoteInput firstRemoteInput = first[i]; 139 RemoteInput secondRemoteInput = second[i]; 140 141 if (!TextUtils.equals(firstRemoteInput.getLabel(), secondRemoteInput.getLabel())) { 142 return true; 143 } 144 if (areDifferent(firstRemoteInput.getChoices(), secondRemoteInput.getChoices())) { 145 return true; 146 } 147 } 148 return false; 149 } 150 areDifferent( @ullable CharSequence[] first, @Nullable CharSequence[] second)151 private static boolean areDifferent( 152 @Nullable CharSequence[] first, @Nullable CharSequence[] second) { 153 if (first == second) { 154 return false; 155 } 156 if (first == null || second == null) { 157 return true; 158 } 159 if (first.length != second.length) { 160 return true; 161 } 162 for (int i = 0; i < first.length; i++) { 163 CharSequence firstCharSequence = first[i]; 164 CharSequence secondCharSequence = second[i]; 165 if (!TextUtils.equals(firstCharSequence, secondCharSequence)) { 166 return true; 167 } 168 } 169 return false; 170 } 171 } 172