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