Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a0be727 authored by Kazuki Takise's avatar Kazuki Takise
Browse files

Resolve race condition in TaskStackChangedListenerTest

This CL makes sure that the start-up process of an activity has
completed and ActivityStack#mResumedActivity is set as the activity
before removing the activity in TaskStackChangedListenerTest.
Otherwise, onTaskRemovalStarted, which is a callback expected to be
called in TaskStackChangedListenerTest is not called because of the
following logic in ActivityStack#finishActivityLocked().

if (mResumedActivity == r) {
    mService.getTaskChangeNotificationController().notifyTaskRemovalStarted(task.taskId);
}

Currently, whether mResumeActivity is set before removing the
activity is not guaranteed, which causes flakiness in some
environments such as ARC. (it's 50/50 whether it's set properly or
not. ) This CL guarantees this and make the tests pass all the time.

Bug: 110908055
Test: atest TaskStackChangedListenerTest
Change-Id: Ieb9f2ffe40de4e79ef2bf43c4036625ce0b63304
parent 5e92684e
Loading
Loading
Loading
Loading
+45 −8
Original line number Diff line number Diff line
@@ -140,10 +140,10 @@ public class TaskStackChangedListenerTest {
        assertEquals(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, params[1]);
    }

    @Test
    /**
     * Tests for onTaskCreated, onTaskMovedToFront, onTaskRemoved and onTaskRemovalStarted.
     */
    @Test
    public void testTaskChangeCallBacks() throws Exception {
        final Object[] params = new Object[2];
        final CountDownLatch taskCreatedLaunchLatch = new CountDownLatch(1);
@@ -215,16 +215,17 @@ public class TaskStackChangedListenerTest {
    /**
     * Starts the provided activity and returns the started instance.
     */
    private Activity startTestActivity(Class<?> activityClass) {
    private TestActivity startTestActivity(Class<?> activityClass) throws InterruptedException {
        final Context context = InstrumentationRegistry.getContext();
        final ActivityMonitor monitor =
                new ActivityMonitor(activityClass.getName(), null, false);
        InstrumentationRegistry.getInstrumentation().addMonitor(monitor);
        context.startActivity(new Intent(context, activityClass));
        final Activity activity = monitor.waitForActivityWithTimeout(1000);
        final TestActivity activity = (TestActivity)monitor.waitForActivityWithTimeout(1000);
        if (activity == null) {
            throw new RuntimeException("Timed out waiting for Activity");
        }
        activity.waitForResumeStateChange(true);
        return activity;
    }

@@ -242,7 +243,43 @@ public class TaskStackChangedListenerTest {
        }catch (InterruptedException e) {}
    }

    public static class ActivityA extends Activity {
    public static class TestActivity extends Activity {
        boolean mIsResumed = false;

        @Override
        protected void onPostResume() {
            super.onPostResume();
            synchronized (this) {
                mIsResumed = true;
                notifyAll();
            }
        }

        @Override
        protected void onPause() {
            super.onPause();
            synchronized (this) {
                mIsResumed = false;
                notifyAll();
            }
        }

        /**
         * If isResumed is {@code true}, sleep the thread until the activity is resumed.
         * if {@code false}, sleep the thread until the activity is paused.
         */
        public void waitForResumeStateChange(boolean isResumed) throws InterruptedException {
            synchronized (this) {
                if (mIsResumed == isResumed) {
                    return;
                }
                wait(5000);
            }
            assertTrue("The activity resume state change timed out", mIsResumed == isResumed);
        }
    }

    public static class ActivityA extends TestActivity {

        private boolean mActivityBLaunched = false;

@@ -258,7 +295,7 @@ public class TaskStackChangedListenerTest {
        }
    }

    public static class ActivityB extends Activity {
    public static class ActivityB extends TestActivity {

        @Override
        protected void onPostResume() {
@@ -271,7 +308,7 @@ public class TaskStackChangedListenerTest {
        }
    }

    public static class ActivityRequestedOrientationChange extends Activity {
    public static class ActivityRequestedOrientationChange extends TestActivity {
        @Override
        protected void onPostResume() {
            super.onPostResume();
@@ -280,7 +317,7 @@ public class TaskStackChangedListenerTest {
        }
    }

    public static class ActivityTaskDescriptionChange extends Activity {
    public static class ActivityTaskDescriptionChange extends TestActivity {
        @Override
        protected void onPostResume() {
            super.onPostResume();
@@ -289,7 +326,7 @@ public class TaskStackChangedListenerTest {
        }
    }

    public static class ActivityTaskChangeCallbacks extends Activity {
    public static class ActivityTaskChangeCallbacks extends TestActivity {
        boolean onDetachedFromWindowCalled = false;
        CountDownLatch onDetachedFromWindowCountDownLatch;