diff options
| author | 2019-12-11 16:47:59 -0800 | |
|---|---|---|
| committer | 2019-12-23 11:43:53 -0800 | |
| commit | ec09309521e63f06259519ba99ad9ca89e538614 (patch) | |
| tree | 77508469526ed2de97486992a8a68573bbdaa1b9 | |
| parent | ce7451cdf34eccb0014bbc3e7a7a4cdd17145571 (diff) | |
Abstract content binding into an interface
Introduce NotificationRowContentBinder interface which adds a layer of
abstraction for the underlying binding implementation. Any implementing
class is basically responsible for taking in certain bind parameters and
binding the appropriate content views. This allows us to more easily
shift out the underlying implementation (i.e. whether its asynchronous
or not, whether we use remote views or not).
Currently, NotificationContentInflater concretely implements this by
creating and using the remote views provided in the notification and
asynchronously inflating/applying it.
Bug: 145749521
Test: atest SystemUITests
Change-Id: Ib03aafe9b4322f0625a4a2d5403423a93ea0d9dc
15 files changed, 322 insertions, 178 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java index e24a3625769c..b846aa08c33b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java @@ -28,7 +28,7 @@ import android.view.accessibility.AccessibilityEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import java.util.stream.Stream; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java index 31b7cb0fb5a0..81833a4022a9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.notification; import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import android.app.Notification; import android.service.notification.StatusBarNotification; @@ -28,7 +28,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.policy.HeadsUpManager; import javax.inject.Inject; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java index 06949208c2bb..f6b55838989c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java @@ -24,7 +24,7 @@ import androidx.annotation.NonNull; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; /** * Listener interface for changes sent by NotificationEntryManager. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 43b9fbc909dc..b8afb78119de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.service.notification.NotificationListenerService.REASON_ERROR; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; @@ -45,8 +47,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationRowBin import com.android.systemui.statusbar.notification.logging.NotifEvent; import com.android.systemui.statusbar.notification.logging.NotifLog; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -94,7 +95,7 @@ import javax.inject.Singleton; @Singleton public class NotificationEntryManager implements Dumpable, - NotificationContentInflater.InflationCallback, + InflationCallback, VisualStabilityManager.Callback { private static final String TAG = "NotificationEntryMgr"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index de16ef5a6d40..dd3a3e0b1505 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -61,8 +61,8 @@ import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; import com.android.systemui.statusbar.notification.row.NotificationGuts; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager; import java.util.ArrayList; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java index 86506a675c08..8afbc27589d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import android.annotation.Nullable; import android.content.Context; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 4c62cdfddc28..3c247df692f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -17,12 +17,12 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_CONTRACTED; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_EXPANDED; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC; import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -89,8 +89,9 @@ import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.logging.NotificationCounters; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.notification.stack.AmbientState; import com.android.systemui.statusbar.notification.stack.AnimationProperties; @@ -247,6 +248,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private InflationCallback mInflationCallback; private boolean mIsChildInGroup; private @InflationFlag int mInflationFlags = REQUIRED_INFLATION_FLAGS; + private final BindParams mBindParams = new BindParams(); // Listener will be called when receiving a long click event. // Use #setLongPressPosition to optionally assign positional data with the long press. @@ -462,8 +464,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * Inflate views based off the inflation flags set. Inflation happens asynchronously. */ public void inflateViews() { - mNotificationInflater.inflateNotificationViews(mInflationFlags, false /* forceInflate */, - mInflationCallback); + mNotificationInflater.bindContent(mEntry, this, mInflationFlags, mBindParams, + false /* forceInflate */, mInflationCallback); } /** @@ -475,8 +477,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) { // View should not be reinflated in the future clearInflationFlags(inflationFlag); - Runnable freeViewRunnable = () -> - mNotificationInflater.freeNotificationView(inflationFlag); + Runnable freeViewRunnable = + () -> mNotificationInflater.unbindContent(mEntry, this, inflationFlag); switch (inflationFlag) { case FLAG_CONTENT_VIEW_HEADS_UP: getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_HEADSUP, @@ -845,13 +847,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } mNotificationParent = isChildInGroup ? parent : null; mPrivateLayout.setIsChildInGroup(isChildInGroup); - mNotificationInflater.setIsChildInGroup(isChildInGroup); + mBindParams.isChildInGroup = isChildInGroup; if (mIsChildInGroup != isChildInGroup) { mIsChildInGroup = isChildInGroup; if (mIsLowPriority) { int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; - mNotificationInflater.inflateNotificationViews(flags, false /* forceInflate */, - mInflationCallback); + mNotificationInflater.bindContent(mEntry, this, flags, mBindParams, + false /* forceInflate */, mInflationCallback); } } resetBackgroundAlpha(); @@ -1257,8 +1259,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView l.reInflateViews(); } mEntry.getSbn().clearPackageContext(); - mNotificationInflater.inflateNotificationViews(mInflationFlags, true /* forceInflate */, - mInflationCallback); + mNotificationInflater.bindContent(mEntry, this, mInflationFlags, mBindParams, + true /* forceInflate */, mInflationCallback); } @Override @@ -1612,7 +1614,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void setIsLowPriority(boolean isLowPriority) { mIsLowPriority = isLowPriority; mPrivateLayout.setIsLowPriority(isLowPriority); - mNotificationInflater.setIsLowPriority(mIsLowPriority); + mBindParams.isLowPriority = mIsLowPriority; if (mChildrenContainer != null) { mChildrenContainer.setIsLowPriority(isLowPriority); } @@ -1624,12 +1626,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void setUseIncreasedCollapsedHeight(boolean use) { mUseIncreasedCollapsedHeight = use; - mNotificationInflater.setUsesIncreasedHeight(use); + mBindParams.usesIncreasedHeight = use; } public void setUseIncreasedHeadsUpHeight(boolean use) { mUseIncreasedHeadsUpHeight = use; - mNotificationInflater.setUsesIncreasedHeadsUpHeight(use); + mBindParams.usesIncreasedHeadsUpHeight = use; } public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) { @@ -1650,8 +1652,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mNeedsRedaction = needsRedaction; if (needsRedaction) { setInflationFlags(FLAG_CONTENT_VIEW_PUBLIC); - mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_PUBLIC, - false /* forceInflate */, mInflationCallback); + mNotificationInflater.bindContent(mEntry, this, FLAG_CONTENT_VIEW_PUBLIC, + mBindParams, false /* forceInflate */, mInflationCallback); } else { clearInflationFlags(FLAG_CONTENT_VIEW_PUBLIC); freeContentViewWhenSafe(FLAG_CONTENT_VIEW_PUBLIC); @@ -1670,7 +1672,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public ExpandableNotificationRow(Context context, AttributeSet attrs) { super(context, attrs); - mNotificationInflater = new NotificationContentInflater(this); + mNotificationInflater = new NotificationContentInflater(); mMenuRow = new NotificationMenuRow(mContext); mImageResolver = new NotificationInlineImageResolver(context, new NotificationInlineImageCache()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java index f4a030a8ca4c..172b72e9b0fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; -import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; @@ -47,112 +47,39 @@ import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAn import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.util.Assert; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.HashMap; /** - * A utility that inflates the right kind of contentView based on the state + * {@link NotificationContentInflater} binds content to a {@link ExpandableNotificationRow} by + * asynchronously building the content's {@link RemoteViews} and applying it to the row. */ -public class NotificationContentInflater { +public class NotificationContentInflater implements NotificationRowContentBinder { public static final String TAG = "NotifContentInflater"; - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, - prefix = {"FLAG_CONTENT_VIEW_"}, - value = { - FLAG_CONTENT_VIEW_CONTRACTED, - FLAG_CONTENT_VIEW_EXPANDED, - FLAG_CONTENT_VIEW_HEADS_UP, - FLAG_CONTENT_VIEW_PUBLIC, - FLAG_CONTENT_VIEW_ALL}) - public @interface InflationFlag {} - /** - * The default, contracted view. Seen when the shade is pulled down and in the lock screen - * if there is no worry about content sensitivity. - */ - public static final int FLAG_CONTENT_VIEW_CONTRACTED = 1; - - /** - * The expanded view. Seen when the user expands a notification. - */ - public static final int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1; - - /** - * The heads up view. Seen when a high priority notification peeks in from the top. - */ - public static final int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2; - - /** - * The public view. This is a version of the contracted view that hides sensitive - * information and is used on the lock screen if we determine that the notification's - * content should be hidden. - */ - public static final int FLAG_CONTENT_VIEW_PUBLIC = 1 << 3; - - public static final int FLAG_CONTENT_VIEW_ALL = ~0; - - private final ExpandableNotificationRow mRow; - private boolean mIsLowPriority; - private boolean mUsesIncreasedHeight; - private boolean mUsesIncreasedHeadsUpHeight; private RemoteViews.OnClickHandler mRemoteViewClickHandler; - private boolean mIsChildInGroup; private boolean mInflateSynchronously = false; private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>(); - public NotificationContentInflater(ExpandableNotificationRow row) { - mRow = row; - } - - public void setIsLowPriority(boolean isLowPriority) { - mIsLowPriority = isLowPriority; - } - - /** - * Set whether the notification is a child in a group - * - * @return whether the view was re-inflated - */ - public void setIsChildInGroup(boolean childInGroup) { - mIsChildInGroup = childInGroup; - } - - public void setUsesIncreasedHeight(boolean usesIncreasedHeight) { - mUsesIncreasedHeight = usesIncreasedHeight; - } - - public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) { - mUsesIncreasedHeadsUpHeight = usesIncreasedHeight; - } - - public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) { - mRemoteViewClickHandler = remoteViewClickHandler; - } - - /** - * Inflate notification content views and bind to the row - * - * @param contentToBind content views that should be inflated and bound - * @param forceInflate true to force reinflation even if views are cached - * @param callback callback after inflation is finished - */ - void inflateNotificationViews( + @Override + public void bindContent( + NotificationEntry entry, + ExpandableNotificationRow row, @InflationFlag int contentToBind, + BindParams bindParams, boolean forceInflate, @Nullable InflationCallback callback) { - if (mRow.isRemoved()) { + if (row.isRemoved()) { // We don't want to reinflate anything for removed notifications. Otherwise views might // be readded to the stack, leading to leaks. This may happen with low-priority groups // where the removal of already removed children can lead to a reinflation. return; } - StatusBarNotification sbn = mRow.getEntry().getSbn(); + StatusBarNotification sbn = row.getEntry().getSbn(); // To check if the notification has inline image and preload inline image if necessary. - mRow.getImageResolver().preloadImages(sbn.getNotification()); + row.getImageResolver().preloadImages(sbn.getNotification()); if (forceInflate) { mCachedContentViews.clear(); @@ -163,11 +90,11 @@ public class NotificationContentInflater { mInflateSynchronously, contentToBind, mCachedContentViews, - mRow, - mIsLowPriority, - mIsChildInGroup, - mUsesIncreasedHeight, - mUsesIncreasedHeadsUpHeight, + row, + bindParams.isLowPriority, + bindParams.isChildInGroup, + bindParams.usesIncreasedHeight, + bindParams.usesIncreasedHeadsUpHeight, callback, mRemoteViewClickHandler); if (mInflateSynchronously) { @@ -179,45 +106,84 @@ public class NotificationContentInflater { @VisibleForTesting InflationProgress inflateNotificationViews( + NotificationEntry entry, + ExpandableNotificationRow row, + BindParams bindParams, boolean inflateSynchronously, @InflationFlag int reInflateFlags, Notification.Builder builder, Context packageContext) { - InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority, - mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, + InflationProgress result = createRemoteViews(reInflateFlags, + builder, + bindParams.isLowPriority, + bindParams.isChildInGroup, + bindParams.usesIncreasedHeight, + bindParams.usesIncreasedHeadsUpHeight, packageContext); - result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(), - mRow.getContext(), packageContext, mRow.getHeadsUpManager(), - mRow.getExistingSmartRepliesAndActions()); + result = inflateSmartReplyViews(result, reInflateFlags, entry, + row.getContext(), packageContext, row.getHeadsUpManager(), + row.getExistingSmartRepliesAndActions()); apply( inflateSynchronously, result, reInflateFlags, mCachedContentViews, - mRow, + row, mRemoteViewClickHandler, null); return result; } + @Override + public void cancelBind( + @NonNull NotificationEntry entry, + @NonNull ExpandableNotificationRow row) { + entry.abortTask(); + } + + @Override + public void unbindContent( + @NonNull NotificationEntry entry, + @NonNull ExpandableNotificationRow row, + @InflationFlag int contentToUnbind) { + int curFlag = 1; + while (contentToUnbind != 0) { + if ((contentToUnbind & curFlag) != 0) { + freeNotificationView(row, curFlag); + } + contentToUnbind &= ~curFlag; + curFlag = curFlag << 1; + } + } + + /** + * Set click handler for notification remote views + * + * @param remoteViewClickHandler click handler for remote views + */ + public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) { + mRemoteViewClickHandler = remoteViewClickHandler; + } + /** * Frees the content view associated with the inflation flag. Will only succeed if the * view is safe to remove. * * @param inflateFlag the flag corresponding to the content view which should be freed */ - public void freeNotificationView(@InflationFlag int inflateFlag) { + private void freeNotificationView(ExpandableNotificationRow row, + @InflationFlag int inflateFlag) { switch (inflateFlag) { case FLAG_CONTENT_VIEW_HEADS_UP: - if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) { - mRow.getPrivateLayout().setHeadsUpChild(null); + if (row.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) { + row.getPrivateLayout().setHeadsUpChild(null); mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP); - mRow.getPrivateLayout().setHeadsUpInflatedSmartReplies(null); + row.getPrivateLayout().setHeadsUpInflatedSmartReplies(null); } break; case FLAG_CONTENT_VIEW_PUBLIC: - if (mRow.getPublicLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) { - mRow.getPublicLayout().setContractedChild(null); + if (row.getPublicLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) { + row.getPublicLayout().setContractedChild(null); mCachedContentViews.remove(FLAG_CONTENT_VIEW_PUBLIC); } break; @@ -637,18 +603,6 @@ public class NotificationContentInflater { && !oldView.hasFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED)); } - public interface InflationCallback { - void handleInflationException(StatusBarNotification notification, Exception e); - - /** - * Callback for after the content views finish inflating. - * - * @param entry the entry with the content views set - * @param inflatedFlags the flags associated with the content views that were inflated - */ - void onAsyncInflationFinished(NotificationEntry entry, @InflationFlag int inflatedFlags); - } - /** * Sets whether to perform inflation on the same thread as the caller. This method should only * be used in tests, not in production. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java new file mode 100644 index 000000000000..2fe54c00bb06 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2019 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.systemui.statusbar.notification.row; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.service.notification.StatusBarNotification; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Binder that takes a notifications {@link ExpandableNotificationRow} and binds the appropriate + * content to it based off the bind parameters passed to it. + */ +public interface NotificationRowContentBinder { + + /** + * Inflate notification content views and bind to the row. + * + * @param entry notification + * @param row notification row to bind views to + * @param contentToBind content views that should be inflated and bound + * @param bindParams parameters for binding content views + * @param forceInflate true to force reinflation even if views are cached + * @param callback callback after inflation is finished + */ + void bindContent( + @NonNull NotificationEntry entry, + @NonNull ExpandableNotificationRow row, + @InflationFlag int contentToBind, + BindParams bindParams, + boolean forceInflate, + @Nullable InflationCallback callback); + + /** + * Cancel any on-going bind operation. + * + * @param entry notification + * @param row notification row to cancel bind on + */ + void cancelBind( + @NonNull NotificationEntry entry, + @NonNull ExpandableNotificationRow row); + + /** + * Unbind content views from the row. + * + * @param entry notification + * @param row notification row to unbind content views from + * @param contentToUnbind content views that should be unbound + */ + void unbindContent( + @NonNull NotificationEntry entry, + @NonNull ExpandableNotificationRow row, + @InflationFlag int contentToUnbind); + + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, + prefix = {"FLAG_CONTENT_VIEW_"}, + value = { + FLAG_CONTENT_VIEW_CONTRACTED, + FLAG_CONTENT_VIEW_EXPANDED, + FLAG_CONTENT_VIEW_HEADS_UP, + FLAG_CONTENT_VIEW_PUBLIC, + FLAG_CONTENT_VIEW_ALL}) + @interface InflationFlag {} + /** + * The default, contracted view. Seen when the shade is pulled down and in the lock screen + * if there is no worry about content sensitivity. + */ + int FLAG_CONTENT_VIEW_CONTRACTED = 1; + /** + * The expanded view. Seen when the user expands a notification. + */ + int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1; + /** + * The heads up view. Seen when a high priority notification peeks in from the top. + */ + int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2; + /** + * The public view. This is a version of the contracted view that hides sensitive + * information and is used on the lock screen if we determine that the notification's + * content should be hidden. + */ + int FLAG_CONTENT_VIEW_PUBLIC = 1 << 3; + + int FLAG_CONTENT_VIEW_ALL = ~0; + + /** + * Parameters for content view binding + */ + class BindParams { + + /** + * Bind a low priority version of the content views. + */ + public boolean isLowPriority; + + /** + * Bind child version of content views. + */ + public boolean isChildInGroup; + + /** + * Use increased height when binding contracted view. + */ + public boolean usesIncreasedHeight; + + /** + * Use increased height when binding heads up views. + */ + public boolean usesIncreasedHeadsUpHeight; + } + + /** + * Callback for inflation finishing + */ + interface InflationCallback { + + /** + * Callback for when there is an inflation exception + * + * @param notification notification which failed to inflate content + * @param e exception + */ + void handleInflationException(StatusBarNotification notification, Exception e); + + /** + * Callback for after the content views finish inflating. + * + * @param entry the entry with the content views set + * @param inflatedFlags the flags associated with the content views that were inflated + */ + void onAsyncInflationFinished(NotificationEntry entry, + @InflationFlag int inflatedFlags); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java index fe09b6b1bad3..fe0739f9088c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java @@ -33,7 +33,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationContentInflater.AsyncInflationTask; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup; import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener; import com.android.systemui.statusbar.policy.HeadsUpManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 6828c322dea2..66a1d3ff756a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.policy; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import android.annotation.NonNull; import android.annotation.Nullable; @@ -33,7 +33,7 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.AlertingNotificationManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java index a5395e8ebe86..402a99d4c23d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java @@ -17,7 +17,7 @@ package com.android.systemui.statusbar; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_CONTRACTED; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 27ea818d3e96..40b0ba9bf633 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -48,7 +48,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationContentInflater; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index afd6bb4d7a24..3d79ce15bfb6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -19,9 +19,9 @@ package com.android.systemui.statusbar.notification.row; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java index b825e950b609..dc4e4980e443 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java @@ -16,9 +16,10 @@ package com.android.systemui.statusbar.notification.row; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_EXPANDED; -import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; +import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -47,8 +48,9 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.InflationTask; import com.android.systemui.statusbar.NotificationTestHelper; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback; -import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.tests.R; import org.junit.Assert; @@ -82,14 +84,17 @@ public class NotificationContentInflaterTest extends SysuiTestCase { ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency).createRow( mBuilder.build()); mRow = spy(row); - mNotificationInflater = new NotificationContentInflater(mRow); + mNotificationInflater = new NotificationContentInflater(); } @Test public void testIncreasedHeadsUpBeingUsed() { - mNotificationInflater.setUsesIncreasedHeadsUpHeight(true); + BindParams params = new BindParams(); + params.usesIncreasedHeadsUpHeight = true; Notification.Builder builder = spy(mBuilder); - mNotificationInflater.inflateNotificationViews( + mNotificationInflater.inflateNotificationViews(mRow.getEntry(), + mRow, + params, true /* inflateSynchronously */, FLAG_CONTENT_VIEW_ALL, builder, @@ -99,9 +104,12 @@ public class NotificationContentInflaterTest extends SysuiTestCase { @Test public void testIncreasedHeightBeingUsed() { - mNotificationInflater.setUsesIncreasedHeight(true); + BindParams params = new BindParams(); + params.usesIncreasedHeight = true; Notification.Builder builder = spy(mBuilder); - mNotificationInflater.inflateNotificationViews( + mNotificationInflater.inflateNotificationViews(mRow.getEntry(), + mRow, + params, true /* inflateSynchronously */, FLAG_CONTENT_VIEW_ALL, builder, @@ -111,13 +119,13 @@ public class NotificationContentInflaterTest extends SysuiTestCase { @Test public void testInflationCallsUpdated() throws Exception { - inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL); + inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow); verify(mRow).onNotificationUpdated(); } @Test public void testInflationOnlyInflatesSetFlags() throws Exception { - inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_HEADS_UP); + inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, mRow); assertNotNull(mRow.getPrivateLayout().getHeadsUpChild()); verify(mRow).onNotificationUpdated(); @@ -128,7 +136,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase { mRow.getPrivateLayout().removeAllViews(); mRow.getEntry().getSbn().getNotification().contentView = new RemoteViews(mContext.getPackageName(), R.layout.status_bar); - inflateAndWait(true /* expectingException */, mNotificationInflater, FLAG_CONTENT_VIEW_ALL); + inflateAndWait(true /* expectingException */, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, + mRow); assertTrue(mRow.getPrivateLayout().getChildCount() == 0); verify(mRow, times(0)).onNotificationUpdated(); } @@ -136,7 +145,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase { @Test public void testAsyncTaskRemoved() throws Exception { mRow.getEntry().abortTask(); - inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL); + inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow); verify(mRow).onNotificationUpdated(); } @@ -144,8 +153,13 @@ public class NotificationContentInflaterTest extends SysuiTestCase { public void testRemovedNotInflated() throws Exception { mRow.setRemoved(); mNotificationInflater.setInflateSynchronously(true); - mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, - false /* forceInflate */, null /* callback */); + mNotificationInflater.bindContent( + mRow.getEntry(), + mRow, + FLAG_CONTENT_VIEW_ALL, + new BindParams(), + false /* forceInflate */, + null /* callback */); Assert.assertNull(mRow.getEntry().getRunningTask()); } @@ -194,12 +208,22 @@ public class NotificationContentInflaterTest extends SysuiTestCase { /* Cancelling requires us to be on the UI thread otherwise we might have a race */ @Test public void testSupersedesExistingTask() { - mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, - false /* forceInflate */, null /* callback */); - - // Trigger inflation of content and expanded only. - mNotificationInflater.setIsLowPriority(true); - mNotificationInflater.setIsChildInGroup(true); + mNotificationInflater.bindContent( + mRow.getEntry(), + mRow, + FLAG_CONTENT_VIEW_ALL, + new BindParams(), + false /* forceInflate */, + null /* callback */); + + // Trigger inflation of contracted only. + mNotificationInflater.bindContent( + mRow.getEntry(), + mRow, + FLAG_CONTENT_VIEW_CONTRACTED, + new BindParams(), + false /* forceInflate */, + null /* callback */); InflationTask runningTask = mRow.getEntry().getRunningTask(); NotificationContentInflater.AsyncInflationTask asyncInflationTask = @@ -222,14 +246,16 @@ public class NotificationContentInflaterTest extends SysuiTestCase { } private static void inflateAndWait(NotificationContentInflater inflater, - @InflationFlag int contentToInflate) + @InflationFlag int contentToInflate, + ExpandableNotificationRow row) throws Exception { - inflateAndWait(false /* expectingException */, inflater, contentToInflate); + inflateAndWait(false /* expectingException */, inflater, contentToInflate, row); } private static void inflateAndWait(boolean expectingException, NotificationContentInflater inflater, - @InflationFlag int contentToInflate) throws Exception { + @InflationFlag int contentToInflate, + ExpandableNotificationRow row) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(1); final ExceptionHolder exceptionHolder = new ExceptionHolder(); inflater.setInflateSynchronously(true); @@ -253,7 +279,13 @@ public class NotificationContentInflaterTest extends SysuiTestCase { countDownLatch.countDown(); } }; - inflater.inflateNotificationViews(contentToInflate, false /* forceInflate */, callback); + inflater.bindContent( + row.getEntry(), + row, + contentToInflate, + new BindParams(), + false /* forceInflate */, + callback /* callback */); assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS)); if (exceptionHolder.mException != null) { throw exceptionHolder.mException; |