Merge "Plugging in a new ViewHierarchyManager to the new pipeline" into rvc-dev

This commit is contained in:
Evan Laird
2020-03-17 17:17:48 +00:00
committed by Android (Google) Code Review
18 changed files with 477 additions and 103 deletions

View File

@@ -45,7 +45,6 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private final Handler mHandler;
private NotificationPresenter mPresenter;
private boolean mPanelExpanded;
private boolean mScreenOn;
private boolean mReorderingAllowed;
@@ -80,7 +79,6 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
}
public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
}
/**

View File

@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
@@ -51,6 +52,7 @@ public class GroupEntry extends ListEntry {
return mSummary;
}
@NonNull
public List<NotificationEntry> getChildren() {
return mUnmodifiableChildren;
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 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.collection
import android.view.textclassifier.Log
import com.android.systemui.statusbar.notification.stack.NotificationListItem
import java.lang.IllegalStateException
import javax.inject.Inject
import javax.inject.Singleton
/**
* The ViewBarn is just a map from [ListEntry] to an instance of [NotificationListItem] which is
* usually just an [ExpandableNotificationRow]
*/
@Singleton
class NotifViewBarn @Inject constructor() {
private val DEBUG = false
private val rowMap = mutableMapOf<String, NotificationListItem>()
fun requireView(forEntry: ListEntry): NotificationListItem {
if (DEBUG) {
Log.d(TAG, "requireView: $forEntry.key")
}
val li = rowMap[forEntry.key]
if (li == null) {
throw IllegalStateException("No view has been registered for entry: $forEntry")
}
return li
}
fun registerViewForEntry(entry: ListEntry, view: NotificationListItem) {
if (DEBUG) {
Log.d(TAG, "registerViewForEntry: $entry.key")
}
rowMap[entry.key] = view
}
fun removeViewForEntry(entry: ListEntry) {
if (DEBUG) {
Log.d(TAG, "removeViewForEntry: $entry.key")
}
rowMap.remove(entry.key)
}
}
private const val TAG = "NotifViewBarn"

View File

