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

Commit 9ad3eaf9 authored by András Kurucz's avatar András Kurucz
Browse files

Add logs to NotificationRoundnessManager

Log the state of NotificationRoundnessManager when we are updating the
corners of a Notification to gather more info for investigating a bug.

Bug: 242861679
Test: atest NotificationRoundnessManagerTest
Change-Id: I78ef916513f46390508259828476bb1ea3b368c7
parent 7b46b29b
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -76,6 +76,14 @@ public class LogModule {
        return factory.create("NotifInterruptLog", 100);
    }

    /** Provides a logging buffer for notification rendering events. */
    @Provides
    @SysUISingleton
    @NotificationRenderLog
    public static LogBuffer provideNotificationRenderLogBuffer(LogBufferFactory factory) {
        return factory.create("NotifRenderLog", 100);
    }

    /** Provides a logging buffer for all logs for lockscreen to shade transition events. */
    @Provides
    @SysUISingleton
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2022 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.log.dagger;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.android.systemui.log.LogBuffer;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

import javax.inject.Qualifier;

/** A {@link LogBuffer} for notification rendering logging. */
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface NotificationRenderLog {
}
+72 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2022 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.logging

import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.NotificationRenderLog
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.NotificationSection
import javax.inject.Inject

/** Handles logging for the {NotificationRoundnessManager}. */
class NotificationRoundnessLogger
@Inject
constructor(@NotificationRenderLog val buffer: LogBuffer) {

    /** Called when the {NotificationRoundnessManager} updates the corners if the Notifications. */
    fun onCornersUpdated(
        view: ExpandableView?,
        isFirstInSection: Boolean,
        isLastInSection: Boolean,
        topChanged: Boolean,
        bottomChanged: Boolean
    ) {
        buffer.log(
            TAG_ROUNDNESS,
            INFO,
            {
                str1 = (view as? ExpandableNotificationRow)?.entry?.key
                bool1 = isFirstInSection
                bool2 = isLastInSection
                bool3 = topChanged
                bool4 = bottomChanged
            },
            {
                "onCornersUpdated: " +
                    "entry=$str1 isFirstInSection=$bool1 isLastInSection=$bool2 " +
                    "topChanged=$bool3 bottomChanged=$bool4"
            }
        )
    }

    /** Called when we update the {NotificationRoundnessManager} with new sections. */
    fun onSectionCornersUpdated(sections: Array<NotificationSection?>, anyChanged: Boolean) {
        buffer.log(
            TAG_ROUNDNESS,
            INFO,
            {
                int1 = sections.size
                bool1 = anyChanged
            },
            { "onSectionCornersUpdated: sections size=$int1 anyChanged=$bool1" }
        )
    }
}

private const val TAG_ROUNDNESS = "NotifRoundnessLogger"
+70 −2
Original line number Diff line number Diff line
@@ -19,12 +19,19 @@ package com.android.systemui.statusbar.notification.stack;
import android.content.res.Resources;
import android.util.MathUtils;

import androidx.annotation.NonNull;

import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationRoundnessLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;

import java.io.PrintWriter;
import java.util.HashSet;

import javax.inject.Inject;
@@ -33,12 +40,16 @@ import javax.inject.Inject;
 * A class that manages the roundness for notification views
 */
@SysUISingleton
public class NotificationRoundnessManager {
public class NotificationRoundnessManager implements Dumpable {

    private static final String TAG = "NotificationRoundnessManager";

    private final ExpandableView[] mFirstInSectionViews;
    private final ExpandableView[] mLastInSectionViews;
    private final ExpandableView[] mTmpFirstInSectionViews;
    private final ExpandableView[] mTmpLastInSectionViews;
    private final NotificationRoundnessLogger mNotifLogger;
    private final DumpManager mDumpManager;
    private boolean mExpanded;
    private HashSet<ExpandableView> mAnimatedChildren;
    private Runnable mRoundingChangedCallback;
@@ -53,12 +64,31 @@ public class NotificationRoundnessManager {

    @Inject
    NotificationRoundnessManager(
            NotificationSectionsFeatureManager sectionsFeatureManager) {
            NotificationSectionsFeatureManager sectionsFeatureManager,
            NotificationRoundnessLogger notifLogger,
            DumpManager dumpManager) {
        int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
        mFirstInSectionViews = new ExpandableView[numberOfSections];
        mLastInSectionViews = new ExpandableView[numberOfSections];
        mTmpFirstInSectionViews = new ExpandableView[numberOfSections];
        mTmpLastInSectionViews = new ExpandableView[numberOfSections];
        mNotifLogger = notifLogger;
        mDumpManager = dumpManager;

        mDumpManager.registerDumpable(TAG, this);
    }

    @Override
    public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("mFirstInSectionViews: length=" + mFirstInSectionViews.length);
        pw.println(dumpViews(mFirstInSectionViews));
        pw.println("mLastInSectionViews: length=" + mLastInSectionViews.length);
        pw.println(dumpViews(mFirstInSectionViews));
        if (mTrackedHeadsUp != null) {
            pw.println("trackedHeadsUp=" + mTrackedHeadsUp.getEntry());
        }
        pw.println("roundForPulsingViews=" + mRoundForPulsingViews);
        pw.println("isClearAllInProgress=" + mIsClearAllInProgress);
    }

