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

Commit 6c75e58f authored by Winson Chung's avatar Winson Chung
Browse files

9/ Update transitions/starting window for shell thread

Bug: 161979899
Test: atest WMShellUnitTests
Test: atest SystemUITests
Change-Id: I0afbacd0db32ef02f1e178f7a53b16df5b64449b
parent f3e26616
Loading
Loading
Loading
Loading
+33 −37
Original line number Diff line number Diff line
@@ -377,12 +377,10 @@ public class StartingSurfaceDrawer {
        final int taskId = startingWindowInfo.taskInfo.taskId;
        final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
                snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */);
        mMainExecutor.execute(() -> {
        mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
        final StartingWindowRecord tView =
                new StartingWindowRecord(null/* decorView */, surface);
        mStartingWindowRecords.put(taskId, tView);
        });
    }

    /**
@@ -392,12 +390,11 @@ public class StartingSurfaceDrawer {
        if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
            Slog.d(TAG, "Task start finish, remove starting surface for task " + taskId);
        }
        mMainExecutor.execute(() -> removeWindowSynced(taskId));
        removeWindowSynced(taskId);
    }

    protected void postAddWindow(int taskId, IBinder appToken,
        View view, WindowManager wm, WindowManager.LayoutParams params) {
        mMainExecutor.execute(() -> {
        boolean shouldSaveView = true;
        try {
            wm.addView(view, params);
@@ -427,7 +424,6 @@ public class StartingSurfaceDrawer {
                    new StartingWindowRecord(view, null /* TaskSnapshotWindow */);
            mStartingWindowRecords.put(taskId, tView);
        }
        });
    }

    protected void removeWindowSynced(int taskId) {
@@ -445,7 +441,7 @@ public class StartingSurfaceDrawer {
                if (DEBUG_TASK_SNAPSHOT) {
                    Slog.v(TAG, "Removing task snapshot window for " + taskId);
                }
                record.mTaskSnapshotWindow.remove(mMainExecutor);
                record.mTaskSnapshotWindow.remove();
            }
            mStartingWindowRecords.remove(taskId);
        }
+27 −29
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DecorView;
import com.android.internal.view.BaseIWindow;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;

/**
 * This class represents a starting window that shows a snapshot.
@@ -121,6 +122,7 @@ public class TaskSnapshotWindow {
    private final Window mWindow;
    private final Surface mSurface;
    private final Runnable mClearWindowHandler;
    private final ShellExecutor mMainExecutor;
    private SurfaceControl mSurfaceControl;
    private SurfaceControl mChildSurfaceControl;
    private final IWindowSession mSession;
@@ -213,7 +215,7 @@ public class TaskSnapshotWindow {
        final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
                surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, appearance,
                windowFlags, windowPrivateFlags, taskBounds, orientation, activityType,
                topWindowInsetsState, clearWindowHandler);
                topWindowInsetsState, clearWindowHandler, mainExecutor);
        final Window window = snapshotSurface.mWindow;

        final InsetsState mTmpInsetsState = new InsetsState();
@@ -229,7 +231,7 @@ public class TaskSnapshotWindow {
            } catch (RemoteException e) {
                snapshotSurface.clearWindowSynced();
            }
            window.setOuter(snapshotSurface, mainExecutor);
            window.setOuter(snapshotSurface);
            try {
                session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1,
                        tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
@@ -249,7 +251,8 @@ public class TaskSnapshotWindow {
            TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
            int appearance, int windowFlags, int windowPrivateFlags, Rect taskBounds,
            int currentOrientation, int activityType, InsetsState topWindowInsetsState,
            Runnable clearWindowHandler) {
            Runnable clearWindowHandler, ShellExecutor mainExecutor) {
        mMainExecutor = mainExecutor;
        mSurface = new Surface();
        mSession = WindowManagerGlobal.getWindowSession();
        mWindow = new Window();
@@ -286,19 +289,18 @@ public class TaskSnapshotWindow {
        mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
    }

    void remove(ShellExecutor mainExecutor) {
    void remove() {
        final long now = SystemClock.uptimeMillis();
        if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS
                // Show the latest content as soon as possible for unlocking to home.
                && mActivityType != ACTIVITY_TYPE_HOME) {
            final long delayTime = mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS - now;
            mainExecutor.executeDelayed(() -> remove(mainExecutor), delayTime);
            mMainExecutor.executeDelayed(() -> remove(), delayTime);
            if (DEBUG) {
                Slog.d(TAG, "Defer removing snapshot surface in " + delayTime);
            }
            return;
        }
        mainExecutor.execute(() -> {
        try {
            if (DEBUG) {
                Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn);
@@ -307,7 +309,6 @@ public class TaskSnapshotWindow {
        } catch (RemoteException e) {
            // nothing
        }
        });
    }

    /**
@@ -497,13 +498,12 @@ public class TaskSnapshotWindow {
        }
    }

    @ExternalThread
    static class Window extends BaseIWindow {
        private TaskSnapshotWindow mOuter;
        private ShellExecutor mMainExecutor;

        public void setOuter(TaskSnapshotWindow outer, ShellExecutor mainExecutor) {
        public void setOuter(TaskSnapshotWindow outer) {
            mOuter = outer;
            mMainExecutor = mainExecutor;
        }

        @Override
@@ -511,22 +511,20 @@ public class TaskSnapshotWindow {
                MergedConfiguration mergedConfiguration, boolean forceLayout,
                boolean alwaysConsumeSystemBars, int displayId) {
            if (mOuter != null) {
                mOuter.mMainExecutor.execute(() -> {
                    if (mergedConfiguration != null
                            && mOuter.mOrientationOnCreation
                            != mergedConfiguration.getMergedConfiguration().orientation) {
                    // The orientation of the screen is changing. We better remove the snapshot ASAP
                    // as we are going to wait on the new window in any case to unfreeze the screen,
                    // and the starting window is not needed anymore.
                    mMainExecutor.execute(() -> {
                        // The orientation of the screen is changing. We better remove the snapshot
                        // ASAP as we are going to wait on the new window in any case to unfreeze
                        // the screen, and the starting window is not needed anymore.
                        mOuter.clearWindowSynced();
                    });
                    } else if (reportDraw) {
                    mMainExecutor.execute(() -> {
                        if (mOuter.mHasDrawn) {
                            mOuter.reportDrawn();
                        }
                    });
                    }
                });
            }
        }
    }
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.transition;

import android.annotation.NonNull;
import android.window.IRemoteTransition;
import android.window.TransitionFilter;

import com.android.wm.shell.common.annotations.ExternalThread;

/**
 * Interface to manage remote transitions.
 */