@@ -0,0 +1,200 @@
/*
* 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.collection
import android.annotation.MainThread
import android.view.ViewGroup
import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.statusbar.notification.VisualStabilityManager
import com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY
import com.android.systemui.statusbar.notification.stack.NotificationListItem
import com.android.systemui.util.Assert
import java.io.FileDescriptor
import java.io.PrintWriter
import java.lang.IllegalStateException
import javax.inject.Inject
import javax.inject.Singleton
/**
* A consumer of a Notification tree built by [ShadeListBuilder] which will update the notification
* presenter with the minimum operations required to make the old tree match the new one
*/
@MainThread
@Singleton
class NotifViewManager @Inject constructor(
private val rowRegistry: NotifViewBarn,
private val stabilityManager: VisualStabilityManager,
private val featureFlags: FeatureFlags
) {
var currentNotifs = listOf<ListEntry>()
private lateinit var listContainer: SimpleNotificationListContainer
fun attach(listBuilder: ShadeListBuilder) {
if (featureFlags.isNewNotifPipelineRenderingEnabled) {
listBuilder.setOnRenderListListener { entries: List<ListEntry> ->
this.onNotifTreeBuilt(entries)
}
}
}
fun setViewConsumer(consumer: SimpleNotificationListContainer) {
listContainer = consumer
}
/**
* Callback for when the tree is rebuilt
*/
fun onNotifTreeBuilt(notifList: List<ListEntry>) {
Assert.isMainThread()
/*
* The assumption here is that anything from the old NotificationViewHierarchyManager that
* is responsible for filtering is done via the NotifFilter logic. This tree we get should
* be *the stuff to display* +/- redacted stuff
*/
detachRows(notifList)
attachRows(notifList)
currentNotifs = notifList
}
private fun detachRows(entries: List<ListEntry>) {
// To properly detach rows, we are looking to remove any view in the consumer that is not
// present in the incoming list.
//
// Every listItem was top-level, so it's entry's parent was ROOT_ENTRY, but now
// there are two possibilities:
//
// 1. It is not present in the entry list
// 1a. It has moved to be a child in the entry list - transfer it
// 1b. It is gone completely - remove it
// 2. It is present in the entry list - diff the children
getListItems(listContainer)
.filter {
// Ignore things that are showing the blocking helper
!it.isBlockingHelperShowing
}
.forEach { listItem ->
val noLongerTopLevel = listItem.entry.parent != ROOT_ENTRY
val becameChild = noLongerTopLevel && listItem.entry.parent != null
val idx = entries.indexOf(listItem.entry)
if (noLongerTopLevel) {
// Summaries won't become children; remove the whole group
if (listItem.isSummaryWithChildren) {
listItem.removeAllChildren()
}
if (becameChild) {
// Top-level element is becoming a child, don't generate an animation
listContainer.setChildTransferInProgress(true)
}
listContainer.removeListItem(listItem)
listContainer.setChildTransferInProgress(false)
} else if (entries[idx] is GroupEntry) {
// A top-level entry exists. If it's a group, diff the children
val groupChildren = (entries[idx] as GroupEntry).children
listItem.notificationChildren?.forEach { listChild ->
if (!groupChildren.contains(listChild.entry)) {
listItem.removeChildNotification(listChild)
// TODO: the old code only calls this if the notif is gone from
// NEM.getActiveNotificationUnfiltered(). Do we care?
listContainer.notifyGroupChildRemoved(
listChild.view, listChild.view.parent as ViewGroup)
}
}
}
}
}
/** Convenience method for getting a sequence of [NotificationListItem]s */
private fun getListItems(container: SimpleNotificationListContainer):
Sequence<NotificationListItem> {
return (0 until container.getContainerChildCount()).asSequence()
.map { container.getContainerChildAt(it) }
.filterIsInstance<NotificationListItem>()
}
private fun attachRows(entries: List<ListEntry>) {
var orderChanged = false
// To attach rows we can use _this one weird trick_: if the intended view to add does not
// have a parent, then simply add it (and its children).
entries.forEach { entry ->
val listItem = rowRegistry.requireView(entry)
if (listItem.view.parent != null) {
listContainer.addListItem(listItem)
stabilityManager.notifyViewAddition(listItem.view)
}
if (entry is GroupEntry) {
for ((idx, childEntry) in entry.children.withIndex()) {
val childListItem = rowRegistry.requireView(childEntry)
// Child hasn't been added yet. add it!
if (!listItem.notificationChildren.contains(childListItem)) {
// TODO: old code here just Log.wtf()'d here. This might wreak havoc
if (childListItem.view.parent != null) {
throw IllegalStateException("trying to add a notification child that " +
"already has a parent. class: " +
"${childListItem.view.parent?.javaClass} " +
"\n child: ${childListItem.view}"
)
}
listItem.addChildNotification(childListItem, idx)
stabilityManager.notifyViewAddition(childListItem.view)
listContainer.notifyGroupChildAdded(childListItem.view)
}
}
// finally after removing and adding has been performed we can apply the order
orderChanged = orderChanged ||
listItem.applyChildOrder(
getChildListFromParent(entry),
stabilityManager,
null /*TODO: stability callback */
)
}
}
if (orderChanged) {
listContainer.generateChildOrderChangedEvent()
}
}
private fun getChildListFromParent(parent: ListEntry): List<NotificationListItem> {
if (parent is GroupEntry) {
return parent.children.map { child -> rowRegistry.requireView(child) }
.toList()
}
return emptyList()
}
fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
}
}
private const val TAG = "NotifViewDataSource"

View File

