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

Commit 0bd8d42c authored by Bryce Lee's avatar Bryce Lee
Browse files

Pause activity when making visible from stopped state.

It is possible for an activity to become visible without gaining
focus. For example, if a paused activity in split-screen finishes
itself, the activity below will become visible. Currently this
activity will not exit the stopped state. This changelist
addresses this inconsistency by cycling the activity to paused if
it becomes visible in the stopped state.

Change-Id: I170d586793dadb0d6ff59d1ad68f2d94699f9ca6
Bug: 71582913
Test: atest ActivityRecordTests#testPausingWhenVisibleFromStopped
parent d93d206c
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -78,7 +80,8 @@ public class ClientTransaction implements Parcelable, ObjectPoolItem {
    }

    /** Get the target state lifecycle request. */
    ActivityLifecycleItem getLifecycleStateRequest() {
    @VisibleForTesting
    public ActivityLifecycleItem getLifecycleStateRequest() {
        return mLifecycleStateRequest;
    }

+12 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ import android.app.ResultInfo;
import android.app.servertransaction.MoveToDisplayItem;
import android.app.servertransaction.MultiWindowModeChangeItem;
import android.app.servertransaction.NewIntentItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.PipModeChangeItem;
import android.app.servertransaction.WindowVisibilityItem;
import android.app.servertransaction.ActivityConfigurationChangeItem;
@@ -1607,6 +1608,17 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
            // The activity may be waiting for stop, but that is no longer appropriate for it.
            mStackSupervisor.mStoppingActivities.remove(this);
            mStackSupervisor.mGoingToSleepActivities.remove(this);

            // If an activity is not in the paused state when becoming visible, cycle to the paused
            // state.
            if (state != PAUSED) {
                // An activity must be in the {@link PAUSING} state for the system to validate
                // the move to {@link PAUSED}.
                state = PAUSING;
                service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
                        PauseActivityItem.obtain(finishing, false /* userLeaving */,
                                configChangeFlags, false /* dontReport */));
            }
        } catch (Exception e) {
            // Just skip on any failure; we'll make it visible when it next restarts.
            Slog.w(TAG, "Exception thrown making visibile: " + intent.getComponent(), e);
+30 −1
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.view.Display.DEFAULT_DISPLAY;

import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
@@ -32,11 +35,14 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PauseActivityItem;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
@@ -46,11 +52,13 @@ import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;

import org.mockito.ArgumentCaptor;

/**
 * Tests for the {@link ActivityRecord} class.
 *
 * Build/Install/Run:
 *  bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
 *  atest FrameworksServicesTests:com.android.server.am.ActivityRecordTests
 */
@MediumTest
@Presubmit
@@ -100,6 +108,27 @@ public class ActivityRecordTests extends ActivityTestsBase {
        assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 0);
    }

    @Test
    public void testPausingWhenVisibleFromStopped() throws Exception {
        mActivity.state = STOPPED;
        mActivity.makeVisibleIfNeeded(null /* starting */);
        assertEquals(mActivity.state, PAUSING);

        final ArgumentCaptor<ClientTransaction> transaction =
                ArgumentCaptor.forClass(ClientTransaction.class);
        verify(mActivity.app.thread, atLeast(1)).scheduleTransaction(transaction.capture());

        boolean pauseFound = false;

        for (ClientTransaction targetTransaction : transaction.getAllValues()) {
            if (targetTransaction.getLifecycleStateRequest() instanceof PauseActivityItem) {
                pauseFound = true;
            }
        }

        assertTrue(pauseFound);
    }

    @Test
    public void testPositionLimitedAspectRatioNavBarBottom() throws Exception {
        verifyPositionWithLimitedAspectRatio(NAV_BAR_BOTTOM, new Rect(0, 0, 1000, 2000), 1.5f,
+5 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.spy;

import org.mockito.invocation.InvocationOnMock;

import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -177,6 +178,10 @@ public class ActivityTestsBase {
                mTaskRecord.addActivityToTop(activity);
            }

            activity.setProcess(new ProcessRecord(null, mService.mContext.getApplicationInfo(),
                    "name", 12345));
            activity.app.thread = mock(IApplicationThread.class);

            return activity;
        }
    }