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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 {
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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"
|
||||
@@ -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("}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user