Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 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 | |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 17 | package com.android.systemui.statusbar.notification.row; |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 18 | |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 19 | import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED; |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 20 | import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; |
| 21 | |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 22 | import android.annotation.IntDef; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 23 | import android.annotation.Nullable; |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 24 | import android.app.Notification; |
| 25 | import android.content.Context; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 26 | import android.os.AsyncTask; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 27 | import android.os.CancellationSignal; |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 28 | import android.service.notification.StatusBarNotification; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 29 | import android.util.ArrayMap; |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 30 | import android.util.Log; |
| 31 | import android.view.View; |
| 32 | import android.widget.RemoteViews; |
| 33 | |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 34 | import com.android.internal.annotations.VisibleForTesting; |
Ahan Wu | de396fa | 2018-05-08 20:42:24 +0800 | [diff] [blame] | 35 | import com.android.internal.widget.ImageMessageConsumer; |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 36 | import com.android.systemui.Dependency; |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 37 | import com.android.systemui.statusbar.InflationTask; |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 38 | import com.android.systemui.statusbar.SmartReplyController; |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 39 | import com.android.systemui.statusbar.notification.InflationException; |
| 40 | import com.android.systemui.statusbar.notification.MediaNotificationProcessor; |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 41 | import com.android.systemui.statusbar.notification.collection.NotificationEntry; |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 42 | import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 43 | import com.android.systemui.statusbar.phone.StatusBar; |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 44 | import com.android.systemui.statusbar.policy.HeadsUpManager; |
| 45 | import com.android.systemui.statusbar.policy.InflatedSmartReplies; |
Gustav Sennton | 8a52dc3 | 2019-04-15 12:48:23 +0100 | [diff] [blame] | 46 | import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions; |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 47 | import com.android.systemui.statusbar.policy.SmartReplyConstants; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 48 | import com.android.systemui.util.Assert; |
| 49 | |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 50 | import java.lang.annotation.Retention; |
| 51 | import java.lang.annotation.RetentionPolicy; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 52 | import java.util.HashMap; |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 53 | |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 54 | /** |
| 55 | * A utility that inflates the right kind of contentView based on the state |
| 56 | */ |
Ned Burns | 1a5e22f | 2019-02-14 15:11:52 -0500 | [diff] [blame] | 57 | public class NotificationContentInflater { |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 58 | |
Ned Burns | 1a5e22f | 2019-02-14 15:11:52 -0500 | [diff] [blame] | 59 | public static final String TAG = "NotifContentInflater"; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 60 | |
| 61 | @Retention(RetentionPolicy.SOURCE) |
| 62 | @IntDef(flag = true, |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 63 | prefix = {"FLAG_CONTENT_VIEW_"}, |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 64 | value = { |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 65 | FLAG_CONTENT_VIEW_CONTRACTED, |
| 66 | FLAG_CONTENT_VIEW_EXPANDED, |
| 67 | FLAG_CONTENT_VIEW_HEADS_UP, |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 68 | FLAG_CONTENT_VIEW_PUBLIC, |
| 69 | FLAG_CONTENT_VIEW_ALL}) |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 70 | public @interface InflationFlag {} |
| 71 | /** |
| 72 | * The default, contracted view. Seen when the shade is pulled down and in the lock screen |
| 73 | * if there is no worry about content sensitivity. |
| 74 | */ |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 75 | public static final int FLAG_CONTENT_VIEW_CONTRACTED = 1; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 76 | |
| 77 | /** |
| 78 | * The expanded view. Seen when the user expands a notification. |
| 79 | */ |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 80 | public static final int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 81 | |
| 82 | /** |
| 83 | * The heads up view. Seen when a high priority notification peeks in from the top. |
| 84 | */ |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 85 | public static final int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 86 | |
| 87 | /** |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 88 | * The public view. This is a version of the contracted view that hides sensitive |
| 89 | * information and is used on the lock screen if we determine that the notification's |
| 90 | * content should be hidden. |
| 91 | */ |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 92 | public static final int FLAG_CONTENT_VIEW_PUBLIC = 1 << 3; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 93 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 94 | public static final int FLAG_CONTENT_VIEW_ALL = ~0; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 95 | |
| 96 | /** |
| 97 | * Content views that must be inflated at all times. |
| 98 | */ |
| 99 | @InflationFlag |
| 100 | private static final int REQUIRED_INFLATION_FLAGS = |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 101 | FLAG_CONTENT_VIEW_CONTRACTED |
Kevin | 01a53cb | 2018-11-09 18:19:54 -0800 | [diff] [blame] | 102 | | FLAG_CONTENT_VIEW_EXPANDED; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 103 | |
| 104 | /** |
| 105 | * The set of content views to inflate. |
| 106 | */ |
| 107 | @InflationFlag |
| 108 | private int mInflationFlags = REQUIRED_INFLATION_FLAGS; |
| 109 | |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 110 | private final ExpandableNotificationRow mRow; |
| 111 | private boolean mIsLowPriority; |
| 112 | private boolean mUsesIncreasedHeight; |
| 113 | private boolean mUsesIncreasedHeadsUpHeight; |
| 114 | private RemoteViews.OnClickHandler mRemoteViewClickHandler; |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 115 | private boolean mIsChildInGroup; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 116 | private InflationCallback mCallback; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 117 | private boolean mInflateSynchronously = false; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 118 | private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>(); |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 119 | |
Ned Burns | 1a5e22f | 2019-02-14 15:11:52 -0500 | [diff] [blame] | 120 | public NotificationContentInflater(ExpandableNotificationRow row) { |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 121 | mRow = row; |
| 122 | } |
| 123 | |
| 124 | public void setIsLowPriority(boolean isLowPriority) { |
| 125 | mIsLowPriority = isLowPriority; |
| 126 | } |
| 127 | |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 128 | /** |
| 129 | * Set whether the notification is a child in a group |
| 130 | * |
| 131 | * @return whether the view was re-inflated |
| 132 | */ |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 133 | public void setIsChildInGroup(boolean childInGroup) { |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 134 | if (childInGroup != mIsChildInGroup) { |
| 135 | mIsChildInGroup = childInGroup; |
| 136 | if (mIsLowPriority) { |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 137 | int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 138 | inflateNotificationViews(flags); |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 139 | } |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 140 | } |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 141 | } |
| 142 | |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 143 | public void setUsesIncreasedHeight(boolean usesIncreasedHeight) { |
| 144 | mUsesIncreasedHeight = usesIncreasedHeight; |
| 145 | } |
| 146 | |
| 147 | public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) { |
| 148 | mUsesIncreasedHeadsUpHeight = usesIncreasedHeight; |
| 149 | } |
| 150 | |
| 151 | public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) { |
| 152 | mRemoteViewClickHandler = remoteViewClickHandler; |
| 153 | } |
| 154 | |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 155 | /** |
| 156 | * Update whether or not the notification is redacted on the lock screen. If the notification |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 157 | * is now redacted, we should inflate the public contracted view to now show on the lock screen. |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 158 | * |
| 159 | * @param needsRedaction true if the notification should now be redacted on the lock screen |
| 160 | */ |
| 161 | public void updateNeedsRedaction(boolean needsRedaction) { |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 162 | if (mRow.getEntry() == null) { |
| 163 | return; |
Adrian Roos | 1a1ecfc | 2017-04-17 11:17:59 -0700 | [diff] [blame] | 164 | } |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 165 | if (needsRedaction) { |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 166 | int flags = FLAG_CONTENT_VIEW_PUBLIC; |
| 167 | inflateNotificationViews(flags); |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 168 | } |
Adrian Roos | 1a1ecfc | 2017-04-17 11:17:59 -0700 | [diff] [blame] | 169 | } |
| 170 | |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 171 | /** |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 172 | * Set whether or not a particular content view is needed and whether or not it should be |
| 173 | * inflated. These flags will be used when we inflate or reinflate. |
| 174 | * |
| 175 | * @param flag the {@link InflationFlag} corresponding to the view that should/should not be |
| 176 | * inflated |
| 177 | * @param shouldInflate true if the view should be inflated, false otherwise |
| 178 | */ |
| 179 | public void updateInflationFlag(@InflationFlag int flag, boolean shouldInflate) { |
| 180 | if (shouldInflate) { |
| 181 | mInflationFlags |= flag; |
| 182 | } else if ((REQUIRED_INFLATION_FLAGS & flag) == 0) { |
| 183 | mInflationFlags &= ~flag; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | /** |
Kevin | 01a53cb | 2018-11-09 18:19:54 -0800 | [diff] [blame] | 188 | * Convenience method for setting multiple flags at once. |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 189 | * |
| 190 | * @param flags a set of {@link InflationFlag} corresponding to content views that should be |
| 191 | * inflated |
| 192 | */ |
Kevin | 01a53cb | 2018-11-09 18:19:54 -0800 | [diff] [blame] | 193 | @VisibleForTesting |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 194 | public void addInflationFlags(@InflationFlag int flags) { |
| 195 | mInflationFlags |= flags; |
| 196 | } |
| 197 | |
| 198 | /** |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 199 | * Whether or not the view corresponding to the flag is set to be inflated currently. |
| 200 | * |
| 201 | * @param flag the {@link InflationFlag} corresponding to the view |
| 202 | * @return true if the flag is set and view will be inflated, false o/w |
| 203 | */ |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 204 | public boolean isInflationFlagSet(@InflationFlag int flag) { |
| 205 | return ((mInflationFlags & flag) != 0); |
| 206 | } |
| 207 | |
| 208 | /** |
Kevin | 01a53cb | 2018-11-09 18:19:54 -0800 | [diff] [blame] | 209 | * Inflate views for set flags on a background thread. This is asynchronous and will |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 210 | * notify the callback once it's finished. |
| 211 | */ |
| 212 | public void inflateNotificationViews() { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 213 | inflateNotificationViews(mInflationFlags); |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 214 | } |
| 215 | |
| 216 | /** |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 217 | * Inflate all views for the specified flags on a background thread. This is asynchronous and |
| 218 | * will notify the callback once it's finished. If the content view is already inflated, this |
| 219 | * will reinflate it. |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 220 | * |
Kevin | 01a53cb | 2018-11-09 18:19:54 -0800 | [diff] [blame] | 221 | * @param reInflateFlags flags which views should be inflated. Should be a subset of |
Ned Burns | 1a5e22f | 2019-02-14 15:11:52 -0500 | [diff] [blame] | 222 | * {@link #mInflationFlags} as only those will be inflated/reinflated. |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 223 | */ |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 224 | private void inflateNotificationViews(@InflationFlag int reInflateFlags) { |
Selim Cinek | 67ff248 | 2017-05-25 10:27:28 -0700 | [diff] [blame] | 225 | if (mRow.isRemoved()) { |
| 226 | // We don't want to reinflate anything for removed notifications. Otherwise views might |
| 227 | // be readded to the stack, leading to leaks. This may happen with low-priority groups |
| 228 | // where the removal of already removed children can lead to a reinflation. |
| 229 | return; |
| 230 | } |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 231 | // Only inflate the ones that are set. |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 232 | reInflateFlags &= mInflationFlags; |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 233 | StatusBarNotification sbn = mRow.getEntry().notification; |
Ahan Wu | de396fa | 2018-05-08 20:42:24 +0800 | [diff] [blame] | 234 | |
| 235 | // To check if the notification has inline image and preload inline image if necessary. |
| 236 | mRow.getImageResolver().preloadImages(sbn.getNotification()); |
| 237 | |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 238 | AsyncInflationTask task = new AsyncInflationTask( |
| 239 | sbn, |
| 240 | mInflateSynchronously, |
| 241 | reInflateFlags, |
| 242 | mCachedContentViews, |
| 243 | mRow, |
| 244 | mIsLowPriority, |
| 245 | mIsChildInGroup, |
| 246 | mUsesIncreasedHeight, |
| 247 | mUsesIncreasedHeadsUpHeight, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 248 | mCallback, |
| 249 | mRemoteViewClickHandler); |
| 250 | if (mInflateSynchronously) { |
Jason Monk | 6dceace | 2018-05-15 20:24:07 -0400 | [diff] [blame] | 251 | task.onPostExecute(task.doInBackground()); |
| 252 | } else { |
| 253 | task.execute(); |
| 254 | } |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 255 | } |
| 256 | |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 257 | @VisibleForTesting |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 258 | InflationProgress inflateNotificationViews( |
| 259 | boolean inflateSynchronously, |
| 260 | @InflationFlag int reInflateFlags, |
| 261 | Notification.Builder builder, |
| 262 | Context packageContext) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 263 | InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority, |
| 264 | mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 265 | packageContext); |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 266 | result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(), |
Gustav Sennton | 8a52dc3 | 2019-04-15 12:48:23 +0100 | [diff] [blame] | 267 | mRow.getContext(), mRow.getHeadsUpManager(), |
| 268 | mRow.getExistingSmartRepliesAndActions()); |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 269 | apply( |
| 270 | inflateSynchronously, |
| 271 | result, |
| 272 | reInflateFlags, |
| 273 | mCachedContentViews, |
| 274 | mRow, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 275 | mRemoteViewClickHandler, |
| 276 | null); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 277 | return result; |
| 278 | } |
Adrian Roos | 1a1ecfc | 2017-04-17 11:17:59 -0700 | [diff] [blame] | 279 | |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 280 | /** |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 281 | * Frees the content view associated with the inflation flag. Will only succeed if the |
| 282 | * view is safe to remove. |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 283 | * |
| 284 | * @param inflateFlag the flag corresponding to the content view which should be freed |
| 285 | */ |
| 286 | public void freeNotificationView(@InflationFlag int inflateFlag) { |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 287 | if ((mInflationFlags & inflateFlag) != 0) { |
| 288 | // The view should still be inflated. |
| 289 | return; |
| 290 | } |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 291 | switch (inflateFlag) { |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 292 | case FLAG_CONTENT_VIEW_HEADS_UP: |
| 293 | if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) { |
| 294 | mRow.getPrivateLayout().setHeadsUpChild(null); |
| 295 | mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP); |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 296 | mRow.getPrivateLayout().setHeadsUpInflatedSmartReplies(null); |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 297 | } |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 298 | break; |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 299 | case FLAG_CONTENT_VIEW_PUBLIC: |
| 300 | if (mRow.getPublicLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) { |
| 301 | mRow.getPublicLayout().setContractedChild(null); |
| 302 | mCachedContentViews.remove(FLAG_CONTENT_VIEW_PUBLIC); |
| 303 | } |
| 304 | break; |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 305 | case FLAG_CONTENT_VIEW_CONTRACTED: |
| 306 | case FLAG_CONTENT_VIEW_EXPANDED: |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 307 | default: |
| 308 | break; |
| 309 | } |
| 310 | } |
| 311 | |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 312 | private static InflationProgress inflateSmartReplyViews(InflationProgress result, |
| 313 | @InflationFlag int reInflateFlags, NotificationEntry entry, Context context, |
Gustav Sennton | 8a52dc3 | 2019-04-15 12:48:23 +0100 | [diff] [blame] | 314 | HeadsUpManager headsUpManager, SmartRepliesAndActions previousSmartRepliesAndActions) { |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 315 | SmartReplyConstants smartReplyConstants = Dependency.get(SmartReplyConstants.class); |
| 316 | SmartReplyController smartReplyController = Dependency.get(SmartReplyController.class); |
| 317 | if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0 && result.newExpandedView != null) { |
| 318 | result.expandedInflatedSmartReplies = |
| 319 | InflatedSmartReplies.inflate( |
| 320 | context, entry, smartReplyConstants, smartReplyController, |
Gustav Sennton | 8a52dc3 | 2019-04-15 12:48:23 +0100 | [diff] [blame] | 321 | headsUpManager, previousSmartRepliesAndActions); |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 322 | } |
| 323 | if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0 && result.newHeadsUpView != null) { |
| 324 | result.headsUpInflatedSmartReplies = |
| 325 | InflatedSmartReplies.inflate( |
| 326 | context, entry, smartReplyConstants, smartReplyController, |
Gustav Sennton | 8a52dc3 | 2019-04-15 12:48:23 +0100 | [diff] [blame] | 327 | headsUpManager, previousSmartRepliesAndActions); |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 328 | } |
| 329 | return result; |
| 330 | } |
| 331 | |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 332 | private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 333 | Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 334 | boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 335 | Context packageContext) { |
| 336 | InflationProgress result = new InflationProgress(); |
| 337 | isLowPriority = isLowPriority && !isChildInGroup; |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 338 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 339 | if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 340 | result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight); |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 341 | } |
| 342 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 343 | if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 344 | result.newExpandedView = createExpandedView(builder, isLowPriority); |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 345 | } |
| 346 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 347 | if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 348 | result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight); |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 349 | } |
| 350 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 351 | if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) { |
Selim Cinek | abcc201 | 2019-07-23 18:44:07 -0700 | [diff] [blame] | 352 | result.newPublicView = builder.makePublicContentView(isLowPriority); |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 353 | } |
| 354 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 355 | result.packageContext = packageContext; |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 356 | result.headsUpStatusBarText = builder.getHeadsUpStatusBarText(false /* showingPublic */); |
| 357 | result.headsUpStatusBarTextPublic = builder.getHeadsUpStatusBarText( |
| 358 | true /* showingPublic */); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 359 | return result; |
| 360 | } |
Adrian Roos | 1a1ecfc | 2017-04-17 11:17:59 -0700 | [diff] [blame] | 361 | |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 362 | public static CancellationSignal apply( |
| 363 | boolean inflateSynchronously, |
| 364 | InflationProgress result, |
| 365 | @InflationFlag int reInflateFlags, |
| 366 | ArrayMap<Integer, RemoteViews> cachedContentViews, |
| 367 | ExpandableNotificationRow row, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 368 | RemoteViews.OnClickHandler remoteViewClickHandler, |
| 369 | @Nullable InflationCallback callback) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 370 | NotificationContentView privateLayout = row.getPrivateLayout(); |
| 371 | NotificationContentView publicLayout = row.getPublicLayout(); |
| 372 | final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>(); |
| 373 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 374 | int flag = FLAG_CONTENT_VIEW_CONTRACTED; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 375 | if ((reInflateFlags & flag) != 0) { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 376 | boolean isNewView = |
| 377 | !canReapplyRemoteView(result.newContentView, |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 378 | cachedContentViews.get(FLAG_CONTENT_VIEW_CONTRACTED)); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 379 | ApplyCallback applyCallback = new ApplyCallback() { |
| 380 | @Override |
| 381 | public void setResultView(View v) { |
| 382 | result.inflatedContentView = v; |
| 383 | } |
| 384 | |
| 385 | @Override |
| 386 | public RemoteViews getRemoteView() { |
| 387 | return result.newContentView; |
| 388 | } |
| 389 | }; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 390 | applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, cachedContentViews, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 391 | row, isNewView, remoteViewClickHandler, callback, privateLayout, |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 392 | privateLayout.getContractedChild(), privateLayout.getVisibleWrapper( |
| 393 | NotificationContentView.VISIBLE_TYPE_CONTRACTED), |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 394 | runningInflations, applyCallback); |
| 395 | } |
| 396 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 397 | flag = FLAG_CONTENT_VIEW_EXPANDED; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 398 | if ((reInflateFlags & flag) != 0) { |
| 399 | if (result.newExpandedView != null) { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 400 | boolean isNewView = |
| 401 | !canReapplyRemoteView(result.newExpandedView, |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 402 | cachedContentViews.get(FLAG_CONTENT_VIEW_EXPANDED)); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 403 | ApplyCallback applyCallback = new ApplyCallback() { |
| 404 | @Override |
| 405 | public void setResultView(View v) { |
| 406 | result.inflatedExpandedView = v; |
| 407 | } |
| 408 | |
| 409 | @Override |
| 410 | public RemoteViews getRemoteView() { |
| 411 | return result.newExpandedView; |
| 412 | } |
| 413 | }; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 414 | applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 415 | cachedContentViews, row, isNewView, remoteViewClickHandler, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 416 | callback, privateLayout, privateLayout.getExpandedChild(), |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 417 | privateLayout.getVisibleWrapper( |
| 418 | NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 419 | applyCallback); |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 420 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 421 | } |
| 422 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 423 | flag = FLAG_CONTENT_VIEW_HEADS_UP; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 424 | if ((reInflateFlags & flag) != 0) { |
| 425 | if (result.newHeadsUpView != null) { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 426 | boolean isNewView = |
| 427 | !canReapplyRemoteView(result.newHeadsUpView, |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 428 | cachedContentViews.get(FLAG_CONTENT_VIEW_HEADS_UP)); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 429 | ApplyCallback applyCallback = new ApplyCallback() { |
| 430 | @Override |
| 431 | public void setResultView(View v) { |
| 432 | result.inflatedHeadsUpView = v; |
| 433 | } |
| 434 | |
| 435 | @Override |
| 436 | public RemoteViews getRemoteView() { |
| 437 | return result.newHeadsUpView; |
| 438 | } |
| 439 | }; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 440 | applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 441 | cachedContentViews, row, isNewView, remoteViewClickHandler, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 442 | callback, privateLayout, privateLayout.getHeadsUpChild(), |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 443 | privateLayout.getVisibleWrapper( |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 444 | VISIBLE_TYPE_HEADSUP), runningInflations, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 445 | applyCallback); |
| 446 | } |
| 447 | } |
| 448 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 449 | flag = FLAG_CONTENT_VIEW_PUBLIC; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 450 | if ((reInflateFlags & flag) != 0) { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 451 | boolean isNewView = |
| 452 | !canReapplyRemoteView(result.newPublicView, |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 453 | cachedContentViews.get(FLAG_CONTENT_VIEW_PUBLIC)); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 454 | ApplyCallback applyCallback = new ApplyCallback() { |
| 455 | @Override |
| 456 | public void setResultView(View v) { |
| 457 | result.inflatedPublicView = v; |
| 458 | } |
| 459 | |
| 460 | @Override |
| 461 | public RemoteViews getRemoteView() { |
| 462 | return result.newPublicView; |
| 463 | } |
| 464 | }; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 465 | applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, cachedContentViews, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 466 | row, isNewView, remoteViewClickHandler, callback, |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 467 | publicLayout, publicLayout.getContractedChild(), |
| 468 | publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED), |
| 469 | runningInflations, applyCallback); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 470 | } |
| 471 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 472 | // Let's try to finish, maybe nobody is even inflating anything |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 473 | finishIfDone(result, reInflateFlags, cachedContentViews, runningInflations, callback, row); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 474 | CancellationSignal cancellationSignal = new CancellationSignal(); |
| 475 | cancellationSignal.setOnCancelListener( |
| 476 | () -> runningInflations.values().forEach(CancellationSignal::cancel)); |
| 477 | return cancellationSignal; |
| 478 | } |
| 479 | |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 480 | @VisibleForTesting |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 481 | static void applyRemoteView( |
| 482 | boolean inflateSynchronously, |
| 483 | final InflationProgress result, |
| 484 | final @InflationFlag int reInflateFlags, |
| 485 | @InflationFlag int inflationId, |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 486 | final ArrayMap<Integer, RemoteViews> cachedContentViews, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 487 | final ExpandableNotificationRow row, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 488 | boolean isNewView, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 489 | RemoteViews.OnClickHandler remoteViewClickHandler, |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 490 | @Nullable final InflationCallback callback, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 491 | NotificationContentView parentLayout, |
| 492 | View existingView, |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 493 | NotificationViewWrapper existingWrapper, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 494 | final HashMap<Integer, CancellationSignal> runningInflations, |
| 495 | ApplyCallback applyCallback) { |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 496 | RemoteViews newContentView = applyCallback.getRemoteView(); |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 497 | if (inflateSynchronously) { |
Jason Monk | 6dceace | 2018-05-15 20:24:07 -0400 | [diff] [blame] | 498 | try { |
| 499 | if (isNewView) { |
| 500 | View v = newContentView.apply( |
| 501 | result.packageContext, |
| 502 | parentLayout, |
| 503 | remoteViewClickHandler); |
| 504 | v.setIsRootNamespace(true); |
| 505 | applyCallback.setResultView(v); |
| 506 | } else { |
| 507 | newContentView.reapply( |
| 508 | result.packageContext, |
| 509 | existingView, |
| 510 | remoteViewClickHandler); |
| 511 | existingWrapper.onReinflated(); |
| 512 | } |
| 513 | } catch (Exception e) { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 514 | handleInflationError(runningInflations, e, row.getStatusBarNotification(), callback); |
Jason Monk | 6dceace | 2018-05-15 20:24:07 -0400 | [diff] [blame] | 515 | // Add a running inflation to make sure we don't trigger callbacks. |
| 516 | // Safe to do because only happens in tests. |
| 517 | runningInflations.put(inflationId, new CancellationSignal()); |
| 518 | } |
| 519 | return; |
| 520 | } |
Ahan Wu | de396fa | 2018-05-08 20:42:24 +0800 | [diff] [blame] | 521 | RemoteViews.OnViewAppliedListener listener = new RemoteViews.OnViewAppliedListener() { |
| 522 | |
| 523 | @Override |
| 524 | public void onViewInflated(View v) { |
| 525 | if (v instanceof ImageMessageConsumer) { |
| 526 | ((ImageMessageConsumer) v).setImageResolver(row.getImageResolver()); |
| 527 | } |
| 528 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 529 | |
| 530 | @Override |
| 531 | public void onViewApplied(View v) { |
| 532 | if (isNewView) { |
| 533 | v.setIsRootNamespace(true); |
| 534 | applyCallback.setResultView(v); |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 535 | } else if (existingWrapper != null) { |
| 536 | existingWrapper.onReinflated(); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 537 | } |
| 538 | runningInflations.remove(inflationId); |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 539 | finishIfDone(result, reInflateFlags, cachedContentViews, runningInflations, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 540 | callback, row); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 541 | } |
| 542 | |
| 543 | @Override |
| 544 | public void onError(Exception e) { |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 545 | // Uh oh the async inflation failed. Due to some bugs (see b/38190555), this could |
| 546 | // actually also be a system issue, so let's try on the UI thread again to be safe. |
| 547 | try { |
| 548 | View newView = existingView; |
| 549 | if (isNewView) { |
| 550 | newView = newContentView.apply( |
| 551 | result.packageContext, |
| 552 | parentLayout, |
| 553 | remoteViewClickHandler); |
| 554 | } else { |
| 555 | newContentView.reapply( |
| 556 | result.packageContext, |
| 557 | existingView, |
| 558 | remoteViewClickHandler); |
| 559 | } |
| 560 | Log.wtf(TAG, "Async Inflation failed but normal inflation finished normally.", |
| 561 | e); |
| 562 | onViewApplied(newView); |
| 563 | } catch (Exception anotherException) { |
| 564 | runningInflations.remove(inflationId); |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 565 | handleInflationError(runningInflations, e, row.getStatusBarNotification(), |
| 566 | callback); |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 567 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 568 | } |
| 569 | }; |
| 570 | CancellationSignal cancellationSignal; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 571 | if (isNewView) { |
| 572 | cancellationSignal = newContentView.applyAsync( |
| 573 | result.packageContext, |
| 574 | parentLayout, |
Selim Cinek | 9c7b307 | 2019-04-12 19:03:41 -0700 | [diff] [blame] | 575 | null, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 576 | listener, |
| 577 | remoteViewClickHandler); |
| 578 | } else { |
| 579 | cancellationSignal = newContentView.reapplyAsync( |
| 580 | result.packageContext, |
| 581 | existingView, |
Selim Cinek | 9c7b307 | 2019-04-12 19:03:41 -0700 | [diff] [blame] | 582 | null, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 583 | listener, |
| 584 | remoteViewClickHandler); |
| 585 | } |
| 586 | runningInflations.put(inflationId, cancellationSignal); |
| 587 | } |
| 588 | |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 589 | private static void handleInflationError( |
| 590 | HashMap<Integer, CancellationSignal> runningInflations, Exception e, |
| 591 | StatusBarNotification notification, @Nullable InflationCallback callback) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 592 | Assert.isMainThread(); |
| 593 | runningInflations.values().forEach(CancellationSignal::cancel); |
| 594 | if (callback != null) { |
| 595 | callback.handleInflationException(notification, e); |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 596 | } |
| 597 | } |
| 598 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 599 | /** |
| 600 | * Finish the inflation of the views |
| 601 | * |
| 602 | * @return true if the inflation was finished |
| 603 | */ |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 604 | private static boolean finishIfDone(InflationProgress result, |
| 605 | @InflationFlag int reInflateFlags, ArrayMap<Integer, RemoteViews> cachedContentViews, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 606 | HashMap<Integer, CancellationSignal> runningInflations, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 607 | @Nullable InflationCallback endListener, ExpandableNotificationRow row) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 608 | Assert.isMainThread(); |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 609 | NotificationEntry entry = row.getEntry(); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 610 | NotificationContentView privateLayout = row.getPrivateLayout(); |
| 611 | NotificationContentView publicLayout = row.getPublicLayout(); |
| 612 | if (runningInflations.isEmpty()) { |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 613 | if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 614 | if (result.inflatedContentView != null) { |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 615 | // New view case |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 616 | privateLayout.setContractedChild(result.inflatedContentView); |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 617 | cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView); |
| 618 | } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_CONTRACTED) != null) { |
| 619 | // Reinflation case. Only update if it's still cached (i.e. view has not been |
| 620 | // freed while inflating). |
| 621 | cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 622 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 623 | } |
| 624 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 625 | if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 626 | if (result.inflatedExpandedView != null) { |
| 627 | privateLayout.setExpandedChild(result.inflatedExpandedView); |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 628 | cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 629 | } else if (result.newExpandedView == null) { |
| 630 | privateLayout.setExpandedChild(null); |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 631 | cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, null); |
| 632 | } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_EXPANDED) != null) { |
| 633 | cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 634 | } |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 635 | if (result.newExpandedView != null) { |
| 636 | privateLayout.setExpandedInflatedSmartReplies( |
| 637 | result.expandedInflatedSmartReplies); |
| 638 | } else { |
| 639 | privateLayout.setExpandedInflatedSmartReplies(null); |
| 640 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 641 | row.setExpandable(result.newExpandedView != null); |
| 642 | } |
| 643 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 644 | if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 645 | if (result.inflatedHeadsUpView != null) { |
| 646 | privateLayout.setHeadsUpChild(result.inflatedHeadsUpView); |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 647 | cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 648 | } else if (result.newHeadsUpView == null) { |
| 649 | privateLayout.setHeadsUpChild(null); |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 650 | cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, null); |
| 651 | } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_HEADS_UP) != null) { |
| 652 | cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 653 | } |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 654 | if (result.newHeadsUpView != null) { |
| 655 | privateLayout.setHeadsUpInflatedSmartReplies( |
| 656 | result.headsUpInflatedSmartReplies); |
| 657 | } else { |
| 658 | privateLayout.setHeadsUpInflatedSmartReplies(null); |
| 659 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 660 | } |
| 661 | |
Kevin | d5022f9 | 2018-10-08 18:30:26 -0700 | [diff] [blame] | 662 | if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 663 | if (result.inflatedPublicView != null) { |
| 664 | publicLayout.setContractedChild(result.inflatedPublicView); |
Kevin | 217ae4e | 2019-03-07 15:49:17 -0800 | [diff] [blame] | 665 | cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView); |
| 666 | } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_PUBLIC) != null) { |
| 667 | cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 668 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 669 | } |
| 670 | |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 671 | entry.headsUpStatusBarText = result.headsUpStatusBarText; |
| 672 | entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 673 | if (endListener != null) { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 674 | endListener.onAsyncInflationFinished(row.getEntry(), reInflateFlags); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 675 | } |
| 676 | return true; |
| 677 | } |
| 678 | return false; |
| 679 | } |
| 680 | |
| 681 | private static RemoteViews createExpandedView(Notification.Builder builder, |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 682 | boolean isLowPriority) { |
| 683 | RemoteViews bigContentView = builder.createBigContentView(); |
| 684 | if (bigContentView != null) { |
| 685 | return bigContentView; |
| 686 | } |
| 687 | if (isLowPriority) { |
| 688 | RemoteViews contentView = builder.createContentView(); |
| 689 | Notification.Builder.makeHeaderExpanded(contentView); |
| 690 | return contentView; |
| 691 | } |
| 692 | return null; |
| 693 | } |
| 694 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 695 | private static RemoteViews createContentView(Notification.Builder builder, |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 696 | boolean isLowPriority, boolean useLarge) { |
| 697 | if (isLowPriority) { |
| 698 | return builder.makeLowPriorityContentView(false /* useRegularSubtext */); |
| 699 | } |
| 700 | return builder.createContentView(useLarge); |
| 701 | } |
| 702 | |
Selim Cinek | fc8073c | 2017-08-16 17:50:20 -0700 | [diff] [blame] | 703 | /** |
| 704 | * @param newView The new view that will be applied |
| 705 | * @param oldView The old view that was applied to the existing view before |
| 706 | * @return {@code true} if the RemoteViews are the same and the view can be reused to reapply. |
| 707 | */ |
| 708 | @VisibleForTesting |
| 709 | static boolean canReapplyRemoteView(final RemoteViews newView, |
| 710 | final RemoteViews oldView) { |
| 711 | return (newView == null && oldView == null) || |
| 712 | (newView != null && oldView != null |
| 713 | && oldView.getPackage() != null |
| 714 | && newView.getPackage() != null |
| 715 | && newView.getPackage().equals(oldView.getPackage()) |
| 716 | && newView.getLayoutId() == oldView.getLayoutId() |
Sunny Goyal | c12d31c | 2018-11-12 16:29:18 -0800 | [diff] [blame] | 717 | && !oldView.hasFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED)); |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 718 | } |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 719 | |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 720 | public void setInflationCallback(InflationCallback callback) { |
| 721 | mCallback = callback; |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 722 | } |
| 723 | |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 724 | public interface InflationCallback { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 725 | void handleInflationException(StatusBarNotification notification, Exception e); |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 726 | |
| 727 | /** |
| 728 | * Callback for after the content views finish inflating. |
| 729 | * |
| 730 | * @param entry the entry with the content views set |
| 731 | * @param inflatedFlags the flags associated with the content views that were inflated |
| 732 | */ |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 733 | void onAsyncInflationFinished(NotificationEntry entry, @InflationFlag int inflatedFlags); |
Selim Cinek | c478f90 | 2017-02-22 20:55:44 -0800 | [diff] [blame] | 734 | } |
Selim Cinek | 1079067 | 2017-03-08 16:33:05 -0800 | [diff] [blame] | 735 | |
Lucas Dupin | f03e752 | 2018-06-25 16:21:13 -0700 | [diff] [blame] | 736 | public void clearCachesAndReInflate() { |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 737 | mCachedContentViews.clear(); |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 738 | inflateNotificationViews(); |
| 739 | } |
| 740 | |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 741 | /** |
| 742 | * Sets whether to perform inflation on the same thread as the caller. This method should only |
| 743 | * be used in tests, not in production. |
| 744 | */ |
| 745 | @VisibleForTesting |
| 746 | void setInflateSynchronously(boolean inflateSynchronously) { |
| 747 | mInflateSynchronously = inflateSynchronously; |
| 748 | } |
| 749 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 750 | public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress> |
Selim Cinek | 67ff248 | 2017-05-25 10:27:28 -0700 | [diff] [blame] | 751 | implements InflationCallback, InflationTask { |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 752 | |
| 753 | private final StatusBarNotification mSbn; |
| 754 | private final Context mContext; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 755 | private final boolean mInflateSynchronously; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 756 | private final boolean mIsLowPriority; |
| 757 | private final boolean mIsChildInGroup; |
| 758 | private final boolean mUsesIncreasedHeight; |
| 759 | private final InflationCallback mCallback; |
| 760 | private final boolean mUsesIncreasedHeadsUpHeight; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 761 | private @InflationFlag int mReInflateFlags; |
| 762 | private final ArrayMap<Integer, RemoteViews> mCachedContentViews; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 763 | private ExpandableNotificationRow mRow; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 764 | private Exception mError; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 765 | private RemoteViews.OnClickHandler mRemoteViewClickHandler; |
| 766 | private CancellationSignal mCancellationSignal; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 767 | |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 768 | private AsyncInflationTask( |
| 769 | StatusBarNotification notification, |
| 770 | boolean inflateSynchronously, |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 771 | @InflationFlag int reInflateFlags, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 772 | ArrayMap<Integer, RemoteViews> cachedContentViews, |
| 773 | ExpandableNotificationRow row, |
| 774 | boolean isLowPriority, |
| 775 | boolean isChildInGroup, |
| 776 | boolean usesIncreasedHeight, |
| 777 | boolean usesIncreasedHeadsUpHeight, |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 778 | InflationCallback callback, |
| 779 | RemoteViews.OnClickHandler remoteViewClickHandler) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 780 | mRow = row; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 781 | mSbn = notification; |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 782 | mInflateSynchronously = inflateSynchronously; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 783 | mReInflateFlags = reInflateFlags; |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 784 | mCachedContentViews = cachedContentViews; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 785 | mContext = mRow.getContext(); |
| 786 | mIsLowPriority = isLowPriority; |
| 787 | mIsChildInGroup = isChildInGroup; |
| 788 | mUsesIncreasedHeight = usesIncreasedHeight; |
| 789 | mUsesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 790 | mRemoteViewClickHandler = remoteViewClickHandler; |
| 791 | mCallback = callback; |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 792 | NotificationEntry entry = row.getEntry(); |
Selim Cinek | 67ff248 | 2017-05-25 10:27:28 -0700 | [diff] [blame] | 793 | entry.setInflationTask(this); |
| 794 | } |
| 795 | |
| 796 | @VisibleForTesting |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 797 | @InflationFlag |
Selim Cinek | 67ff248 | 2017-05-25 10:27:28 -0700 | [diff] [blame] | 798 | public int getReInflateFlags() { |
| 799 | return mReInflateFlags; |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 800 | } |
| 801 | |
| 802 | @Override |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 803 | protected InflationProgress doInBackground(Void... params) { |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 804 | try { |
| 805 | final Notification.Builder recoveredBuilder |
| 806 | = Notification.Builder.recoverBuilder(mContext, |
| 807 | mSbn.getNotification()); |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 808 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 809 | Context packageContext = mSbn.getPackageContext(mContext); |
Selim Cinek | 5fb73f8 | 2017-04-20 16:55:38 -0700 | [diff] [blame] | 810 | Notification notification = mSbn.getNotification(); |
Selim Cinek | 0847acd | 2017-04-24 19:48:29 -0700 | [diff] [blame] | 811 | if (notification.isMediaNotification()) { |
| 812 | MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext, |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 813 | packageContext); |
Selim Cinek | 5fb73f8 | 2017-04-20 16:55:38 -0700 | [diff] [blame] | 814 | processor.processNotification(notification, recoveredBuilder); |
| 815 | } |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 816 | InflationProgress inflationProgress = createRemoteViews(mReInflateFlags, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 817 | recoveredBuilder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, |
| 818 | mUsesIncreasedHeadsUpHeight, packageContext); |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 819 | return inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(), |
Gustav Sennton | 8a52dc3 | 2019-04-15 12:48:23 +0100 | [diff] [blame] | 820 | mRow.getContext(), mRow.getHeadsUpManager(), |
| 821 | mRow.getExistingSmartRepliesAndActions()); |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 822 | } catch (Exception e) { |
| 823 | mError = e; |
| 824 | return null; |
| 825 | } |
| 826 | } |
| 827 | |
| 828 | @Override |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 829 | protected void onPostExecute(InflationProgress result) { |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 830 | if (mError == null) { |
Ned Burns | 342c3a0 | 2019-02-15 18:08:39 -0500 | [diff] [blame] | 831 | mCancellationSignal = apply(mInflateSynchronously, result, mReInflateFlags, |
Selim Cinek | c3fec68 | 2019-06-06 18:11:07 -0700 | [diff] [blame] | 832 | mCachedContentViews, mRow, mRemoteViewClickHandler, this); |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 833 | } else { |
| 834 | handleError(mError); |
| 835 | } |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 836 | } |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 837 | |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 838 | private void handleError(Exception e) { |
| 839 | mRow.getEntry().onInflationTaskFinished(); |
| 840 | StatusBarNotification sbn = mRow.getStatusBarNotification(); |
| 841 | final String ident = sbn.getPackageName() + "/0x" |
| 842 | + Integer.toHexString(sbn.getId()); |
| 843 | Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e); |
| 844 | mCallback.handleInflationException(sbn, |
| 845 | new InflationException("Couldn't inflate contentViews" + e)); |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 846 | } |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 847 | |
Selim Cinek | 0f66a4c | 2017-04-28 19:26:28 -0700 | [diff] [blame] | 848 | @Override |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 849 | public void abort() { |
| 850 | cancel(true /* mayInterruptIfRunning */); |
| 851 | if (mCancellationSignal != null) { |
| 852 | mCancellationSignal.cancel(); |
| 853 | } |
| 854 | } |
| 855 | |
| 856 | @Override |
Selim Cinek | 67ff248 | 2017-05-25 10:27:28 -0700 | [diff] [blame] | 857 | public void supersedeTask(InflationTask task) { |
| 858 | if (task instanceof AsyncInflationTask) { |
| 859 | // We want to inflate all flags of the previous task as well |
| 860 | mReInflateFlags |= ((AsyncInflationTask) task).mReInflateFlags; |
| 861 | } |
| 862 | } |
| 863 | |
| 864 | @Override |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 865 | public void handleInflationException(StatusBarNotification notification, Exception e) { |
| 866 | handleError(e); |
| 867 | } |
| 868 | |
| 869 | @Override |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 870 | public void onAsyncInflationFinished(NotificationEntry entry, |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 871 | @InflationFlag int inflatedFlags) { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 872 | mRow.getEntry().onInflationTaskFinished(); |
| 873 | mRow.onNotificationUpdated(); |
Kevin | d4660b2 | 2018-09-27 10:57:35 -0700 | [diff] [blame] | 874 | mCallback.onAsyncInflationFinished(mRow.getEntry(), inflatedFlags); |
Ahan Wu | de396fa | 2018-05-08 20:42:24 +0800 | [diff] [blame] | 875 | |
| 876 | // Notify the resolver that the inflation task has finished, |
| 877 | // try to purge unnecessary cached entries. |
| 878 | mRow.getImageResolver().purgeCache(); |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 879 | } |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 880 | } |
| 881 | |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 882 | @VisibleForTesting |
| 883 | static class InflationProgress { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 884 | private RemoteViews newContentView; |
| 885 | private RemoteViews newHeadsUpView; |
| 886 | private RemoteViews newExpandedView; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 887 | private RemoteViews newPublicView; |
| 888 | |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 889 | @VisibleForTesting |
| 890 | Context packageContext; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 891 | |
| 892 | private View inflatedContentView; |
| 893 | private View inflatedHeadsUpView; |
| 894 | private View inflatedExpandedView; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 895 | private View inflatedPublicView; |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 896 | private CharSequence headsUpStatusBarText; |
| 897 | private CharSequence headsUpStatusBarTextPublic; |
Gustav Sennton | 5759f87 | 2019-02-13 17:25:26 +0000 | [diff] [blame] | 898 | |
| 899 | private InflatedSmartReplies expandedInflatedSmartReplies; |
| 900 | private InflatedSmartReplies headsUpInflatedSmartReplies; |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 901 | } |
| 902 | |
Selim Cinek | d246bed | 2017-06-19 16:58:35 -0700 | [diff] [blame] | 903 | @VisibleForTesting |
| 904 | abstract static class ApplyCallback { |
Selim Cinek | 01d3da6 | 2017-04-28 15:03:48 -0700 | [diff] [blame] | 905 | public abstract void setResultView(View v); |
| 906 | public abstract RemoteViews getRemoteView(); |
Selim Cinek | 2630dc7 | 2017-04-20 15:16:10 -0700 | [diff] [blame] | 907 | } |
Selim Cinek | 1a48bab | 2017-02-17 19:38:40 -0800 | [diff] [blame] | 908 | } |