diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 391525e118662..092e86daddb88 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -179,6 +179,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) { return; } + Trace.beginSection("NotificationViewHierarchyManager.updateNotificationViews"); beginUpdate(); @@ -353,6 +354,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle mListContainer.onNotificationViewUpdateFinished(); endUpdate(); + Trace.endSection(); } /** @@ -362,6 +364,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle * {@link com.android.systemui.statusbar.notification.collection.coordinator.StackCoordinator} */ private void updateNotifStats() { + Trace.beginSection("NotificationViewHierarchyManager.updateNotifStats"); boolean hasNonClearableAlertingNotifs = false; boolean hasClearableAlertingNotifs = false; boolean hasNonClearableSilentNotifs = false; @@ -403,6 +406,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */, hasClearableSilentNotifs /* hasClearableSilentNotifs */ )); + Trace.endSection(); } /** @@ -520,7 +524,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle } private void updateRowStatesInternal() { - Trace.beginSection("NotificationViewHierarchyManager#updateRowStates"); + Trace.beginSection("NotificationViewHierarchyManager.updateRowStates"); final int N = mListContainer.getContainerChildCount(); int visibleNotifications = 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index c33160858d0fa..ad9f12ec3bc09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -24,6 +24,7 @@ import android.app.Notification; import android.app.NotificationChannel; import android.os.RemoteException; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; @@ -343,11 +344,14 @@ public class NotificationEntryManager implements private final InflationCallback mInflationCallback = new InflationCallback() { @Override public void handleInflationException(NotificationEntry entry, Exception e) { + Trace.beginSection("NotificationEntryManager.handleInflationException"); NotificationEntryManager.this.handleInflationException(entry.getSbn(), e); + Trace.endSection(); } @Override public void onAsyncInflationFinished(NotificationEntry entry) { + Trace.beginSection("NotificationEntryManager.onAsyncInflationFinished"); mPendingNotifications.remove(entry.getKey()); // If there was an async task started after the removal, we don't want to add it back to // the list, otherwise we might get leaks. @@ -369,6 +373,7 @@ public class NotificationEntryManager implements } } } + Trace.endSection(); } }; @@ -463,6 +468,7 @@ public class NotificationEntryManager implements boolean forceRemove, DismissedByUserStats dismissedByUserStats, int reason) { + Trace.beginSection("NotificationEntryManager.removeNotificationInternal"); final NotificationEntry entry = getActiveNotificationUnfiltered(key); @@ -470,6 +476,7 @@ public class NotificationEntryManager implements if (interceptor.onNotificationRemoveRequested(key, entry, reason)) { // Remove intercepted; log and skip mLogger.logRemovalIntercepted(key); + Trace.endSection(); return; } } @@ -557,6 +564,7 @@ public class NotificationEntryManager implements mLeakDetector.trackGarbage(entry); } } + Trace.endSection(); } private void sendNotificationRemovalToServer( @@ -620,6 +628,7 @@ public class NotificationEntryManager implements private void addNotificationInternal( StatusBarNotification notification, RankingMap rankingMap) throws InflationException { + Trace.beginSection("NotificationEntryManager.addNotificationInternal"); String key = notification.getKey(); if (DEBUG) { Log.d(TAG, "addNotification key=" + key); @@ -667,6 +676,7 @@ public class NotificationEntryManager implements for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onRankingApplied(); } + Trace.endSection(); } public void addNotification(StatusBarNotification notification, RankingMap ranking) { @@ -679,12 +689,14 @@ public class NotificationEntryManager implements private void updateNotificationInternal(StatusBarNotification notification, RankingMap ranking) throws InflationException { + Trace.beginSection("NotificationEntryManager.updateNotificationInternal"); if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")"); final String key = notification.getKey(); abortExistingInflation(key, "updateNotification"); final NotificationEntry entry = getActiveNotificationUnfiltered(key); if (entry == null) { + Trace.endSection(); return; } @@ -721,6 +733,7 @@ public class NotificationEntryManager implements for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onRankingApplied(); } + Trace.endSection(); } public void updateNotification(StatusBarNotification notification, RankingMap ranking) { @@ -740,14 +753,17 @@ public class NotificationEntryManager implements mLogger.logUseWhileNewPipelineActive("updateNotifications", reason); return; } + Trace.beginSection("NotificationEntryManager.updateNotifications"); reapplyFilterAndSort(reason); if (mPresenter != null) { mPresenter.updateNotificationViews(reason); } mNotifLiveDataStore.setActiveNotifList(getVisibleNotifications()); + Trace.endSection(); } public void updateNotificationRanking(RankingMap rankingMap) { + Trace.beginSection("NotificationEntryManager.updateNotificationRanking"); List entries = new ArrayList<>(); entries.addAll(getVisibleNotifications()); entries.addAll(mPendingNotifications.values()); @@ -788,6 +804,7 @@ public class NotificationEntryManager implements for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onRankingApplied(); } + Trace.endSection(); } void notifyChannelModified( @@ -887,6 +904,7 @@ public class NotificationEntryManager implements /** @return list of active notifications filtered for the current user */ public List getActiveNotificationsForCurrentUser() { + Trace.beginSection("NotificationEntryManager.getActiveNotificationsForCurrentUser"); Assert.isMainThread(); ArrayList filtered = new ArrayList<>(); @@ -898,7 +916,7 @@ public class NotificationEntryManager implements } filtered.add(entry); } - + Trace.endSection(); return filtered; } @@ -908,10 +926,12 @@ public class NotificationEntryManager implements * @param reason the reason for calling this method, which will be logged */ public void updateRanking(RankingMap rankingMap, String reason) { + Trace.beginSection("NotificationEntryManager.updateRanking"); updateRankingAndSort(rankingMap, reason); for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onRankingApplied(); } + Trace.endSection(); } /** Resorts / filters the current notification set with the current RankingMap */ @@ -920,7 +940,9 @@ public class NotificationEntryManager implements mLogger.logUseWhileNewPipelineActive("reapplyFilterAndSort", reason); return; } + Trace.beginSection("NotificationEntryManager.reapplyFilterAndSort"); updateRankingAndSort(mRanker.getRankingMap(), reason); + Trace.endSection(); } /** Calls to NotificationRankingManager and updates mSortedAndFiltered */ @@ -929,9 +951,11 @@ public class NotificationEntryManager implements mLogger.logUseWhileNewPipelineActive("updateRankingAndSort", reason); return; } + Trace.beginSection("NotificationEntryManager.updateRankingAndSort"); mSortedAndFiltered.clear(); mSortedAndFiltered.addAll(mRanker.updateRanking( rankingMap, mActiveNotifications.values(), reason)); + Trace.endSection(); } /** dump the current active notification list. Called from StatusBar */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index 74c97fdbddca5..31d9f09d15696 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -426,14 +426,18 @@ public class ShadeListBuilder implements Dumpable { } Trace.endSection(); + Trace.beginSection("ShadeListBuilder.logEndBuildList"); // Step 9: We're done! mLogger.logEndBuildList( mIterationCount, mReadOnlyNotifList.size(), countChildren(mReadOnlyNotifList)); if (mAlwaysLogList || mIterationCount % 10 == 0) { + Trace.beginSection("ShadeListBuilder.logFinalList"); mLogger.logFinalList(mNotifList); + Trace.endSection(); } + Trace.endSection(); mPipelineState.setState(STATE_IDLE); mIterationCount++; Trace.endSection(); @@ -996,16 +1000,20 @@ public class ShadeListBuilder implements Dumpable { } private void freeEmptyGroups() { + Trace.beginSection("ShadeListBuilder.freeEmptyGroups"); mGroups.values().removeIf(ge -> ge.getSummary() == null && ge.getChildren().isEmpty()); + Trace.endSection(); } private void logChanges() { + Trace.beginSection("ShadeListBuilder.logChanges"); for (NotificationEntry entry : mAllEntries) { logAttachStateChanges(entry); } for (GroupEntry group : mGroups.values()) { logAttachStateChanges(group); } + Trace.endSection(); } private void logAttachStateChanges(ListEntry entry) { @@ -1083,6 +1091,7 @@ public class ShadeListBuilder implements Dumpable { } private void cleanupPluggables() { + Trace.beginSection("ShadeListBuilder.cleanupPluggables"); callOnCleanup(mNotifPreGroupFilters); callOnCleanup(mNotifPromoters); callOnCleanup(mNotifFinalizeFilters); @@ -1093,6 +1102,7 @@ public class ShadeListBuilder implements Dumpable { } callOnCleanup(List.of(getStabilityManager())); + Trace.endSection(); } private void callOnCleanup(List> pluggables) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt index c6a8a69cfb0db..1c96e8ceb27f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt @@ -23,6 +23,7 @@ import com.android.systemui.statusbar.notification.collection.render.NotifStackC import com.android.systemui.statusbar.notification.collection.render.NotifStats import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT import com.android.systemui.statusbar.phone.NotificationIconAreaController +import com.android.systemui.util.traceSection import javax.inject.Inject /** @@ -38,10 +39,11 @@ class StackCoordinator @Inject internal constructor( pipeline.addOnAfterRenderListListener(::onAfterRenderList) } - fun onAfterRenderList(entries: List, controller: NotifStackController) { - controller.setNotifStats(calculateNotifStats(entries)) - notificationIconAreaController.updateNotificationIcons(entries) - } + fun onAfterRenderList(entries: List, controller: NotifStackController) = + traceSection("StackCoordinator.onAfterRenderList") { + controller.setNotifStats(calculateNotifStats(entries)) + notificationIconAreaController.updateNotificationIcons(entries) + } private fun calculateNotifStats(entries: List): NotifStats { var hasNonClearableAlertingNotifs = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index b02dc0cffdb9a..54e26c34522d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -39,6 +39,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.children import com.android.systemui.util.foldToSparseArray import com.android.systemui.util.takeUntil +import com.android.systemui.util.traceSection import javax.inject.Inject /** @@ -157,7 +158,9 @@ class NotificationSectionsManager @Inject internal constructor( } } } - private fun logShadeContents() = parent.children.forEachIndexed(::logShadeChild) + private fun logShadeContents() = traceSection("NotifSectionsManager.logShadeContents") { + parent.children.forEachIndexed(::logShadeChild) + } private val isUsingMultipleSections: Boolean get() = sectionsFeatureManager.getNumberOfBuckets() > 1 @@ -221,10 +224,10 @@ class NotificationSectionsManager @Inject internal constructor( * Should be called whenever notifs are added, removed, or updated. Updates section boundary * bookkeeping and adds/moves/removes section headers if appropriate. */ - fun updateSectionBoundaries(reason: String) { + fun updateSectionBoundaries(reason: String) = traceSection("NotifSectionsManager.update") { notifPipelineFlags.checkLegacyPipelineEnabled() if (!isUsingMultipleSections) { - return + return@traceSection } logger.logStartSectionUpdate(reason) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index dd72615768b02..25b8a65456385 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -43,7 +43,6 @@ import android.graphics.Path; import android.graphics.PointF; import android.graphics.Rect; import android.os.Bundle; -import android.os.UserHandle; import android.provider.Settings; import android.util.AttributeSet; import android.util.IndentingPrintWriter; @@ -696,8 +695,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable && mQsExpansionFraction != 1 && !mScreenOffAnimationController.shouldHideNotificationsFooter() && !mIsRemoteInputActive; - boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1; + boolean showHistory = mController.isHistoryEnabled(); updateFooterView(showFooterView, showDismissView, showHistory); } @@ -5243,11 +5241,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable R.layout.status_bar_no_notifications, this, false); view.setText(R.string.empty_shade_text); view.setOnClickListener(v -> { - final boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1; - Intent intent = showHistory ? new Intent( - Settings.ACTION_NOTIFICATION_HISTORY) : new Intent( - Settings.ACTION_NOTIFICATION_SETTINGS); + final boolean showHistory = mController.isHistoryEnabled(); + Intent intent = showHistory + ? new Intent(Settings.ACTION_NOTIFICATION_HISTORY) + : new Intent(Settings.ACTION_NOTIFICATION_SETTINGS); mStatusBar.startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP); }); setEmptyShadeView(view); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 334128a2b4ca1..a2929f01f715c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -35,6 +35,8 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.PointF; +import android.os.Trace; +import android.os.UserHandle; import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; @@ -180,7 +182,6 @@ public class NotificationStackScrollLayoutController { private final NotificationLockscreenUserManager mLockscreenUserManager; // TODO: StatusBar should be encapsulated behind a Controller private final StatusBar mStatusBar; - private final NotificationGroupManagerLegacy mLegacyGroupManager; private final SectionHeaderController mSilentHeaderController; private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; private final InteractionJankMonitor mJankMonitor; @@ -191,6 +192,7 @@ public class NotificationStackScrollLayoutController { private boolean mFadeNotificationsOnDismiss; private NotificationSwipeHelper mSwipeHelper; private boolean mShowEmptyShadeView; + @Nullable private Boolean mHistoryEnabled; private int mBarState; private HeadsUpAppearanceController mHeadsUpAppearanceController; @@ -340,6 +342,8 @@ public class NotificationStackScrollLayoutController { @Override public void onUserChanged(int userId) { mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode()); + mHistoryEnabled = null; + updateFooter(); } }; @@ -699,8 +703,6 @@ public class NotificationStackScrollLayoutController { } }); mNotifPipelineFlags = notifPipelineFlags; - mLegacyGroupManager = mNotifPipelineFlags.isNewPipelineEnabled() - ? null : legacyGroupManager; mSilentHeaderController = silentHeaderController; mNotifPipeline = notifPipeline; mNotifCollection = notifCollection; @@ -802,6 +804,7 @@ public class NotificationStackScrollLayoutController { (key, newValue) -> { switch (key) { case Settings.Secure.NOTIFICATION_HISTORY_ENABLED: + mHistoryEnabled = null; // invalidate updateFooter(); break; case HIGH_PRIORITY: @@ -1009,6 +1012,20 @@ public class NotificationStackScrollLayoutController { return mNotifStats.getNumActiveNotifs(); } + public boolean isHistoryEnabled() { + Boolean historyEnabled = mHistoryEnabled; + if (historyEnabled == null) { + if (mView == null || mView.getContext() == null) { + Log.wtf(TAG, "isHistoryEnabled failed to initialize its value"); + return false; + } + mHistoryEnabled = historyEnabled = + Settings.Secure.getIntForUser(mView.getContext().getContentResolver(), + Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1; + } + return historyEnabled; + } + public int getIntrinsicContentHeight() { return mView.getIntrinsicContentHeight(); } @@ -1199,6 +1216,7 @@ public class NotificationStackScrollLayoutController { * are true. */ public void updateShowEmptyShadeView() { + Trace.beginSection("NSSLC.updateShowEmptyShadeView"); mShowEmptyShadeView = mBarState != KEYGUARD && (!mView.isQsExpanded() || mView.isUsingSplitNotificationShade()) && getVisibleNotificationCount() == 0; @@ -1206,6 +1224,7 @@ public class NotificationStackScrollLayoutController { mView.updateEmptyShadeView( mShowEmptyShadeView, mZenModeController.areNotificationsHiddenInShade()); + Trace.endSection(); } public boolean areNotificationsHiddenInShade() { @@ -1323,11 +1342,15 @@ public class NotificationStackScrollLayoutController { if (mNotifPipelineFlags.isNewPipelineEnabled()) { return; } + Trace.beginSection("NSSLC.updateSectionBoundaries"); mView.updateSectionBoundaries(reason); + Trace.endSection(); } public void updateFooter() { + Trace.beginSection("NSSLC.updateFooter"); mView.updateFooter(); + Trace.endSection(); } public void onUpdateRowStates() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index bdcbbbc99ea34..4f731ed5f72ce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.notification.stack; -import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED; import static android.view.View.GONE; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; @@ -41,8 +40,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.os.UserHandle; -import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.MathUtils; @@ -112,10 +109,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { public void setUp() throws Exception { allowTestableLooperAsMainThread(); - Settings.Secure.putIntForUser(mContext.getContentResolver(), NOTIFICATION_HISTORY_ENABLED, - 1, UserHandle.USER_CURRENT); - - // Interact with real instance of AmbientState. mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController); @@ -150,6 +143,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setShelfController(notificationShelfController); mStackScroller.setStatusBar(mBar); mStackScroller.setEmptyShadeView(mEmptyShadeView); + when(mStackScrollLayoutController.isHistoryEnabled()).thenReturn(true); when(mStackScrollLayoutController.getNoticationRoundessManager()) .thenReturn(mNotificationRoundnessManager); mStackScroller.setController(mStackScrollLayoutController); @@ -403,6 +397,22 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { verify(mStackScroller).updateFooterView(true, true, true); } + @Test + public void testUpdateFooter_withoutHistory() { + setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); + + when(mStackScrollLayoutController.isHistoryEnabled()).thenReturn(false); + when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1); + when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL))) + .thenReturn(true); + + FooterView view = mock(FooterView.class); + mStackScroller.setFooterView(view); + mStackScroller.updateFooter(); + verify(mStackScroller).updateFooterView(true, true, false); + } + @Test public void testUpdateFooter_oneClearableNotification_beforeUserSetup() { setBarStateForTest(StatusBarState.SHADE);