Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +1 −1 Original line number Diff line number Diff line Loading @@ -1398,7 +1398,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { throw exception; } Log.e(TAG, "Allowing " + mConsecutiveReentrantRebuilds Log.wtf(TAG, "Allowing " + mConsecutiveReentrantRebuilds + " consecutive reentrant notification pipeline rebuild(s).", exception); mChoreographer.schedule(); } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +109 −28 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpTree; import static com.android.systemui.statusbar.notification.collection.ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -45,6 +46,7 @@ import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.ArrayMap; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading Loading @@ -125,6 +127,10 @@ public class ShadeListBuilderTest extends SysuiTestCase { private Map<String, Integer> mNextIdMap = new ArrayMap<>(); private int mNextRank = 0; private Log.TerribleFailureHandler mOldWtfHandler = null; private Log.TerribleFailure mLastWtf = null; private int mWtfCount = 0; @Before public void setUp() { MockitoAnnotations.initMocks(this); Loading Loading @@ -1748,14 +1754,17 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPreGroupFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the filter is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } @Test(expected = IllegalStateException.class) Loading @@ -1767,18 +1776,24 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPreGroupFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the filter is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); try { runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); } finally { expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } // THEN an exception IS thrown. } @Test public void testNonConsecutiveOutOfOrderInvalidationDontThrowAfterTooManyRuns() { public void testNonConsecutiveOutOfOrderInvalidationsDontThrowAfterTooManyRuns() { // GIVEN a PreGroupNotifFilter that gets invalidated during the grouping stage, NotifFilter filter = new PackageFilter(PACKAGE_1); CountingInvalidator invalidator = new CountingInvalidator(filter); Loading @@ -1786,17 +1801,22 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPreGroupFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); // WHEN we try to run the pipeline and the filter is invalidated at least // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, interceptWtfs(); // WHEN we try to run the pipeline and the filter is invalidated // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, the pipeline runs for a non-reentrant reason, // and then the filter is invalidated MAX_CONSECUTIVE_REENTRANT_REBUILDS times again, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); // Note: dispatchBuild itself triggers a non-reentrant pipeline run. dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown, but WTFs ARE logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS * 2); } @Test Loading @@ -1808,14 +1828,18 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPromoter(promoter); mListBuilder.addOnBeforeSortListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the promoter is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_1); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); // THEN an exception is NOT thrown. } @Test(expected = IllegalStateException.class) Loading @@ -1827,12 +1851,18 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPromoter(promoter); mListBuilder.addOnBeforeSortListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the promoter is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_1); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); try { runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); } finally { expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } // THEN an exception IS thrown. } Loading @@ -1846,14 +1876,17 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.setComparators(singletonList(comparator)); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the comparator is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } @Test(expected = IllegalStateException.class) Loading @@ -1865,12 +1898,14 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.setComparators(singletonList(comparator)); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the comparator is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception IS thrown. } Loading @@ -1884,14 +1919,17 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addFinalizeFilter(filter); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the PreRenderFilter is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } @Test(expected = IllegalStateException.class) Loading @@ -1903,16 +1941,59 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addFinalizeFilter(filter); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the PreRenderFilter is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); try { runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); } finally { expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } // THEN an exception IS thrown. } private void interceptWtfs() { assertNull(mOldWtfHandler); mLastWtf = null; mWtfCount = 0; mOldWtfHandler = Log.setWtfHandler((tag, e, system) -> { Log.e("ShadeListBuilderTest", "Observed WTF: " + e); mLastWtf = e; mWtfCount++; }); } private void expectNoWtfs() { assertNull(expectWtfs(0)); } private Log.TerribleFailure expectWtf() { return expectWtfs(1); } private Log.TerribleFailure expectWtfs(int expectedWtfCount) { assertNotNull(mOldWtfHandler); Log.setWtfHandler(mOldWtfHandler); mOldWtfHandler = null; Log.TerribleFailure wtf = mLastWtf; int wtfCount = mWtfCount; mLastWtf = null; mWtfCount = 0; assertEquals(expectedWtfCount, wtfCount); return wtf; } @Test public void testStableOrdering() { mStabilityManager.setAllowEntryReordering(false); Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +1 −1 Original line number Diff line number Diff line Loading @@ -1398,7 +1398,7 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { throw exception; } Log.e(TAG, "Allowing " + mConsecutiveReentrantRebuilds Log.wtf(TAG, "Allowing " + mConsecutiveReentrantRebuilds + " consecutive reentrant notification pipeline rebuild(s).", exception); mChoreographer.schedule(); } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +109 −28 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpTree; import static com.android.systemui.statusbar.notification.collection.ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -45,6 +46,7 @@ import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.ArrayMap; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading Loading @@ -125,6 +127,10 @@ public class ShadeListBuilderTest extends SysuiTestCase { private Map<String, Integer> mNextIdMap = new ArrayMap<>(); private int mNextRank = 0; private Log.TerribleFailureHandler mOldWtfHandler = null; private Log.TerribleFailure mLastWtf = null; private int mWtfCount = 0; @Before public void setUp() { MockitoAnnotations.initMocks(this); Loading Loading @@ -1748,14 +1754,17 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPreGroupFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the filter is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } @Test(expected = IllegalStateException.class) Loading @@ -1767,18 +1776,24 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPreGroupFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the filter is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); try { runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); } finally { expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } // THEN an exception IS thrown. } @Test public void testNonConsecutiveOutOfOrderInvalidationDontThrowAfterTooManyRuns() { public void testNonConsecutiveOutOfOrderInvalidationsDontThrowAfterTooManyRuns() { // GIVEN a PreGroupNotifFilter that gets invalidated during the grouping stage, NotifFilter filter = new PackageFilter(PACKAGE_1); CountingInvalidator invalidator = new CountingInvalidator(filter); Loading @@ -1786,17 +1801,22 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPreGroupFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); // WHEN we try to run the pipeline and the filter is invalidated at least // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, interceptWtfs(); // WHEN we try to run the pipeline and the filter is invalidated // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, the pipeline runs for a non-reentrant reason, // and then the filter is invalidated MAX_CONSECUTIVE_REENTRANT_REBUILDS times again, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); // Note: dispatchBuild itself triggers a non-reentrant pipeline run. dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown, but WTFs ARE logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS * 2); } @Test Loading @@ -1808,14 +1828,18 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPromoter(promoter); mListBuilder.addOnBeforeSortListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the promoter is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_1); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); // THEN an exception is NOT thrown. } @Test(expected = IllegalStateException.class) Loading @@ -1827,12 +1851,18 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addPromoter(promoter); mListBuilder.addOnBeforeSortListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the promoter is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_1); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); try { runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); } finally { expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } // THEN an exception IS thrown. } Loading @@ -1846,14 +1876,17 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.setComparators(singletonList(comparator)); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the comparator is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } @Test(expected = IllegalStateException.class) Loading @@ -1865,12 +1898,14 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.setComparators(singletonList(comparator)); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the comparator is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception IS thrown. } Loading @@ -1884,14 +1919,17 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addFinalizeFilter(filter); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the PreRenderFilter is invalidated exactly // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); // THEN an exception is NOT thrown. // THEN an exception is NOT thrown directly, but a WTF IS logged. expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } @Test(expected = IllegalStateException.class) Loading @@ -1903,16 +1941,59 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addFinalizeFilter(filter); mListBuilder.addOnBeforeRenderListListener(listener); interceptWtfs(); // WHEN we try to run the pipeline and the PreRenderFilter is invalidated more than // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, addNotif(0, PACKAGE_2); invalidator.setInvalidationCount(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1); dispatchBuild(); runWhileScheduledUpTo(ShadeListBuilder.MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); try { runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2); } finally { expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS); } // THEN an exception IS thrown. } private void interceptWtfs() { assertNull(mOldWtfHandler); mLastWtf = null; mWtfCount = 0; mOldWtfHandler = Log.setWtfHandler((tag, e, system) -> { Log.e("ShadeListBuilderTest", "Observed WTF: " + e); mLastWtf = e; mWtfCount++; }); } private void expectNoWtfs() { assertNull(expectWtfs(0)); } private Log.TerribleFailure expectWtf() { return expectWtfs(1); } private Log.TerribleFailure expectWtfs(int expectedWtfCount) { assertNotNull(mOldWtfHandler); Log.setWtfHandler(mOldWtfHandler); mOldWtfHandler = null; Log.TerribleFailure wtf = mLastWtf; int wtfCount = mWtfCount; mLastWtf = null; mWtfCount = 0; assertEquals(expectedWtfCount, wtfCount); return wtf; } @Test public void testStableOrdering() { mStabilityManager.setAllowEntryReordering(false); Loading