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

Commit b6fb50b6 authored by Ivan Tkachenko's avatar Ivan Tkachenko
Browse files

Fix RemoteTargetGluer crash

- Updated DesktopVisibilityController to track the numer of visible
  freeform windows, and use it to initialize RemoteTargetGluer.
- Updated IDesktopTaskListener to observe visible freeform windows count
- Added resize remoteTargetHandles logic in RemoteTargetGLuer to update
  handles size with targets.apps.size on assign.
- This is a workaround and should be removed when RemoteTargetGLuer
  intialisation logic is refactored.

Bug: 288121021
Flag: None
Test: Manual
Change-Id: I0297616b4a140fac810c9736bddf6f817d0a98ed
parent 6d4fe47e
Loading
Loading
Loading
Loading
+37 −23
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ public class DesktopVisibilityController {
            "persist.wm.debug.desktop_stashing", false);
    private final Launcher mLauncher;

    private boolean mFreeformTasksVisible;
    private int mVisibleFreeformTasksCount;
    private boolean mInOverviewState;
    private boolean mBackgroundStateEnabled;
    private boolean mGestureInProgress;
@@ -68,13 +68,13 @@ public class DesktopVisibilityController {
    public void registerSystemUiListener() {
        mDesktopTaskListener = new IDesktopTaskListener.Stub() {
            @Override
            public void onVisibilityChanged(int displayId, boolean visible) {
            public void onTasksVisibilityChanged(int displayId, int visibleTasksCount) {
                MAIN_EXECUTOR.execute(() -> {
                    if (displayId == mLauncher.getDisplayId()) {
                        if (DEBUG) {
                            Log.d(TAG, "desktop visibility changed value=" + visible);
                            Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount);
                        }
                        setFreeformTasksVisible(visible);
                        setVisibleFreeformTasksCount(visibleTasksCount);
                    }
                });
            }
@@ -112,32 +112,45 @@ public class DesktopVisibilityController {
     * Whether freeform windows are visible in desktop mode.
     */
    public boolean areFreeformTasksVisible() {
        boolean freeformTasksVisible = mVisibleFreeformTasksCount > 0;
        if (DEBUG) {
            Log.d(TAG, "areFreeformTasksVisible: freeformVisible=" + mFreeformTasksVisible
            Log.d(TAG, "areFreeformTasksVisible: freeformVisible=" + freeformTasksVisible
                    + " overview=" + mInOverviewState);
        }
        return mFreeformTasksVisible && !mInOverviewState;
        return freeformTasksVisible && !mInOverviewState;
    }

    /**
     * Sets whether freeform windows are visible and updates launcher visibility based on that.
     * Number of visible freeform windows in desktop mode.
     */
    public void setFreeformTasksVisible(boolean freeformTasksVisible) {
    public int getVisibleFreeformTasksCount() {
        return mVisibleFreeformTasksCount;
    }

    /**
     * Sets the number of freeform windows that are visible and updates launcher visibility based on
     * it.
     */
    public void setVisibleFreeformTasksCount(int visibleTasksCount) {
        if (DEBUG) {
            Log.d(TAG, "setFreeformTasksVisible: visible=" + freeformTasksVisible
                    + " currentValue=" + mFreeformTasksVisible);
            Log.d(TAG, "setVisibleFreeformTasksCount: visibleTasksCount=" + visibleTasksCount
                    + " currentValue=" + mVisibleFreeformTasksCount);
        }
        if (!isDesktopModeSupported()) {
            return;
        }

        if (freeformTasksVisible != mFreeformTasksVisible) {
            mFreeformTasksVisible = freeformTasksVisible;
            if (mFreeformTasksVisible) {
        if (visibleTasksCount != mVisibleFreeformTasksCount) {
            final boolean wasVisible = mVisibleFreeformTasksCount > 0;
            final boolean isVisible = visibleTasksCount > 0;
            mVisibleFreeformTasksCount = visibleTasksCount;

            if (wasVisible != isVisible) {
                if (mVisibleFreeformTasksCount > 0) {
                    setLauncherViewsVisibility(View.INVISIBLE);
                    if (!mInOverviewState) {
                    // When freeform is visible & we're not in overview, we want launcher to appear
                    // paused, this ensures that taskbar displays.
                        // When freeform is visible & we're not in overview, we want launcher to
                        // appear paused, this ensures that taskbar displays.
                        markLauncherPaused();
                    }
                } else {
@@ -148,6 +161,7 @@ public class DesktopVisibilityController {
                }
            }
        }
    }

    /**
     * Process launcher state change and update launcher view visibility based on desktop state
+31 −19
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.view.RemoteAnimationTarget;

import androidx.annotation.Nullable;

import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.TaskViewSimulator;
@@ -62,15 +63,18 @@ public class RemoteTargetGluer {
     */
    public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
        if (isDesktopModeSupported()) {
            // TODO(279931899): binder call, only for prototyping. Creating the gluer should be
            //  postponed so we can create it when we have the remote animation targets ready.
            int desktopTasks = SystemUiProxy.INSTANCE.get(context).getVisibleDesktopTaskCount(
                    context.getDisplayId());
            if (desktopTasks > 0) {
                init(context, sizingStrategy, desktopTasks, true /* forDesktop */);
            DesktopVisibilityController desktopVisibilityController =
                    LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
            if (desktopVisibilityController != null) {
                int visibleTasksCount = desktopVisibilityController.getVisibleFreeformTasksCount();
                if (visibleTasksCount > 0) {
                    // Allocate +1 to account for a new task added to the desktop mode
                    int numHandles = visibleTasksCount + 1;
                    init(context, sizingStrategy, numHandles, true /* forDesktop */);
                    return;
                }
            }
        }

        // Assume 2 handles needed for split, scale down as needed later on when we actually
        // get remote targets
@@ -129,18 +133,7 @@ public class RemoteTargetGluer {
     * the left/top task, index 1 right/bottom.
     */
    public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
        // Resize the mRemoteTargetHandles array since we started assuming split screen, but
        // targets.apps is the ultimate source of truth here
        long appCount = Arrays.stream(targets.apps)
                .filter(app -> app.mode == targets.targetMode)
                .count();
        Log.d(TAG, "appCount: " + appCount + " handleLength: " + mRemoteTargetHandles.length);
        if (appCount < mRemoteTargetHandles.length) {
            Log.d(TAG, "resizing handles");
            RemoteTargetHandle[] newHandles = new RemoteTargetHandle[(int) appCount];
            System.arraycopy(mRemoteTargetHandles, 0/*src*/, newHandles, 0/*dst*/, (int) appCount);
            mRemoteTargetHandles = newHandles;
        }
        resizeRemoteTargetHandles(targets);

        // If we are in a true split screen case (2 apps running on screen), either:
        //     a) mSplitBounds was already set (from the clicked GroupedTaskView)
@@ -198,6 +191,8 @@ public class RemoteTargetGluer {
     * transform params per app in {@code targets.apps} list.
     */
    public RemoteTargetHandle[] assignTargetsForDesktop(RemoteAnimationTargets targets) {
        resizeRemoteTargetHandles(targets);

        for (int i = 0; i < mRemoteTargetHandles.length; i++) {
            RemoteAnimationTarget primaryTaskTarget = targets.apps[i];
            mRemoteTargetHandles[i].mTransformParams.setTargetSet(
@@ -207,6 +202,23 @@ public class RemoteTargetGluer {
        return mRemoteTargetHandles;
    }

    /**
     * Resize the `mRemoteTargetHandles` array since we assumed initial size, but
     * `targets.apps` is the ultimate source of truth here
     */
    private void resizeRemoteTargetHandles(RemoteAnimationTargets targets) {
        long appCount = Arrays.stream(targets.apps)
                .filter(app -> app.mode == targets.targetMode)
                .count();
        Log.d(TAG, "appCount: " + appCount + " handleLength: " + mRemoteTargetHandles.length);
        if (appCount < mRemoteTargetHandles.length) {
            Log.d(TAG, "resizing handles");
            RemoteTargetHandle[] newHandles = new RemoteTargetHandle[(int) appCount];
            System.arraycopy(mRemoteTargetHandles, 0/*src*/, newHandles, 0/*dst*/, (int) appCount);
            mRemoteTargetHandles = newHandles;
        }
    }

    private Rect getStartBounds(RemoteAnimationTarget target) {
        return target.startBounds == null ? target.screenSpaceBounds : target.startBounds;
    }