Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1516e8a authored by Steve Elliott's avatar Steve Elliott
Browse files

Remove prev SBIV parent before attaching to NIC

This fixes an edge case were the NotificationIconContainer is
re-inflated and re-bound due to a configuration change, and as a result
the SBIVs (which are re-used between the NIC instances) are still
attached to the prev container.

Flag: ACONFIG com.android.systemui.notifications_icon_container_refactor DEVELOPMENT
Fixes: 315396311
Test: manual - enable flag, change display size and text, verify no crash
Change-Id: I94c109bf0f14c3902f5c1534b9b74f4956dc1ce9
parent 8b99457c
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder

import android.graphics.Color
import android.graphics.Rect
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.ColorInt
import androidx.collection.ArrayMap
@@ -220,7 +222,7 @@ object NotificationIconContainerViewBinder {
        notifyBindingFailures: (Collection<String>) -> Unit,
        viewStore: IconViewStore,
        bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit = { _, _ -> },
    ): Unit = coroutineScope {
    ) {
        val iconSizeFlow: Flow<Int> =
            configuration.getDimensionPixelSize(
                com.android.internal.R.dimen.status_bar_icon_size_sp,
@@ -235,6 +237,21 @@ object NotificationIconContainerViewBinder {
                ->
                FrameLayout.LayoutParams(iconSize + 2 * iconHPadding, statusBarHeight)
            }
        try {
            bindIcons(view, layoutParams, notifyBindingFailures, viewStore, bindIcon)
        } finally {
            // Detach everything so that child SBIVs don't hold onto a reference to the container.
            view.detachAllIcons()
        }
    }

    private suspend fun Flow<NotificationIconsViewData>.bindIcons(
        view: NotificationIconContainer,
        layoutParams: Flow<FrameLayout.LayoutParams>,
        notifyBindingFailures: (Collection<String>) -> Unit,
        viewStore: IconViewStore,
        bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit,
    ): Unit = coroutineScope {
        val failedBindings = mutableSetOf<String>()
        val boundViewsByNotifKey = ArrayMap<String, Pair<StatusBarIconView, Job>>()
        var prevIcons = NotificationIconsViewData()
@@ -266,9 +283,17 @@ object NotificationIconContainerViewBinder {
                        continue
                    }
                    failedBindings.remove(notifKey)
                    // The view might still be transiently added if it was just removed and added
                    // again
                    view.removeTransientView(sbiv)
                    (sbiv.parent as? ViewGroup)?.run {
                        if (this !== view) {
                            Log.wtf(TAG, "StatusBarIconView($notifKey) has an unexpected parent")
                        }
                        // If the container was re-inflated and re-bound, then SBIVs might still be
                        // attached to the prior view.
                        removeView(sbiv)
                        // The view might still be transiently added if it was just removed and
                        // added again.
                        removeTransientView(sbiv)
                    }
                    view.addView(sbiv, idx)
                    boundViewsByNotifKey.remove(notifKey)?.second?.cancel()
                    boundViewsByNotifKey[notifKey] =
@@ -351,7 +376,8 @@ object NotificationIconContainerViewBinder {
        fun iconView(key: String): StatusBarIconView?
    }

    @ColorInt private val DEFAULT_AOD_ICON_COLOR = Color.WHITE
    @ColorInt private const val DEFAULT_AOD_ICON_COLOR = Color.WHITE
    private const val TAG =  "NotifIconContainerViewBinder"
}

/** [IconViewStore] for the [com.android.systemui.statusbar.NotificationShelf] */
+15 −0
Original line number Diff line number Diff line
@@ -400,6 +400,21 @@ public class NotificationIconContainer extends ViewGroup {
        }
    }

    /**
     * Removes all child {@link StatusBarIconView} instances from this container, immediately and
     * without animation. This should be called when tearing down this container so that external
     * icon views are not holding onto a reference thru {@link View#getParent()}.
     */
    public void detachAllIcons() {
        boolean animsWereEnabled = mAnimationsEnabled;
        boolean wasChangingPositions = mChangingViewPositions;
        mAnimationsEnabled = false;
        mChangingViewPositions = true;
        removeAllViews();
        mChangingViewPositions = wasChangingPositions;
        mAnimationsEnabled = animsWereEnabled;
    }

    public boolean areIconsOverflowing() {
        return mIsShowingOverflowDot;
    }