    public void updateView(ExpandableView view, boolean animate) {
@@ -95,6 +125,9 @@ public class NotificationRoundnessManager {
        view.setFirstInSection(isFirstInSection);
        view.setLastInSection(isLastInSection);

        mNotifLogger.onCornersUpdated(view, isFirstInSection,
                isLastInSection, topChanged, bottomChanged);

        return (isFirstInSection || isLastInSection) && (topChanged || bottomChanged);
    }

@@ -184,6 +217,7 @@ public class NotificationRoundnessManager {
        if (isLastInSection(view) && !top) {
            return 1.0f;
        }

        if (view == mTrackedHeadsUp) {
            // If we're pushing up on a headsup the appear fraction is < 0 and it needs to still be
            // rounded.
@@ -220,6 +254,8 @@ public class NotificationRoundnessManager {
        if (anyChanged) {
            mRoundingChangedCallback.run();
        }

        mNotifLogger.onSectionCornersUpdated(sections, anyChanged);
    }

    private boolean handleRemovedOldViews(NotificationSection[] sections,
@@ -296,4 +332,36 @@ public class NotificationRoundnessManager {
    public void setShouldRoundPulsingViews(boolean shouldRoundPulsingViews) {
        mRoundForPulsingViews = shouldRoundPulsingViews;
    }

    private String dumpViews(ExpandableView[] views) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < views.length; i++) {
            if (views[i] == null) continue;

            sb.append("\t")
                    .append("[").append(i).append("] ")
                    .append("isPinned=").append(views[i].isPinned()).append(" ")
                    .append("isFirstInSection=").append(views[i].isFirstInSection()).append(" ")
                    .append("isLastInSection=").append(views[i].isLastInSection()).append(" ");

            if (views[i] instanceof ExpandableNotificationRow) {
                sb.append("entry=");
                dumpEntry(((ExpandableNotificationRow) views[i]).getEntry(), sb);
            }

            sb.append("\n");
        }
        return sb.toString();
    }

    private void dumpEntry(NotificationEntry entry, StringBuilder sb) {
        sb.append("NotificationEntry{key=").append(entry.getKey()).append(" ");

        if (entry.getSection() != null) {
            sb.append(" section=")
                    .append(entry.getSection().getLabel());
        }

        sb.append("}");
    }
}
+22 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.notification.stack;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -32,8 +34,10 @@ import androidx.test.filters.SmallTest;

import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationRoundnessLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -57,6 +61,7 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase {
    private Runnable mRoundnessCallback = mock(Runnable.class);
    private ExpandableNotificationRow mFirst;
    private ExpandableNotificationRow mSecond;
    private NotificationRoundnessLogger mLogger = mock(NotificationRoundnessLogger.class);
    private float mSmallRadiusRatio;

    @Before
@@ -66,7 +71,9 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase {
        mSmallRadiusRatio = resources.getDimension(R.dimen.notification_corner_radius_small)
                / resources.getDimension(R.dimen.notification_corner_radius);
        mRoundnessManager = new NotificationRoundnessManager(
                new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext));
                new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext),
                mLogger,
                mock(DumpManager.class));
        allowTestableLooperAsMainThread();
        NotificationTestHelper testHelper = new NotificationTestHelper(
                mContext,
@@ -337,6 +344,20 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase {
        Assert.assertTrue(mSecond.isLastInSection());
    }

    @Test
    public void testLoggingOnRoundingUpdate() {
        NotificationSection[] sections = new NotificationSection[]{
                createSection(mFirst, mSecond),
                createSection(null, null)
        };
        mRoundnessManager.updateRoundedChildren(sections);
        verify(mLogger).onSectionCornersUpdated(sections, /*anyChanged=*/ true);
        verify(mLogger, atLeast(1)).onCornersUpdated(eq(mFirst), anyBoolean(),
                anyBoolean(), anyBoolean(), anyBoolean());
        verify(mLogger, atLeast(1)).onCornersUpdated(eq(mSecond), anyBoolean(),
                anyBoolean(), anyBoolean(), anyBoolean());
    }

    private NotificationSection createSection(ExpandableNotificationRow first,
            ExpandableNotificationRow last) {
        NotificationSection section = mock(NotificationSection.class);