From 5ecea7cdd07b0d24178da2406519a98d80a8e2f8 Mon Sep 17 00:00:00 2001 From: Jimmy Shiu Date: Wed, 19 Apr 2023 13:49:53 +0800 Subject: [PATCH] Fixed flaky HintManagerServiceTest#testReportActualWorkDuration The flake is related to the running sequence. If Object#notify() is called before Object#wait(), the latter will block forever. Using CountDownLatch to solve the problem. CountDownLatch#await() will wait until its count reaches 0. CountDownLatch with an initial count of 1, so the code after CountDownLatch#await() will only run after CountDownLatch#countDown() has been called. Bug: 277881247 Test: atest HintManagerServiceTest Test: verify by adding sleep between countdown() and await() Change-Id: I1a2b0fbec5f48f504107e3c031bf6e9f3ff571f5 --- .../power/hint/HintManagerServiceTest.java | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java index 136507d429fc6..726a4e285d682 100644 --- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -57,6 +57,8 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.concurrent.CountDownLatch; + /** * Tests for {@link com.android.server.power.hint.HintManagerService}. * @@ -149,29 +151,28 @@ public class HintManagerServiceTest { // Set session to background and calling updateHintAllowed() would invoke pause(); service.mUidObserver.onUidStateChanged( a.mUid, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); - final Object sync = new Object(); + + // Using CountDownLatch to ensure above onUidStateChanged() job was digested. + final CountDownLatch latch = new CountDownLatch(1); FgThread.getHandler().post(() -> { - synchronized (sync) { - sync.notify(); - } + latch.countDown(); }); - synchronized (sync) { - sync.wait(); - } + latch.await(); + assumeFalse(a.updateHintAllowed()); verify(mNativeWrapperMock, times(1)).halPauseHintSession(anyLong()); // Set session to foreground and calling updateHintAllowed() would invoke resume(); service.mUidObserver.onUidStateChanged( a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); + + // Using CountDownLatch to ensure above onUidStateChanged() job was digested. + final CountDownLatch latch2 = new CountDownLatch(1); FgThread.getHandler().post(() -> { - synchronized (sync) { - sync.notify(); - } + latch2.countDown(); }); - synchronized (sync) { - sync.wait(); - } + latch2.await(); + assumeTrue(a.updateHintAllowed()); verify(mNativeWrapperMock, times(1)).halResumeHintSession(anyLong()); } @@ -237,15 +238,14 @@ public class HintManagerServiceTest { // Set session to background, then the duration would not be updated. service.mUidObserver.onUidStateChanged( a.mUid, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); - final Object sync = new Object(); + + // Using CountDownLatch to ensure above onUidStateChanged() job was digested. + final CountDownLatch latch = new CountDownLatch(1); FgThread.getHandler().post(() -> { - synchronized (sync) { - sync.notify(); - } + latch.countDown(); }); - synchronized (sync) { - sync.wait(); - } + latch.await(); + assumeFalse(a.updateHintAllowed()); a.reportActualWorkDuration(DURATIONS_THREE, TIMESTAMPS_THREE); verify(mNativeWrapperMock, never()).halReportActualWorkDuration(anyLong(), any(), any()); @@ -287,15 +287,14 @@ public class HintManagerServiceTest { service.mUidObserver.onUidStateChanged( a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0); - final Object sync = new Object(); + + // Using CountDownLatch to ensure above onUidStateChanged() job was digested. + final CountDownLatch latch = new CountDownLatch(1); FgThread.getHandler().post(() -> { - synchronized (sync) { - sync.notify(); - } + latch.countDown(); }); - synchronized (sync) { - sync.wait(); - } + latch.await(); + assertFalse(a.updateHintAllowed()); }