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

Commit 3d119a90 authored by Louis Chang's avatar Louis Chang
Browse files

Set activity state to PAUSED when making visible from STOPPING/STOPPED

An invisible activity state was STOPPED and was not updated while
making it visible. Once the activity became invisible again, the
activity won’t have to reenter the STOPPED state. But the window
surface was not destroyed and the window was in the surface destroy list
(WindowState.mDestroying was true).

In that case, when resuming the activity by finishing current top
activity (such as pressing back key), a transition animation was
set, but failed to play and had to wait until timeout.

Bug: 118349021
Bug: 132811175
Bug: 134986295
Test: ActivityRecordTests
Test: ActivityVisibilityTests
Test: ActivityLifecycleTests

Change-Id: I887740312de8f8580c58cde36e0f5137365b607c
parent 19f2034a
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2039,6 +2039,13 @@ final class ActivityRecord extends ConfigurationContainer {
            mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                    WindowVisibilityItem.obtain(true /* showWindow */));
            makeActiveIfNeeded(null /* activeActivity*/);
            if (isState(STOPPING, STOPPED) && isFocusable()) {
                // #shouldMakeActive() only evaluates the topmost activities in task, so
                // activities that are not the topmost in task are not being resumed or paused.
                // For activities that are still in STOPPING or STOPPED state, updates the state
                // to PAUSE at least when making it visible.
                setState(PAUSED, "makeClientVisible");
            }
        } catch (Exception e) {
            Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
        }
+11 −4
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
@@ -56,7 +57,6 @@ import android.app.servertransaction.PauseActivityItem;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
@@ -163,12 +163,10 @@ public class ActivityRecordTests extends ActivityTestsBase {
        // Make sure the state does not change if we are not the current top activity.
        mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped behind");

        // Make sure that the state does not change when we have an activity becoming translucent
        final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
        mStack.mTranslucentActivityWaiting = topActivity;
        mActivity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);

        assertTrue(mActivity.isState(STOPPED));
        assertTrue(mActivity.isState(PAUSED));
    }

    private void ensureActivityConfiguration() {
@@ -438,6 +436,15 @@ public class ActivityRecordTests extends ActivityTestsBase {
        }
    }

    @Test
    public void testShouldPauseWhenMakeClientVisible() {
        ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
        topActivity.changeWindowTranslucency(false);
        mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
        mActivity.makeClientVisible();
        assertEquals(PAUSED, mActivity.getState());
    }

    @Test
    public void testSizeCompatMode_FixedAspectRatioBoundsWithDecor() {
        setupDisplayContentForCompatDisplayInsets();