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

Commit 7b2354ec authored by Bryce Lee's avatar Bryce Lee Committed by Android (Google) Code Review
Browse files

Merge "Properly handle start results when using wait flag."

parents 7a4d3d9d 5f0e28fb
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
@@ -1133,19 +1134,31 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        }
    }

    void reportTaskToFrontNoLaunch(ActivityRecord r) {
    void reportWaitingActivityLaunchedIfNeeded(ActivityRecord r, int result) {
        if (mWaitingActivityLaunched.isEmpty()) {
            return;
        }

        if (result != START_DELIVERED_TO_TOP && result != START_TASK_TO_FRONT) {
            return;
        }

        boolean changed = false;

        for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
            WaitResult w = mWaitingActivityLaunched.remove(i);
            if (w.who == null) {
                changed = true;
                // Set result to START_TASK_TO_FRONT so that startActivityMayWait() knows that
                // the starting activity ends up moving another activity to front, and it should
                // wait for this new activity to become visible instead.
                // Do not modify other fields.
                w.result = START_TASK_TO_FRONT;
                w.result = result;

                // Unlike START_TASK_TO_FRONT, When an intent is delivered to top, there
                // will be no followup launch signals. Assign the result and launched component.
                if (result == START_DELIVERED_TO_TOP) {
                    w.who = r.realActivity;
                }
            }
        }

        if (changed) {
            mService.notifyAll();
        }
+44 −32
Original line number Diff line number Diff line
@@ -879,11 +879,11 @@ class ActivityStarter {
        }

        // We're waiting for an activity launch to finish, but that activity simply
        // brought another activity to front. Let startActivityMayWait() know about
        // this, so it waits for the new activity to become visible instead.
        if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
            mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
        }
        // brought another activity to front. We must also handle the case where the task is already
        // in the front as a result of the trampoline activity being in the same task (it will be
        // considered focused as the trampoline will be finished). Let startActivityMayWait() know
        // about this, so it waits for the new activity to become visible instead.
        mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);

        ActivityStack startedActivityStack = null;
        final ActivityStack currentStack = r.getStack();
@@ -1076,7 +1076,11 @@ class ActivityStarter {

            if (outResult != null) {
                outResult.result = res;
                if (res == ActivityManager.START_SUCCESS) {

                final ActivityRecord r = outRecord[0];

                switch(res) {
                    case START_SUCCESS: {
                        mSupervisor.mWaitingActivityLaunched.add(outResult);
                        do {
                            try {
@@ -1088,12 +1092,18 @@ class ActivityStarter {
                        if (outResult.result == START_TASK_TO_FRONT) {
                            res = START_TASK_TO_FRONT;
                        }
                        break;
                    }
                if (res == START_TASK_TO_FRONT) {
                    final ActivityRecord r = outRecord[0];

                    // ActivityRecord may represent a different activity, but it should not be in
                    // the resumed state.
                    case START_DELIVERED_TO_TOP: {
                        outResult.timeout = false;
                        outResult.who = r.realActivity;
                        outResult.totalTime = 0;
                        outResult.thisTime = 0;
                        break;
                    }
                    case START_TASK_TO_FRONT: {
                        // ActivityRecord may represent a different activity, but it should not be
                        // in the resumed state.
                        if (r.nowVisible && r.state == RESUMED) {
                            outResult.timeout = false;
                            outResult.who = r.realActivity;
@@ -1110,6 +1120,8 @@ class ActivityStarter {
                                }
                            } while (!outResult.timeout && outResult.who == null);
                        }
                        break;
                    }
                }
            }

+35 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.am;

import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -25,6 +27,8 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;

import android.app.ActivityManager;
import android.app.WaitResult;
import android.content.ComponentName;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -45,7 +49,7 @@ import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS
 * Tests for the {@link ActivityStackSupervisor} class.
 *
 * Build/Install/Run:
 *  bit FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
 *  atest FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
 */
@MediumTest
@Presubmit
@@ -146,4 +150,34 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {

        assertFalse(mSupervisor.mStoppingActivities.contains(firstActivity));
    }

    /**
     * Ensures that waiting results are notified of launches.
     */
    @Test
    public void testReportWaitingActivityLaunchedIfNeeded() throws Exception {
        final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
                .setStack(mFullscreenStack).build();

        // #notifyAll will be called on the ActivityManagerService. we must hold the object lock
        // when this happens.
        synchronized (mSupervisor.mService) {
            final WaitResult taskToFrontWait = new WaitResult();
            mSupervisor.mWaitingActivityLaunched.add(taskToFrontWait);
            mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity, START_TASK_TO_FRONT);

            assertTrue(mSupervisor.mWaitingActivityLaunched.isEmpty());
            assertEquals(taskToFrontWait.result, START_TASK_TO_FRONT);
            assertEquals(taskToFrontWait.who, null);

            final WaitResult deliverToTopWait = new WaitResult();
            mSupervisor.mWaitingActivityLaunched.add(deliverToTopWait);
            mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity,
                    START_DELIVERED_TO_TOP);

            assertTrue(mSupervisor.mWaitingActivityLaunched.isEmpty());
            assertEquals(deliverToTopWait.result, START_DELIVERED_TO_TOP);
            assertEquals(deliverToTopWait.who, firstActivity.realActivity);
        }
    }
}