@@ -319,7 +319,7 @@ public class ShadeListBuilder implements Dumpable {
logParentingChanges();
freeEmptyGroups();
// Step 6: Dispatch the new list, first to any listeners and then to the view layer
// Step 8: Dispatch the new list, first to any listeners and then to the view layer
if (mIterationCount % 10 == 0) {
mLogger.logFinalList(mNotifList);
}
@@ -328,7 +328,7 @@ public class ShadeListBuilder implements Dumpable {
mOnRenderListListener.onRenderList(mReadOnlyNotifList);
}
// Step 7: We're done!
// Step 9: We're done!
mLogger.logEndBuildList(mIterationCount);
mPipelineState.setState(STATE_IDLE);
mIterationCount++;
@@ -816,7 +816,7 @@ public class ShadeListBuilder implements Dumpable {
* @param entries A read-only view into the current notif list. Note that this list is
* backed by the live list and will change in response to new pipeline runs.
*/
void onRenderList(List<ListEntry> entries);
void onRenderList(@NonNull List<ListEntry> entries);
}
private static final NotifSection sDefaultSection =

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 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.collection
import android.view.View
import android.view.ViewGroup
import com.android.systemui.statusbar.notification.stack.NotificationListItem
/**
* Minimal interface of what [NotifViewManager] needs from [NotificationListContainer]
*/
interface SimpleNotificationListContainer {
/** Called to signify that a top-level element is becoming a child in the shade */
fun setChildTransferInProgress(b: Boolean)
/** Used to generate a list of [NotificationListItem] */
fun getContainerChildAt(i: Int): View
/** Similar to above */
fun getContainerChildCount(): Int
/** Remove a [NotificationListItem] from the container */
fun removeListItem(li: NotificationListItem)
/** Add a [NotificationListItem] to the container */
fun addListItem(li: NotificationListItem)
/** Allows [NotifViewManager] to notify the container about a group child removal */
fun notifyGroupChildRemoved(row: View, parent: ViewGroup)
/** Allows [NotifViewManager] to notify the container about a group child addition */
fun notifyGroupChildAdded(row: View)
/** [NotifViewManager] calls this when the order of the children changes */
fun generateChildOrderChangedEvent()
}

View File

@@ -26,6 +26,7 @@ import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
@@ -57,6 +58,7 @@ public class PreparationCoordinator implements Coordinator {
private final PreparationCoordinatorLogger mLogger;
private final NotifInflater mNotifInflater;
private final NotifInflationErrorManager mNotifErrorManager;
private final NotifViewBarn mViewBarn;
private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>();
private final IStatusBarService mStatusBarService;
@@ -65,12 +67,14 @@ public class PreparationCoordinator implements Coordinator {
PreparationCoordinatorLogger logger,
NotifInflaterImpl notifInflater,
NotifInflationErrorManager errorManager,
NotifViewBarn viewBarn,
IStatusBarService service) {
mLogger = logger;
mNotifInflater = notifInflater;
mNotifInflater.setInflationCallback(mInflationCallback);
mNotifErrorManager = errorManager;
mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
mViewBarn = viewBarn;
mStatusBarService = service;
}
@@ -109,6 +113,7 @@ public class PreparationCoordinator implements Coordinator {
@Override
public void onEntryCleanUp(NotificationEntry entry) {
mInflationStates.remove(entry);
mViewBarn.removeViewForEntry(entry);
}
};
@@ -142,6 +147,7 @@ public class PreparationCoordinator implements Coordinator {
@Override
public void onInflationFinished(NotificationEntry entry) {
mLogger.logNotifInflated(entry.getKey());
mViewBarn.registerViewForEntry(entry, entry.getRow());
mInflationStates.put(entry, STATE_INFLATED);
mNotifInflatingFilter.invalidateList();
}
@@ -151,6 +157,7 @@ public class PreparationCoordinator implements Coordinator {
new NotifInflationErrorManager.NotifInflationErrorListener() {
@Override
public void onNotifInflationError(NotificationEntry entry, Exception e) {
mViewBarn.removeViewForEntry(entry);
mInflationStates.put(entry, STATE_ERROR);
try {
final StatusBarNotification sbn = entry.getSbn();

View File

@@ -1,85 +0,0 @@
/*
* 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.collection.init;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
/**
* Temporary class that tracks the result of the list builder and dumps it to text when requested.
*
* Eventually, this will be something that hands off the result of the pipeline to the View layer.
*/
public class FakePipelineConsumer implements Dumpable {
private List<ListEntry> mEntries = Collections.emptyList();
/** Attach the consumer to the pipeline. */
public void attach(ShadeListBuilder listBuilder) {
listBuilder.setOnRenderListListener(this::onBuildComplete);
}
private void onBuildComplete(List<ListEntry> entries) {
mEntries = entries;
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println();
pw.println("Active notif tree:");
for (int i = 0; i < mEntries.size(); i++) {
ListEntry entry = mEntries.get(i);
if (entry instanceof GroupEntry) {
GroupEntry ge = (GroupEntry) entry;
pw.println(dumpGroup(ge, "", i));
pw.println(dumpEntry(ge.getSummary(), INDENT, -1));
for (int j = 0; j < ge.getChildren().size(); j++) {
pw.println(dumpEntry(ge.getChildren().get(j), INDENT, j));
}
} else {
pw.println(dumpEntry(entry.getRepresentativeEntry(), "", i));
}
}
}
private String dumpGroup(GroupEntry entry, String indent, int index) {
return String.format(
"%s[%d] %s (group)",
indent,
index,
entry.getKey());
}
private String dumpEntry(NotificationEntry entry, String indent, int index) {
return String.format(
"%s[%s] %s (channel=%s)",
indent,
index == -1 ? "*" : Integer.toString(index),
entry.getKey(),
entry.getChannel() != null ? entry.getChannel().getId() : "");
}
private static final String INDENT = " ";
}

View File

@@ -25,10 +25,12 @@ import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotifViewManager;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -50,7 +52,7 @@ public class NotifPipelineInitializer implements Dumpable {
private final DumpManager mDumpManager;
private final FeatureFlags mFeatureFlags;
private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
private final NotifViewManager mNotifViewManager;
@Inject
public NotifPipelineInitializer(
@@ -61,7 +63,8 @@ public class NotifPipelineInitializer implements Dumpable {
NotifCoordinators notifCoordinators,
NotifInflaterImpl notifInflater,
DumpManager dumpManager,
FeatureFlags featureFlags) {
FeatureFlags featureFlags,
NotifViewManager notifViewManager) {
mPipelineWrapper = pipelineWrapper;
mGroupCoalescer = groupCoalescer;
mNotifCollection = notifCollection;
@@ -70,12 +73,14 @@ public class NotifPipelineInitializer implements Dumpable {
mDumpManager = dumpManager;
mNotifInflater = notifInflater;
mFeatureFlags = featureFlags;
mNotifViewManager = notifViewManager;
}
/** Hooks the new pipeline up to NotificationManager */
public void initialize(
NotificationListener notificationService,
NotificationRowBinderImpl rowBinder) {
NotificationRowBinderImpl rowBinder,
NotificationListContainer listContainer) {
mDumpManager.registerDumpable("NotifPipeline", this);
@@ -88,7 +93,8 @@ public class NotifPipelineInitializer implements Dumpable {
mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
mFakePipelineConsumer.attach(mListBuilder);
mNotifViewManager.setViewConsumer(listContainer);
mNotifViewManager.attach(mListBuilder);
mListBuilder.attach(mNotifCollection);
mNotifCollection.attach(mGroupCoalescer);
mGroupCoalescer.attach(notificationService);
@@ -98,7 +104,7 @@ public class NotifPipelineInitializer implements Dumpable {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mFakePipelineConsumer.dump(fd, pw, args);
mNotifViewManager.dump(fd, pw, args);
mNotifPluggableCoordinators.dump(fd, pw, args);
mGroupCoalescer.dump(fd, pw, args);
}

View File

@@ -94,7 +94,10 @@ class NotificationsControllerImpl @Inject constructor(
notifBindPipelineInitializer.initialize()
if (featureFlags.isNewNotifPipelineEnabled) {
newNotifPipeline.get().initialize(notificationListener, notificationRowBinder)
newNotifPipeline.get().initialize(
notificationListener,
notificationRowBinder,
listContainer)
}
if (featureFlags.isNewNotifPipelineRenderingEnabled) {

View File

@@ -94,6 +94,7 @@ import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationListItem;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -115,7 +116,8 @@ import java.util.function.Consumer;
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
implements PluginListener<NotificationMenuRowPlugin>, SwipeableView,
NotificationListItem {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -666,6 +668,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight);
}
@NonNull
public NotificationEntry getEntry() {
return mEntry;
}
@@ -767,6 +770,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
row.setIsChildInGroup(true, this);
}
/**
* Same as {@link #addChildNotification(ExpandableNotificationRow, int)}, but takes a
* {@link NotificationListItem} instead
*
* @param childItem item
* @param childIndex index
*/
public void addChildNotification(NotificationListItem childItem, int childIndex) {
addChildNotification((ExpandableNotificationRow) childItem.getView(), childIndex);
}
public void removeChildNotification(ExpandableNotificationRow row) {
if (mChildrenContainer != null) {
mChildrenContainer.removeNotification(row);
@@ -776,6 +790,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
row.setBottomRoundness(0.0f, false /* animate */);
}
@Override
public void removeChildNotification(NotificationListItem child) {
removeChildNotification((ExpandableNotificationRow) child.getView());
}
@Override
public boolean isChildInGroup() {
return mNotificationParent != null;
@@ -879,7 +898,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* @param callback the callback to invoked in case it is not allowed
* @return whether the list order has changed
*/
public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
public boolean applyChildOrder(List<? extends NotificationListItem> childOrder,
VisualStabilityManager visualStabilityManager,
VisualStabilityManager.Callback callback) {
return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder,
@@ -1274,6 +1293,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
onChildrenCountChanged();
}
@Override
public View getView() {
return this;
}
public void setForceUnlocked(boolean forceUnlocked) {
mForceUnlocked = forceUnlocked;
if (mIsSummaryWithChildren) {

View File

@@ -412,7 +412,7 @@ public class NotificationChildrenContainer extends ViewGroup {
* @param callback
* @return whether the list order has changed
*/
public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
public boolean applyChildOrder(List<? extends NotificationListItem> childOrder,
VisualStabilityManager visualStabilityManager,
VisualStabilityManager.Callback callback) {
if (childOrder == null) {
@@ -421,7 +421,7 @@ public class NotificationChildrenContainer extends ViewGroup {
boolean result = false;
for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) {
ExpandableNotificationRow child = mChildren.get(i);
ExpandableNotificationRow desiredChild = childOrder.get(i);
ExpandableNotificationRow desiredChild = (ExpandableNotificationRow) childOrder.get(i);
if (child != desiredChild) {
if (visualStabilityManager.canReorderNotification(desiredChild)) {
mChildren.remove(desiredChild);

View File

@@ -18,12 +18,14 @@ package com.android.systemui.statusbar.notification.stack;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import android.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.SimpleNotificationListContainer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -33,7 +35,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
* notification views added and removed from it, and will manage displaying them to the user.
*/
public interface NotificationListContainer extends ExpandableView.OnHeightChangedListener,
VisibilityLocationProvider {
VisibilityLocationProvider, SimpleNotificationListContainer {
/**
* Called when a child is being transferred.
@@ -186,4 +188,10 @@ public interface NotificationListContainer extends ExpandableView.OnHeightChange
}
default void setWillExpand(boolean willExpand) {};
/**
* Remove a list item from the container
* @param v the item to remove
*/
void removeListItem(@NonNull NotificationListItem v);
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2020 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.stack;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.view.View;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.List;
/**
* A NotificationListItem is a child view of the notification list that can yield a
* NotificationEntry when asked. I.e., it's an ExpandableNotificationRow but doesn't require us
* to strictly rely on ExpandableNotificationRow as our consumed type
*/
public interface NotificationListItem {
/** @return entry for this item */
@NonNull
NotificationEntry getEntry();
/** @return true if the blocking helper is showing */
boolean isBlockingHelperShowing();
/** @return true if this list item is a summary with children */
boolean isSummaryWithChildren();
// This generic is kind of ugly - we should change this once the old VHM is gone
/** @return list of the children of this item */
List<? extends NotificationListItem> getNotificationChildren();
/** remove all children from this list item */
void removeAllChildren();
/** remove particular child */
void removeChildNotification(NotificationListItem child);
/** add an item as a child */
void addChildNotification(NotificationListItem child, int childIndex);
/** Update the order of the children with the new list */
boolean applyChildOrder(
List<? extends NotificationListItem> childOrderList,
VisualStabilityManager vsm,
@Nullable VisualStabilityManager.Callback callback);
/** return the associated view for this list item */
@NonNull
View getView();
}

View File

@@ -3322,12 +3322,22 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
onViewRemovedInternal(row, childrenContainer);
}
@Override
public void notifyGroupChildRemoved(View child, ViewGroup parent) {
notifyGroupChildRemoved((ExpandableView) child, parent);
}
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void notifyGroupChildAdded(ExpandableView row) {
onViewAddedInternal(row);
}
@Override
public void notifyGroupChildAdded(View view) {
notifyGroupChildAdded((ExpandableView) view);
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void setAnimationsEnabled(boolean animationsEnabled) {
mAnimationsEnabled = animationsEnabled;
@@ -5135,6 +5145,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
removeView(v);
}
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void removeListItem(NotificationListItem v) {
removeContainerView(v.getView());
}
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void addContainerView(View v) {
@@ -5142,6 +5158,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
addView(v);
}
@Override
public void addListItem(NotificationListItem v) {
addContainerView(v.getView());
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void runAfterAnimationFinished(Runnable runnable) {
mAnimationFinishedRunnables.add(runnable);

View File

@@ -398,8 +398,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
NotificationGroup group = mGroupMap.get(groupKey);
//TODO: see if this can become an Entry
return group == null ? null
: group.summary == null ? null
: group.summary;
: group.summary;
}
/**

View File

@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationListItem;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -284,9 +285,15 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
@Override
public void notifyGroupChildAdded(ExpandableView row) {}
@Override
public void notifyGroupChildAdded(View v) {}
@Override
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {}
@Override
public void notifyGroupChildRemoved(View v, ViewGroup childrenContainer) {}
@Override
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {}
@@ -312,12 +319,22 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
mRows.remove(v);
}
@Override
public void removeListItem(NotificationListItem li) {
removeContainerView(li.getView());
}
@Override
public void addContainerView(View v) {
mLayout.addView(v);
mRows.add(v);
}
@Override
public void addListItem(NotificationListItem li) {
addContainerView(li.getView());
}
@Override
public void setMaxDisplayedNotifications(int maxNotifications) {
if (mMakeReentrantCallDuringSetMaxDisplayedNotifications) {

View File

@@ -33,6 +33,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
@@ -86,6 +87,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mock(PreparationCoordinatorLogger.class),
mNotifInflater,
mErrorManager,
mock(NotifViewBarn.class),
mService);
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);