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

Commit 40b68c07 authored by Merissa Mitchell's avatar Merissa Mitchell
Browse files

[WindowDecor] Move WindowDecorTaskResourceLoader calls to main thread

This CL makes the following changes:
- Combine getName and getHeaderIcon since they are always called
  together by their callers
- getNameAndHeaderIcon and getVeilIcon are now run on the main thread
  instead of the background thread. If the resource is not cached,
loadAppResources is run on the background thread. The result is then
returned on the main thread.

This eliminates the following race condition:
1) WindowDecor created, relayout called for the first time and schedules
   the loading of resources (including checking the cache) in the
background thread
2) WindowDecor destroyed while the callback for loading the resources
   has not finished
3) When the callback is finally run, the WindowDecor no longer exists,
   and checkWindowDecorExists throws an IllegalStateException

Test: atest WMShellUnitTests:com.android.wm.shell.windowdecor
Bug: 425315974
Flag: EXEMPT bugfix
Change-Id: Icad26c7641bb4d890318614e77f768d23b9c5d7b
parent 97d8da20
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.widget.TextView
import android.window.TaskConstants
import com.android.wm.shell.R
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader
@@ -47,7 +46,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


/**
@@ -62,7 +60,7 @@ internal class OpenByDefaultDialog(
    private val taskResourceLoader: WindowDecorTaskResourceLoader,
    private val surfaceControlTransactionSupplier: Supplier<SurfaceControl.Transaction>,
    @ShellMainThread private val mainDispatcher: MainCoroutineDispatcher,
    @ShellBackgroundThread private val bgScope: CoroutineScope,
    @ShellMainThread private val mainScope: CoroutineScope,
    private val listener: DialogLifecycleListener,
) {
    private lateinit var dialog: OpenByDefaultDialogView
@@ -84,16 +82,12 @@ internal class OpenByDefaultDialog(
    init {
        createDialog()
        initializeRadioButtons()
        loadAppInfoJob = bgScope.launch {
        loadAppInfoJob = mainScope.launch {
            if (!isActive) return@launch
            val name = taskResourceLoader.getName(taskInfo)
            val icon = taskResourceLoader.getHeaderIcon(taskInfo)
            withContext(mainDispatcher.immediate) {
                if (!isActive) return@withContext
            val (name, icon) = taskResourceLoader.getNameAndHeaderIcon(taskInfo)
            bindAppInfo(icon, name)
        }
    }
    }

    /** Creates an open by default settings dialog. */
    fun createDialog() {
+8 −2
Original line number Diff line number Diff line
@@ -982,6 +982,7 @@ public abstract class WMShellModule {
    @Provides
    static DesktopTilingDecorViewModel provideDesktopTilingViewModel(Context context,
            @ShellMainThread MainCoroutineDispatcher mainDispatcher,
            @ShellMainThread CoroutineScope mainScope,
            @ShellBackgroundThread CoroutineScope bgScope,
            DisplayController displayController,
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
@@ -1003,6 +1004,7 @@ public abstract class WMShellModule {
        return new DesktopTilingDecorViewModel(
                context,
                mainDispatcher,
                mainScope,
                bgScope,
                displayController,
                rootTaskDisplayAreaOrganizer,
@@ -1328,10 +1330,14 @@ public abstract class WMShellModule {
    static WindowDecorTaskResourceLoader provideWindowDecorTaskResourceLoader(
            @NonNull Context context, @NonNull ShellInit shellInit,
            @NonNull ShellController shellController,
            @ShellMainThread Handler mainHandler,
            @ShellMainThread CoroutineScope mainScope,
            @ShellMainThread MainCoroutineDispatcher mainDispatcher,
            @ShellBackgroundThread MainCoroutineDispatcher bgDispatcher,
            @NonNull ShellCommandHandler shellCommandHandler,
            @NonNull UserProfileContexts userProfileContexts) {
        return new WindowDecorTaskResourceLoader(context, shellInit, shellController,
                shellCommandHandler, userProfileContexts);
        return new WindowDecorTaskResourceLoader(context, shellInit, shellController, mainHandler,
                mainScope, mainDispatcher, bgDispatcher, shellCommandHandler, userProfileContexts);
    }

    @WMSingleton
+1 −4
Original line number Diff line number Diff line
@@ -110,7 +110,6 @@ class DefaultWindowDecoration @JvmOverloads constructor(
    @ShellMainThread private val mainExecutor: ShellExecutor,
    @ShellMainThread private val mainDispatcher: MainCoroutineDispatcher,
    @ShellMainThread private val mainScope: CoroutineScope,
    @ShellBackgroundThread private val bgScope: CoroutineScope,
    @ShellBackgroundThread private val bgExecutor: ShellExecutor,
    private val transitions: Transitions,
    private val choreographer: Choreographer,
@@ -783,7 +782,7 @@ class DefaultWindowDecoration @JvmOverloads constructor(
            displayController = displayController,
            taskResourceLoader = taskResourceLoader,
            mainDispatcher = mainDispatcher,
            bgScope = bgScope,
            mainScope = mainScope,
            parentSurface = taskSurface,
            surfaceControlTransactionSupplier = surfaceControlTransactionSupplier,
            taskInfo = taskInfo
@@ -899,7 +898,6 @@ class DefaultWindowDecoration @JvmOverloads constructor(
                mainExecutor,
                mainDispatcher,
                mainScope,
                bgScope,
                bgExecutor,
                syncQueue,
                rootTaskDisplayAreaOrganizer,
@@ -935,7 +933,6 @@ class DefaultWindowDecoration @JvmOverloads constructor(
                handler,
                mainDispatcher,
                mainScope,
                bgScope,
                windowManagerWrapper,
                multiInstanceHelper,
                windowDecorCaptionRepository,
+1 −1
Original line number Diff line number Diff line
@@ -2038,7 +2038,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    mMainExecutor,
                    mMainDispatcher,
                    mMainScope,
                    mBgScope,
                    mBgExecutor,
                    mTransitions,
                    mMainChoreographer,
@@ -2073,6 +2072,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                            mMainHandler,
                            mMainExecutor,
                            mMainDispatcher,
                            mMainScope,
                            mBgScope,
                            mBgExecutor,
                            mTransitions,
+15 −32
Original line number Diff line number Diff line
@@ -124,12 +124,12 @@ import kotlin.Pair;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.functions.Function2;

import kotlinx.coroutines.CoroutineScope;
import kotlinx.coroutines.MainCoroutineDispatcher;

import java.util.ArrayList;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -150,6 +150,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    private final @ShellMainThread Handler mHandler;
    private final @ShellMainThread ShellExecutor mMainExecutor;
    private final @ShellMainThread MainCoroutineDispatcher mMainDispatcher;
    private final @ShellMainThread CoroutineScope mMainScope;
    private final @ShellBackgroundThread CoroutineScope mBgScope;
    private final @ShellBackgroundThread ShellExecutor mBgExecutor;
    private final Transitions mTransitions;
@@ -216,8 +217,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    private final DesktopModeUiEventLogger mDesktopModeUiEventLogger;
    private boolean mIsRecentsTransitionRunning = false;
    private boolean mIsDragging = false;
    private Runnable mLoadAppInfoRunnable;
    private Runnable mSetAppInfoRunnable;

    private final Function0<Unit> mCloseMaximizeMenuFunction = () -> {
        closeMaximizeMenu();
@@ -242,6 +241,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            @ShellMainThread Handler handler,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread MainCoroutineDispatcher mainDispatcher,
            @ShellMainThread CoroutineScope mainScope,
            @ShellBackgroundThread CoroutineScope bgScope,
            @ShellBackgroundThread ShellExecutor bgExecutor,
            Transitions transitions,
@@ -264,8 +264,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            LockTaskChangeListener lockTaskChangeListener) {
        this (context, userContext, displayController, taskResourceLoader, splitScreenController,
                desktopUserRepositories, taskOrganizer, taskInfo, taskSurface, handler,
                mainExecutor, mainDispatcher, bgScope, bgExecutor, transitions, choreographer,
                syncQueue, appHeaderViewHolderFactory, appHandleViewHolderFactory,
                mainExecutor, mainDispatcher, mainScope, bgScope, bgExecutor, transitions,
                choreographer, syncQueue, appHeaderViewHolderFactory, appHandleViewHolderFactory,
                rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester,
                SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
                WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(
@@ -292,6 +292,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            @ShellMainThread Handler handler,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread MainCoroutineDispatcher mainDispatcher,
            @ShellMainThread CoroutineScope mainScope,
            @ShellBackgroundThread CoroutineScope bgScope,
            @ShellBackgroundThread ShellExecutor bgExecutor,
            Transitions transitions,
@@ -329,6 +330,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        mHandler = handler;
        mMainExecutor = mainExecutor;
        mMainDispatcher = mainDispatcher;
        mMainScope = mainScope;
        mBgScope = bgScope;
        mBgExecutor = bgExecutor;
        mTransitions = transitions;
@@ -544,6 +546,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                        notifyCaptionStateChanged();
                    }
                }
                return Unit.INSTANCE;
            });
        }

@@ -573,30 +576,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    }

    /**
     * Loads the task's name and icon in a background thread and posts the results back in the
     * main thread.
     * Loads the task's name and icon in a background thread (if they are not cached) and posts the
     * results back in the main thread.
     */
    private void loadTaskNameAndIconInBackground(BiConsumer<CharSequence, Bitmap> onResult) {
    private void loadTaskNameAndIconInBackground(Function2<CharSequence, Bitmap, Unit> onResult) {
        if (mWindowDecorViewHolder == null) return;
        if (asAppHeader(mWindowDecorViewHolder) == null) {
            // Only needed when drawing a header.
            return;
        }
        if (mLoadAppInfoRunnable != null) {
            mBgExecutor.removeCallbacks(mLoadAppInfoRunnable);
        }
        if (mSetAppInfoRunnable != null) {
            mMainExecutor.removeCallbacks(mSetAppInfoRunnable);
        }
        mLoadAppInfoRunnable = () -> {
            final CharSequence name = mTaskResourceLoader.getName(mTaskInfo);
            final Bitmap icon = mTaskResourceLoader.getHeaderIcon(mTaskInfo);
            mSetAppInfoRunnable = () -> {
                onResult.accept(name, icon);
            };
            mMainExecutor.execute(mSetAppInfoRunnable);
        };
        mBgExecutor.execute(mLoadAppInfoRunnable);
        mTaskResourceLoader.getNameAndHeaderIcon(mTaskInfo, onResult);
    }

    private boolean showInputLayer() {
@@ -1298,7 +1287,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                mTaskResourceLoader,
                mSurfaceControlTransactionSupplier,
                mMainDispatcher,
                mBgScope,
                mMainScope,
                new OpenByDefaultDialog.DialogLifecycleListener() {
                    @Override
                    public void onDialogCreated() {
@@ -1336,7 +1325,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
    private void createResizeVeilIfNeeded() {
        if (mResizeVeil != null) return;
        mResizeVeil = new ResizeVeil(mContext, mDisplayController, mTaskResourceLoader,
                mMainDispatcher, mBgScope, mTaskSurface,
                mMainDispatcher, mMainScope, mTaskSurface,
                mSurfaceControlTransactionSupplier, mTaskInfo);
    }

@@ -1570,7 +1559,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        }
        mHandleMenu = mHandleMenuFactory.create(
                mMainDispatcher,
                mBgScope,
                mMainScope,
                this,
                mWindowManagerWrapper,
                mWindowDecorationActions,
@@ -1874,12 +1863,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin

    @Override
    public void close() {
        if (mLoadAppInfoRunnable != null) {
            mBgExecutor.removeCallbacks(mLoadAppInfoRunnable);
        }
        if (mSetAppInfoRunnable != null) {
            mMainExecutor.removeCallbacks(mSetAppInfoRunnable);
        }
        mTaskResourceLoader.onWindowDecorClosed(mTaskInfo);
        closeDragResizeListener();
        closeHandleMenu();
Loading