Loading packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java 0 → 100644 +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 { } packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt 0 → 100644 +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" packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +70 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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); } Loading Loading @@ -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. Loading Loading @@ -220,6 +254,8 @@ public class NotificationRoundnessManager { if (anyChanged) { mRoundingChangedCallback.run(); } mNotifLogger.onSectionCornersUpdated(sections, anyChanged); } private boolean handleRemovedOldViews(NotificationSection[] sections, Loading Loading @@ -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("}"); } } packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java +22 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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, Loading Loading @@ -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); Loading Loading
packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java 0 → 100644 +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 { }
packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt 0 → 100644 +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"
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +70 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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); } Loading Loading @@ -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. Loading Loading @@ -220,6 +254,8 @@ public class NotificationRoundnessManager { if (anyChanged) { mRoundingChangedCallback.run(); } mNotifLogger.onSectionCornersUpdated(sections, anyChanged); } private boolean handleRemovedOldViews(NotificationSection[] sections, Loading Loading @@ -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("}"); } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java +22 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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, Loading Loading @@ -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); Loading