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

Commit aa7bf8b3 authored by Vinit Nayak's avatar Vinit Nayak
Browse files

Add initial split from GroupedTaskView animation

* Created SplitAnimationController to prevent more
RecentsView bloat
* Extract SplitSelectSource attributes into separate class
* http://recall/-/cMb5xTTxhmZtFt04eYnmQj/eACJq1un8Ef91LgmQblpAw

Bug: 267370106
Change-Id: I5d430c091ac84bbbc30319e7b78711b610a21252
parent f1a0bd61
Loading
Loading
Loading
Loading
+163 −0
Original line number Diff line number Diff line
/*
 *  Copyright (C) 2023 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.quickstep.util

import android.animation.ObjectAnimator
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.view.View
import com.android.launcher3.DeviceProfile
import com.android.launcher3.anim.PendingAnimation
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
import com.android.quickstep.views.TaskThumbnailView
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
import java.util.function.Supplier

/**
 * Utils class to help run animations for initiating split screen from launcher.
 * Will be expanded with future refactors. Works in conjunction with the state stored in
 * [SplitSelectStateController]
 */
class SplitAnimationController(val splitSelectStateController: SplitSelectStateController) {
    companion object {
        // Break this out into maybe enums? Abstractions into its own classes? Tbd.
        data class SplitAnimInitProps(
                val originalView: View,
                val originalBitmap: Bitmap?,
                val iconDrawable: Drawable,
                val fadeWithThumbnail: Boolean,
                val isStagedTask: Boolean,
                val iconView: View?
        )
    }

    /**
     * Returns different elements to animate for the initial split selection animation
     * depending on the state of the surface from which the split was initiated
     */
    fun getFirstAnimInitViews(taskViewSupplier: Supplier<TaskView>,
                              splitSelectSourceSupplier: Supplier<SplitSelectSource>)
            : SplitAnimInitProps {
        if (!splitSelectStateController.isAnimateCurrentTaskDismissal) {
            // Initiating from home
            val splitSelectSource = splitSelectSourceSupplier.get()
            return SplitAnimInitProps(splitSelectSource.view, originalBitmap = null,
                    splitSelectSource.drawable, fadeWithThumbnail = false, isStagedTask = true,
                    iconView = null)
        } else if (splitSelectStateController.isDismissingFromSplitPair) {
            // Initiating split from overview, but on a split pair
            val taskView = taskViewSupplier.get()
            for (container : TaskIdAttributeContainer in taskView.taskIdAttributeContainers) {
                if (container.task.key.id == splitSelectStateController.initialTaskId) {
                    return SplitAnimInitProps(container.thumbnailView,
                            container.thumbnailView.thumbnail, container.iconView.drawable!!,
                            fadeWithThumbnail = true, isStagedTask = true,
                            iconView = container.iconView
                    )
                }
            }
            throw IllegalStateException("Attempting to init split from existing split pair " +
                    "without a valid taskIdAttributeContainer")
        } else {
            // Initiating split from overview on fullscreen task TaskView
            val taskView = taskViewSupplier.get()
            return SplitAnimInitProps(taskView.thumbnail, taskView.thumbnail.thumbnail,
                    taskView.iconView.drawable!!, fadeWithThumbnail = true, isStagedTask = true,
                    taskView.iconView
            )
        }
    }

