Merge "Plugging in a new ViewHierarchyManager to the new pipeline" into rvc-dev
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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 =
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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 = " ";
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user