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

Commit b3dee02f authored by Winson Chung's avatar Winson Chung
Browse files

Load the split divider veil icons on a boosted background thread

- Re-land ag/27118118 (trigger loading of split veil icons at touch
  down vs after moving past a threashold), and move loading of the
  split resize veil icons to the background thread (and boost during
  icon load to ensure we get them with foreground priority)

Bug: 370895085
Bug: 351138552
Flag: EXEMPT bugfix
Test: Splitscreen smoke test & take perfetto trace when moving the divider
Change-Id: Ia416cea8709bdeac5b47a4efda785079804a312e
parent e7974aca
Loading
Loading
Loading
Loading
+60 −10
Original line number Diff line number Diff line
@@ -33,12 +33,14 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Trace;
import android.view.IWindow;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
@@ -50,10 +52,12 @@ import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SurfaceUtils;

import java.util.function.Consumer;
@@ -79,9 +83,19 @@ public class SplitDecorManager extends WindowlessWindowManager {
    private static final String RESIZING_BACKGROUND_SURFACE_NAME = "ResizingBackground";
    private static final String GAP_BACKGROUND_SURFACE_NAME = "GapBackground";

    // Indicates the loading state of mIcon
    enum IconLoadState {
        NOT_LOADED,
        LOADING,
        LOADED
    }

    private final IconProvider mIconProvider;
    private final ShellExecutor mMainExecutor;
    private final ShellExecutor mBgExecutor;

    private Drawable mIcon;
    private IconLoadState mIconLoadState = IconLoadState.NOT_LOADED;
    private ImageView mVeilIconView;
    private SurfaceControlViewHost mViewHost;
    /** The parent surface that this is attached to. Should be the stage root. */
@@ -109,9 +123,14 @@ public class SplitDecorManager extends WindowlessWindowManager {
    private int mOffsetY;
    private int mRunningAnimationCount = 0;

    public SplitDecorManager(Configuration configuration, IconProvider iconProvider) {
    public SplitDecorManager(Configuration configuration,
            IconProvider iconProvider,
            ShellExecutor mainExecutor,
            ShellExecutor bgExecutor) {
        super(configuration, null /* rootSurface */, null /* hostInputToken */);
        mIconProvider = iconProvider;
        mMainExecutor = mainExecutor;
        mBgExecutor = bgExecutor;
    }

    @Override
@@ -199,6 +218,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
        }
        mHostLeash = null;
        mIcon = null;
        mIconLoadState = IconLoadState.NOT_LOADED;
        mVeilIconView = null;
        mIsCurrentlyChanging = false;
        mShown = false;
@@ -260,10 +280,11 @@ public class SplitDecorManager extends WindowlessWindowManager {
                    .setWindowCrop(mGapBackgroundLeash, sideBounds.width(), sideBounds.height());
        }

        if (mIcon == null && resizingTask.topActivityInfo != null) {
            mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo);
        if (mIconLoadState == IconLoadState.NOT_LOADED && resizingTask.topActivityInfo != null) {
            loadIconInBackground(resizingTask.topActivityInfo, () -> {
                mVeilIconView.setImageDrawable(mIcon);
                mVeilIconView.setVisibility(View.VISIBLE);
            });

            WindowManager.LayoutParams lp =
                    (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
@@ -417,10 +438,10 @@ public class SplitDecorManager extends WindowlessWindowManager {
        }

        if (mIcon == null && resizingTask.topActivityInfo != null) {
            // Initialize icon
            mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo);
            loadIconInBackground(resizingTask.topActivityInfo, () -> {
                mVeilIconView.setImageDrawable(mIcon);
                mVeilIconView.setVisibility(View.VISIBLE);
            });

            WindowManager.LayoutParams lp =
                    (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
@@ -453,7 +474,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
            return;
        }

        // Recenter icon
        // Re-center icon
        t.setPosition(mIconLeash,
                mInstantaneousBounds.width() / 2f - mIconSize / 2f,
                mInstantaneousBounds.height() / 2f - mIconSize / 2f);
@@ -596,7 +617,36 @@ public class SplitDecorManager extends WindowlessWindowManager {
            mVeilIconView.setImageDrawable(null);
            t.hide(mIconLeash);
            mIcon = null;
            mIconLoadState = IconLoadState.NOT_LOADED;
        }
    }

    /**
     * Loads the icon for the given {@param info}, calling {@param postLoadCb} on the main thread
     * if provided.
     */
    private void loadIconInBackground(@NonNull ActivityInfo info, @Nullable Runnable postLoadCb) {
        mIconLoadState = IconLoadState.LOADING;
        mBgExecutor.setBoost();
        mBgExecutor.execute(() -> {
            Trace.beginSection("SplitDecorManager.loadIconInBackground("
                    + info.applicationInfo.packageName + ")");
            final Drawable icon = mIconProvider.getIcon(info);
            Trace.endSection();
            mMainExecutor.execute(() -> {
                if (mIconLoadState != IconLoadState.LOADING) {
                    // The request was canceled while loading in the background, just drop the
                    // result
                    return;
                }
                mIcon = icon;
                mIconLoadState = IconLoadState.LOADED;
                if (postLoadCb != null) {
                    postLoadCb.run();
                }
            });
            mBgExecutor.resetBoost();
        });
    }

    private static float[] getResizingBackgroundColor(ActivityManager.RunningTaskInfo taskInfo) {
+4 −0
Original line number Diff line number Diff line
@@ -794,6 +794,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
    }

    void onStartDragging() {
        // This triggers initialization of things like the resize veil in preparation for
        // showing it when the user moves the divider past the slop
        updateDividerBounds(getDividerPosition(), false /* shouldUseParallaxEffect */);

        mInteractionJankMonitor.begin(getDividerLeash(), mContext, mHandler,
                CUJ_SPLIT_SCREEN_RESIZE);
    }
+3 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.wm.shell.common.split.SplitState;
import com.android.wm.shell.dagger.pip.TvPipModule;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.shared.TransactionPool;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.splitscreen.tv.TvSplitScreenController;
@@ -93,11 +94,12 @@ public class TvWMShellModule {
            SplitState splitState,
            @ShellMainThread ShellExecutor mainExecutor,
            Handler mainHandler,
            @ShellBackgroundThread ShellExecutor bgExecutor,
            SystemWindows systemWindows) {
        return new TvSplitScreenController(context, shellInit, shellCommandHandler, shellController,
                shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController,
                displayImeController, displayInsetsController, transitions, transactionPool,
                iconProvider, recentTasks, launchAdjacentController, multiInstanceHelper,
                splitState, mainExecutor, mainHandler, systemWindows);
                splitState, mainExecutor, mainHandler, bgExecutor, systemWindows);
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -517,7 +517,8 @@ public abstract class WMShellModule {
            MultiInstanceHelper multiInstanceHelper,
            SplitState splitState,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread Handler mainHandler) {
            @ShellMainThread Handler mainHandler,
            @ShellBackgroundThread ShellExecutor bgExecutor) {
        return new SplitScreenController(
                context,
                shellInit,
@@ -541,7 +542,8 @@ public abstract class WMShellModule {
                multiInstanceHelper,
                splitState,
                mainExecutor,
                mainHandler);
                mainHandler,
                bgExecutor);
    }

    //
+6 −3
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
    private final LauncherApps mLauncherApps;
    private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
    private final ShellExecutor mMainExecutor;
    private final ShellExecutor mBgExecutor;
    private final Handler mMainHandler;
    private final SplitScreenImpl mImpl = new SplitScreenImpl();
    private final DisplayController mDisplayController;
@@ -231,7 +232,8 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
            MultiInstanceHelper multiInstanceHelper,
            SplitState splitState,
            ShellExecutor mainExecutor,
            Handler mainHandler) {
            Handler mainHandler,
            ShellExecutor bgExecutor) {
        mShellCommandHandler = shellCommandHandler;
        mShellController = shellController;
        mTaskOrganizer = shellTaskOrganizer;
@@ -241,6 +243,7 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
        mRootTDAOrganizer = rootTDAOrganizer;
        mMainExecutor = mainExecutor;
        mMainHandler = mainHandler;
        mBgExecutor = bgExecutor;
        mDisplayController = displayController;
        mDisplayImeController = displayImeController;
        mDisplayInsetsController = displayInsetsController;
@@ -298,8 +301,8 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
        return new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                mTaskOrganizer, mDisplayController, mDisplayImeController,
                mDisplayInsetsController, mTransitions, mTransactionPool, mIconProvider,
                mMainExecutor, mMainHandler, mRecentTasksOptional, mLaunchAdjacentController,
                mWindowDecorViewModel, mSplitState);
                mMainExecutor, mMainHandler, mBgExecutor, mRecentTasksOptional,
                mLaunchAdjacentController, mWindowDecorViewModel, mSplitState);
    }

    @Override
Loading