    /**
     * When selecting first app from split pair, second app's thumbnail remains. This animates
     * the second thumbnail by expanding it to take up the full taskViewWidth/Height and overlaying
     * it with [TaskThumbnailView]'s splashView. Adds animations to the provided builder.
     * Note: The app that **was not** selected as the first split app should be the container that's
     * passed through.
     *
     * @param builder Adds animation to this
     * @param taskIdAttributeContainer container of the app that **was not** selected
     * @param isPrimaryTaskSplitting if true, task that was split would be top/left in the pair
     *                               (opposite of that representing [taskIdAttributeContainer])
     */
    fun addInitialSplitFromPair(taskIdAttributeContainer: TaskIdAttributeContainer,
                                builder: PendingAnimation, deviceProfile: DeviceProfile,
                                taskViewWidth: Int, taskViewHeight: Int,
                                isPrimaryTaskSplitting: Boolean) {
        val thumbnail = taskIdAttributeContainer.thumbnailView
        val iconView: View = taskIdAttributeContainer.iconView
        builder.add(ObjectAnimator.ofFloat(thumbnail, TaskThumbnailView.SPLASH_ALPHA, 1f))
        thumbnail.setShowSplashForSplitSelection(true)
        if (deviceProfile.isLandscape) {
            // Center view first so scaling happens uniformly, alternatively we can move pivotX to 0
            val centerThumbnailTranslationX: Float = (taskViewWidth - thumbnail.width) / 2f
            val centerIconTranslationX: Float = (taskViewWidth - iconView.width) / 2f
            val finalScaleX: Float = taskViewWidth.toFloat() / thumbnail.width
            builder.add(ObjectAnimator.ofFloat(thumbnail,
                    TaskThumbnailView.SPLIT_SELECT_TRANSLATE_X, centerThumbnailTranslationX))
            // icons are anchored from Gravity.END, so need to use negative translation
            builder.add(ObjectAnimator.ofFloat(iconView, View.TRANSLATION_X,
                    -centerIconTranslationX))
            builder.add(ObjectAnimator.ofFloat(thumbnail, View.SCALE_X, finalScaleX))

            // Reset other dimensions
            // TODO(b/271468547), can't set Y translate to 0, need to account for top space
            thumbnail.scaleY = 1f
            val translateYResetVal: Float = if (!isPrimaryTaskSplitting) 0f else
                deviceProfile.overviewTaskThumbnailTopMarginPx.toFloat()
            builder.add(ObjectAnimator.ofFloat(thumbnail,
                    TaskThumbnailView.SPLIT_SELECT_TRANSLATE_Y,
                    translateYResetVal))
        } else {
            val thumbnailSize = taskViewHeight - deviceProfile.overviewTaskThumbnailTopMarginPx
            // Center view first so scaling happens uniformly, alternatively we can move pivotY to 0
            // primary thumbnail has layout margin above it, so secondary thumbnail needs to take
            // that into account. We should migrate to only using translations otherwise this
            // asymmetry causes problems..

            // Icon defaults to center | horizontal, we add additional translation for split
            val centerIconTranslationX = 0f
            var centerThumbnailTranslationY: Float

            // TODO(b/271468547), primary thumbnail has layout margin above it, so secondary
            //  thumbnail needs to take that into account. We should migrate to only using
            //  translations otherwise this asymmetry causes problems..
            if (isPrimaryTaskSplitting) {
                centerThumbnailTranslationY = (thumbnailSize - thumbnail.height) / 2f
                centerThumbnailTranslationY += deviceProfile.overviewTaskThumbnailTopMarginPx
                        .toFloat()
            } else {
                centerThumbnailTranslationY = (thumbnailSize - thumbnail.height) / 2f
            }
            val finalScaleY: Float = thumbnailSize.toFloat() / thumbnail.height
            builder.add(ObjectAnimator.ofFloat(thumbnail,
                    TaskThumbnailView.SPLIT_SELECT_TRANSLATE_Y, centerThumbnailTranslationY))

            // icons are anchored from Gravity.END, so need to use negative translation
            builder.add(ObjectAnimator.ofFloat(iconView, View.TRANSLATION_X,
                    centerIconTranslationX))
            builder.add(ObjectAnimator.ofFloat(thumbnail, View.SCALE_Y, finalScaleY))

            // Reset other dimensions
            thumbnail.scaleX = 1f
            builder.add(ObjectAnimator.ofFloat(thumbnail,
                    TaskThumbnailView.SPLIT_SELECT_TRANSLATE_X, 0f))
        }
    }
}
+24 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ public class SplitSelectStateController {
    private final Context mContext;
    private final Handler mHandler;
    private final RecentsModel mRecentTasksModel;
    private final SplitAnimationController mSplitAnimationController;
    private StatsLogManager mStatsLogManager;
    private final SystemUiProxy mSystemUiProxy;
    private final StateManager mStateManager;
@@ -96,6 +97,11 @@ public class SplitSelectStateController {
    private boolean mRecentsAnimationRunning;
    /** If {@code true}, animates the existing task view split placeholder view */
    private boolean mAnimateCurrentTaskDismissal;
    /**
     * Acts as a subset of {@link #mAnimateCurrentTaskDismissal}, we can't be dismissing from a
     * split pair task view without wanting to animate current task dismissal overall
     */
    private boolean mDismissingFromSplitPair;
    @Nullable
    private UserHandle mUser;
    /** If not null, this is the TaskView we want to launch from */
@@ -116,6 +122,7 @@ public class SplitSelectStateController {
        mStateManager = stateManager;
        mDepthController = depthController;
        mRecentTasksModel = recentsModel;
        mSplitAnimationController = new SplitAnimationController(this);
    }

    /**
@@ -399,6 +406,18 @@ public class SplitSelectStateController {
        mAnimateCurrentTaskDismissal = animateCurrentTaskDismissal;
    }

    public boolean isDismissingFromSplitPair() {
        return mDismissingFromSplitPair;
    }

    public void setDismissingFromSplitPair(boolean dismissingFromSplitPair) {
        mDismissingFromSplitPair = dismissingFromSplitPair;
    }

    public SplitAnimationController getSplitAnimationController() {
        return mSplitAnimationController;
    }

    /**
     * Requires Shell Transitions
     */
@@ -506,6 +525,7 @@ public class SplitSelectStateController {
        mItemInfo = null;
        mSplitEvent = null;
        mAnimateCurrentTaskDismissal = false;
        mDismissingFromSplitPair = false;
    }

    /**
@@ -532,6 +552,10 @@ public class SplitSelectStateController {
        return mInitialTaskId;
    }

    public int getSecondTaskId() {
        return mSecondTaskId;
    }

    private boolean isSecondTaskIntentSet() {
        return (mSecondTaskId != INVALID_TASK_ID || mSecondTaskIntent != null);
    }
+1 −1
Original line number Diff line number Diff line
@@ -500,7 +500,7 @@ public class DesktopTaskView extends TaskView {
    }

    @Override
    void setThumbnailVisibility(int visibility) {
    void setThumbnailVisibility(int visibility, int taskId) {
        for (int i = 0; i < mSnapshotViewMap.size(); i++) {
            mSnapshotViewMap.valueAt(i).setVisibility(visibility);
        }
+52 −9
Original line number Diff line number Diff line
package com.android.quickstep.views;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;

import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;

@@ -25,6 +27,7 @@ import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -267,6 +270,19 @@ public class GroupedTaskView extends TaskView {

    @Override
    protected int getLastSelectedChildTaskIndex() {
        SplitSelectStateController splitSelectController =
                getRecentsView().getSplitSelectController();
        if (splitSelectController.isDismissingFromSplitPair()) {
            // return the container index of the task that wasn't initially selected to split with
            // because that is the only remaining app that can be selected. The coordinate checks
            // below aren't reliable since both of those views may be gone/transformed
            int initSplitTaskId = getThisTaskCurrentlyInSplitSelection();
            if (initSplitTaskId != INVALID_TASK_ID) {
                return initSplitTaskId == mTask.key.id ? 1 : 0;
            }
        }

        // Check which of the two apps was selected
        if (isCoordInView(mIconView2, mLastTouchDownPosition)
                || isCoordInView(mSnapshotView2, mLastTouchDownPosition)) {
            return 1;
@@ -296,9 +312,30 @@ public class GroupedTaskView extends TaskView {
        if (mSplitBoundsConfig == null || mSnapshotView == null || mSnapshotView2 == null) {
            return;
        }
        int initSplitTaskId = getThisTaskCurrentlyInSplitSelection();
        if (initSplitTaskId == INVALID_TASK_ID) {
            getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
                    mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
                    mActivity.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL);
            // Should we be having a separate translation step apart from the measuring above?
            // The following only applies to large screen for now, but for future reference
            // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
            // translation directions
            mSnapshotView.applySplitSelectTranslateX(mSnapshotView.getTranslationX());
            mSnapshotView.applySplitSelectTranslateY(mSnapshotView.getTranslationY());
            mSnapshotView2.applySplitSelectTranslateX(mSnapshotView2.getTranslationX());
            mSnapshotView2.applySplitSelectTranslateY(mSnapshotView2.getTranslationY());
        } else {
            // Currently being split with this taskView, let the non-split selected thumbnail
            // take up full thumbnail area
            TaskIdAttributeContainer container =
                    mTaskIdAttributeContainer[initSplitTaskId == mTask.key.id ? 1 : 0];
            container.getThumbnailView().measure(widthMeasureSpec,
                    View.MeasureSpec.makeMeasureSpec(
                            heightSize -
                                    mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx,
                            MeasureSpec.EXACTLY));
        }
        updateIconPlacement();
    }

@@ -379,6 +416,12 @@ public class GroupedTaskView extends TaskView {
        mSnapshotView2.refreshSplashView();
    }

    @Override
    protected void resetViewTransforms() {
        super.resetViewTransforms();
        mSnapshotView2.resetViewTransforms();
    }

    /**
     * Sets visibility for thumbnails and associated elements (DWB banners).
     * IconView is unaffected.
@@ -387,13 +430,13 @@ public class GroupedTaskView extends TaskView {
     * When setting VISIBLE (as a reset), sets the visibility for both tasks.
     */
    @Override
    void setThumbnailVisibility(int visibility) {
    void setThumbnailVisibility(int visibility, int taskId) {
        if (visibility == VISIBLE) {
            mSnapshotView.setVisibility(visibility);
            mDigitalWellBeingToast.setBannerVisibility(visibility);
            mSnapshotView2.setVisibility(visibility);
            mDigitalWellBeingToast2.setBannerVisibility(visibility);
        } else if (getLastSelectedChildTaskIndex() == 0) {
        } else if (taskId == getTaskIds()[0]) {
            mSnapshotView.setVisibility(visibility);
            mDigitalWellBeingToast.setBannerVisibility(visibility);
        } else {
+53 −25
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitAnimationController.Companion.SplitAnimInitProps;
import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.SurfaceTransaction;
@@ -194,6 +195,7 @@ import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TaskVisualsChangeListener;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.VibrationConstants;
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -937,7 +939,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        if (mHandleTaskStackChanges) {
            TaskView taskView = getTaskViewByTaskId(taskId);
            if (taskView != null) {
                for (TaskView.TaskIdAttributeContainer container :
                for (TaskIdAttributeContainer container :
                        taskView.getTaskIdAttributeContainers()) {
                    if (container == null || taskId != container.getTask().key.id) {
                        continue;
@@ -3096,28 +3098,25 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T

        RectF startingTaskRect = new RectF();
        safeRemoveDragLayerView(mFirstFloatingTaskView);
        SplitAnimInitProps splitAnimInitProps =
                mSplitSelectStateController.getSplitAnimationController().getFirstAnimInitViews(
                        () -> mSplitHiddenTaskView, () -> mSplitSelectSource);
        if (mSplitSelectStateController.isAnimateCurrentTaskDismissal()) {
            // Create the split select animation from Overview
            mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE);
            anim.setViewAlpha(mSplitHiddenTaskView.getIconView(), 0, clampToProgress(LINEAR,
            mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE,
                    mSplitSelectStateController.getInitialTaskId());
            anim.setViewAlpha(splitAnimInitProps.getIconView(), 0, clampToProgress(LINEAR,
                    timings.getIconFadeStartOffset(),
                    timings.getIconFadeEndOffset()));
        }

        mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitHiddenTaskView.getThumbnail(),
                    mSplitHiddenTaskView.getThumbnail().getThumbnail(),
                    mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
            mFirstFloatingTaskView.setAlpha(1);
            mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
                    true /* fadeWithThumbnail */, true /* isStagedTask */);
        } else {
            // Create the split select animation from Home
            mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitSelectSource.view, null /* thumbnail */,
                    mSplitSelectSource.drawable, startingTaskRect);
                splitAnimInitProps.getOriginalView(),
                splitAnimInitProps.getOriginalBitmap(),
                splitAnimInitProps.getIconDrawable(), startingTaskRect);
        mFirstFloatingTaskView.setAlpha(1);
        mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
                    false /* fadeWithThumbnail */, true /* isStagedTask */);
        }
                splitAnimInitProps.getFadeWithThumbnail(), splitAnimInitProps.isStagedTask());

        // Allow user to click staged app to launch into fullscreen
        if (ENABLE_LAUNCH_FROM_STAGED_APP.get()) {
@@ -4447,7 +4446,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mTaskViewsSecondarySplitTranslation = translation;
        for (int i = 0; i < getTaskViewCount(); i++) {
            TaskView taskView = requireTaskViewAt(i);
            if (taskView == mSplitHiddenTaskView) {
            if (taskView == mSplitHiddenTaskView && !taskView.containsMultipleTasks()) {
                continue;
            }
            taskView.getSecondarySplitTranslationProperty().set(taskView, translation);
@@ -4499,6 +4498,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mSplitHiddenTaskViewIndex = indexOfChild(mSplitHiddenTaskView);
        mSplitSelectStateController
                .setAnimateCurrentTaskDismissal(splitSelectSource.animateCurrentTaskDismissal);

        // Prevent dismissing whole task if we're only initiating from one of 2 tasks in split pair
        mSplitSelectStateController.setDismissingFromSplitPair(mSplitHiddenTaskView != null
                && mSplitHiddenTaskView.containsMultipleTasks());
        mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
                splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
                splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
@@ -4517,8 +4520,32 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
     * Modifies a PendingAnimation with the animations for entering split staging
     */
    public void createSplitSelectInitAnimation(PendingAnimation builder, int duration) {
        if (mSplitSelectStateController.isAnimateCurrentTaskDismissal()) {
            // Splitting from Overview
        boolean isInitiatingSplitFromTaskView =
                mSplitSelectStateController.isAnimateCurrentTaskDismissal();
        boolean isInitiatingTaskViewSplitPair =
                mSplitSelectStateController.isDismissingFromSplitPair();
        if (isInitiatingSplitFromTaskView && isInitiatingTaskViewSplitPair) {
            // Splitting from Overview for split pair task
            createInitialSplitSelectAnimation(builder);

            // Animate pair thumbnail into full thumbnail
            boolean primaryTaskSelected =
                    mSplitHiddenTaskView.getTaskIdAttributeContainers()[0].getTask().key.id ==
                            mSplitSelectStateController.getInitialTaskId();
            TaskIdAttributeContainer taskIdAttributeContainer = mSplitHiddenTaskView
                    .getTaskIdAttributeContainers()[primaryTaskSelected ? 1 : 0];
            TaskThumbnailView thumbnail = taskIdAttributeContainer.getThumbnailView();
            mSplitSelectStateController.getSplitAnimationController()
                    .addInitialSplitFromPair(taskIdAttributeContainer, builder,
                            mActivity.getDeviceProfile(),
                            mSplitHiddenTaskView.getWidth(), mSplitHiddenTaskView.getHeight(),
                            primaryTaskSelected);
            builder.addOnFrameCallback(() ->{
                thumbnail.refreshSplashView();
                mSplitHiddenTaskView.updateSnapshotRadius();
            });
        } else if (isInitiatingSplitFromTaskView) {
            // Splitting from Overview for fullscreen task
            createTaskDismissAnimation(builder, mSplitHiddenTaskView, true, false, duration,
                    true /* dismissingForSplitSelection*/);
        } else {
@@ -4606,7 +4633,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T

        mSecondSplitHiddenView = containerTaskView;
        if (mSecondSplitHiddenView != null) {
            mSecondSplitHiddenView.setThumbnailVisibility(INVISIBLE);
            mSecondSplitHiddenView.setThumbnailVisibility(INVISIBLE,
                    mSplitSelectStateController.getSecondTaskId());
        }

        InteractionJankMonitorWrapper.begin(this,
@@ -4632,7 +4660,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        }

        if (mSecondSplitHiddenView != null) {
            mSecondSplitHiddenView.setThumbnailVisibility(VISIBLE);
            mSecondSplitHiddenView.setThumbnailVisibility(VISIBLE, INVALID_TASK_ID);
            mSecondSplitHiddenView = null;
        }

@@ -4658,7 +4686,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        resetTaskVisuals();
        mSplitHiddenTaskViewIndex = -1;
        if (mSplitHiddenTaskView != null) {
            mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE);
            mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE, INVALID_TASK_ID);
            mSplitHiddenTaskView = null;
        }
        if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
@@ -5528,7 +5556,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        }

        taskView.setShowScreenshot(true);
        for (TaskView.TaskIdAttributeContainer container :
        for (TaskIdAttributeContainer container :
                taskView.getTaskIdAttributeContainers()) {
            if (container == null) {
                continue;
Loading