Merge "Fix crash when adding a notification to a group while it is animating away."
This commit is contained in:
@@ -23,8 +23,10 @@ import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -517,6 +519,36 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
|
||||
return mChangingPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before adding this view to a group, which would always throw an exception if this view
|
||||
* has a parent, so clean up the transient container and throw an exception if the parent isn't
|
||||
* a transient container. Provide as much detail in the event of a crash as possible.
|
||||
*/
|
||||
public void removeFromTransientContainerForAdditionTo(ViewGroup newParent) {
|
||||
final ViewParent parent = getParent();
|
||||
if (parent == null) {
|
||||
// If this view has no parent, the add will succeed, so do nothing.
|
||||
return;
|
||||
}
|
||||
ViewGroup transientContainer = getTransientContainer();
|
||||
if (transientContainer == null) {
|
||||
throw new IllegalStateException(
|
||||
"Can't add view " + this + " to container " + newParent + "; current parent "
|
||||
+ parent + " is not a transient container");
|
||||
}
|
||||
if (transientContainer != parent) {
|
||||
throw new IllegalStateException(
|
||||
"Expandable view " + this + " has transient container " + transientContainer
|
||||
+ " which is not the same as its parent " + parent);
|
||||
}
|
||||
if (parent != newParent) {
|
||||
Log.w(TAG, "Moving view " + this + " from transient container "
|
||||
+ transientContainer + " to parent " + newParent);
|
||||
}
|
||||
transientContainer.removeTransientView(this);
|
||||
setTransientContainer(null);
|
||||
}
|
||||
|
||||
public void setTransientContainer(ViewGroup transientContainer) {
|
||||
mTransientContainer = transientContainer;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.android.systemui.statusbar.notification.NotificationFadeAware;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
||||
import com.android.systemui.statusbar.notification.row.HybridGroupManager;
|
||||
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
|
||||
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
|
||||
@@ -272,6 +273,7 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
* @param childIndex the index to add it at, if -1 it will be added at the end
|
||||
*/
|
||||
public void addNotification(ExpandableNotificationRow row, int childIndex) {
|
||||
ensureRemovedFromTransientContainer(row);
|
||||
int newIndex = childIndex < 0 ? mAttachedChildren.size() : childIndex;
|
||||
mAttachedChildren.add(newIndex, row);
|
||||
addView(row);
|
||||
@@ -291,6 +293,16 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureRemovedFromTransientContainer(View v) {
|
||||
if (v.getParent() != null && v instanceof ExpandableView) {
|
||||
// If the child is animating away, it will still have a parent, so detach it first
|
||||
// TODO: We should really cancel the active animations here. This will
|
||||
// happen automatically when the view's intro animation starts, but
|
||||
// it's a fragile link.
|
||||
((ExpandableView) v).removeFromTransientContainerForAdditionTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNotification(ExpandableNotificationRow row) {
|
||||
int childIndex = mAttachedChildren.indexOf(row);
|
||||
mAttachedChildren.remove(row);
|
||||
|
||||
@@ -4655,18 +4655,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
}
|
||||
|
||||
private void ensureRemovedFromTransientContainer(View v) {
|
||||
if (v.getParent() == this && v instanceof ExpandableView) {
|
||||
ExpandableView expandableView = (ExpandableView) v;
|
||||
ViewGroup transientContainer = expandableView.getTransientContainer();
|
||||
// If the child is animating away, it will still have a parent, so
|
||||
// detach it first
|
||||
if (v.getParent() != null && v instanceof ExpandableView) {
|
||||
// If the child is animating away, it will still have a parent, so detach it first
|
||||
// TODO: We should really cancel the active animations here. This will
|
||||
// happen automatically when the view's intro animation starts, but
|
||||
// it's a fragile link.
|
||||
if (transientContainer != null) {
|
||||
transientContainer.removeTransientView(v);
|
||||
expandableView.setTransientContainer(null);
|
||||
}
|
||||
((ExpandableView) v).removeFromTransientContainerForAdditionTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user