From 0b0791615edb53aee93aa585139828a33f423145 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Thu, 17 Mar 2022 16:36:53 -0400 Subject: [PATCH] Fix stale View tracking in ShadeViewDiffer NSSL can independently re-inflate certain Views (such as section headers) which will cause the View references tracked by ShadeViewDiffer to become stale. This results in odd behavior when SVD compares its tracked Views with the ones in NSSL. The tracking serves as an optimization, so rather than maintain the additional state across pipeline runes, we re-generate the View->Spec lookup map once per run. Fixes: 216150338 Test: 1. Have silent notifications in the shade 2. Change the device theme. 3. Dismiss all notifications 1 by 1 4. Verify Silent Header is no longer visible once no more silent notifications are present. Change-Id: I1e500e2868b6c4825dd6f7cc7e2d8cf61b831773 --- .../collection/render/ShadeViewDiffer.kt | 49 ++++++++----------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt index 386e2d31380c5..032e6784ae08c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.collection.render import android.annotation.MainThread import android.view.View -import com.android.systemui.util.kotlin.transform import com.android.systemui.util.traceSection /** @@ -41,7 +40,6 @@ class ShadeViewDiffer( ) { private val rootNode = ShadeNode(rootController) private val nodes = mutableMapOf(rootController to rootNode) - private val views = mutableMapOf() /** * Adds and removes views from the root (and its children) until their structure matches the @@ -66,26 +64,25 @@ class ShadeViewDiffer( * * For debugging purposes. */ - fun getViewLabel(view: View): String = views[view]?.label ?: view.toString() + fun getViewLabel(view: View): String = + nodes.values.firstOrNull { node -> node.view === view }?.label ?: view.toString() - private fun detachChildren( - parentNode: ShadeNode, - specMap: Map - ) { - val parentSpec = specMap[parentNode.controller] - - for (i in parentNode.getChildCount() - 1 downTo 0) { - val childView = parentNode.getChildAt(i) - views[childView]?.let { childNode -> - val childSpec = specMap[childNode.controller] - - maybeDetachChild(parentNode, parentSpec, childNode, childSpec) - - if (childNode.controller.getChildCount() > 0) { - detachChildren(childNode, specMap) + private fun detachChildren(parentNode: ShadeNode, specMap: Map) { + val views = nodes.values.asSequence().map { node -> node.view to node }.toMap() + fun detachRecursively(parentNode: ShadeNode, specMap: Map) { + val parentSpec = specMap[parentNode.controller] + for (i in parentNode.getChildCount() - 1 downTo 0) { + val childView = parentNode.getChildAt(i) + views[childView]?.let { childNode -> + val childSpec = specMap[childNode.controller] + maybeDetachChild(parentNode, parentSpec, childNode, childSpec) + if (childNode.controller.getChildCount() > 0) { + detachRecursively(childNode, specMap) + } } } } + detachRecursively(parentNode, specMap) } private fun maybeDetachChild( @@ -94,14 +91,13 @@ class ShadeViewDiffer( childNode: ShadeNode, childSpec: NodeSpec? ) { - val newParentNode = transform(childSpec?.parent) { getNode(it) } + val newParentNode = childSpec?.parent?.let { getNode(it) } if (newParentNode != parentNode) { val childCompletelyRemoved = newParentNode == null if (childCompletelyRemoved) { nodes.remove(childNode.controller) - views.remove(childNode.controller.view) } logger.logDetachingChild( @@ -115,10 +111,7 @@ class ShadeViewDiffer( } } - private fun attachChildren( - parentNode: ShadeNode, - specMap: Map - ) { + private fun attachChildren(parentNode: ShadeNode, specMap: Map) { val parentSpec = checkNotNull(specMap[parentNode.controller]) for ((index, childSpec) in parentSpec.children.withIndex()) { @@ -160,7 +153,6 @@ class ShadeViewDiffer( if (node == null) { node = ShadeNode(spec.controller) nodes[node.controller] = node - views[node.view] = node } return node } @@ -194,10 +186,9 @@ class ShadeViewDiffer( private class DuplicateNodeException(message: String) : RuntimeException(message) -private class ShadeNode( - val controller: NodeController -) { - val view = controller.view +private class ShadeNode(val controller: NodeController) { + val view: View + get() = controller.view var parent: ShadeNode? = null