@ExternalThread
public interface RemoteTransitions {
    /**
     * Registers a remote transition.
     */
    void registerRemote(@NonNull TransitionFilter filter,
            @NonNull IRemoteTransition remoteTransition);

    /**
     * Unregisters a remote transition.
     */
    void unregisterRemote(@NonNull IRemoteTransition remoteTransition);
}
+39 −6
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public class Transitions {
    private final ShellExecutor mAnimExecutor;
    private final TransitionPlayerImpl mPlayerImpl;
    private final RemoteTransitionHandler mRemoteTransitionHandler;
    private final RemoteTransitionImpl mImpl = new RemoteTransitionImpl();

    /** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
    private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
@@ -78,6 +79,10 @@ public class Transitions {
    /** Keeps track of currently tracked transitions and all the animations associated with each */
    private final ArrayMap<IBinder, ActiveTransition> mActiveTransitions = new ArrayMap<>();

    public static RemoteTransitions asRemoteTransitions(Transitions transitions) {
        return transitions.mImpl;
    }

    public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
            @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
        mOrganizer = organizer;
@@ -101,8 +106,20 @@ public class Transitions {

    /** Create an empty/non-registering transitions object for system-ui tests. */
    @VisibleForTesting
    public static Transitions createEmptyForTesting() {
        return new Transitions();
    public static RemoteTransitions createEmptyForTesting() {
        return new RemoteTransitions() {
            @Override
            public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter,
                    @androidx.annotation.NonNull IRemoteTransition remoteTransition) {
                // Do nothing
            }

            @Override
            public void unregisterRemote(
                    @androidx.annotation.NonNull IRemoteTransition remoteTransition) {
                // Do nothing
            }
        };
    }

    /** Register this transition handler with Core */
@@ -134,16 +151,14 @@ public class Transitions {
    }

    /** Register a remote transition to be used when `filter` matches an incoming transition */
    @ExternalThread
    public void registerRemote(@NonNull TransitionFilter filter,
            @NonNull IRemoteTransition remoteTransition) {
        mMainExecutor.execute(() -> mRemoteTransitionHandler.addFiltered(filter, remoteTransition));
        mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
    }

    /** Unregisters a remote transition and all associated filters */
    @ExternalThread
    public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
        mMainExecutor.execute(() -> mRemoteTransitionHandler.removeFiltered(remoteTransition));
        mRemoteTransitionHandler.removeFiltered(remoteTransition);
    }

    /** @return true if the transition was triggered by opening something vs closing something */
@@ -361,4 +376,22 @@ public class Transitions {
            mMainExecutor.execute(() -> Transitions.this.requestStartTransition(iBinder, request));
        }
    }

    @ExternalThread
    private class RemoteTransitionImpl implements RemoteTransitions {
        @Override
        public void registerRemote(@NonNull TransitionFilter filter,
                @NonNull IRemoteTransition remoteTransition) {
            mMainExecutor.execute(() -> {
                Transitions.this.registerRemote(filter, remoteTransition);
            });
        }

        @Override
        public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
            mMainExecutor.execute(() -> {
                Transitions.this.unregisterRemote(remoteTransition);
            });
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.window.TaskSnapshot;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.startingsurface.TaskSnapshotWindow;

import org.junit.Test;
@@ -83,7 +84,7 @@ public class TaskSnapshotWindowTest {
                createTaskDescription(Color.WHITE, Color.RED, Color.BLUE),
                0 /* appearance */, windowFlags /* windowFlags */, 0 /* privateWindowFlags */,
                taskBounds, ORIENTATION_PORTRAIT, ACTIVITY_TYPE_STANDARD, new InsetsState(),
                null /* clearWindow */);
                null /* clearWindow */, new TestShellExecutor());
    }

    private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
Loading