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

Commit 3e5b2122 authored by Vinit Nayak's avatar Vinit Nayak Committed by Automerger Merge Worker
Browse files

Merge "Default to using SplitSelectSource drawable if TaskView icon drawable...

Merge "Default to using SplitSelectSource drawable if TaskView icon drawable is null" into tm-qpr-dev am: 8e307ba5

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/22347415



Change-Id: I9fe261fdaa96ab8d5a0792a3d69cb201beebdb9a
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 240885e2 8e307ba5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -639,7 +639,7 @@ public class QuickstepLauncher extends Launcher {
        PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
        RectF startingTaskRect = new RectF();
        final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(this,
                source.view, null /* thumbnail */, source.drawable, startingTaskRect);
                source.getView(), null /* thumbnail */, source.getDrawable(), startingTaskRect);
        floatingTaskView.setAlpha(1);
        floatingTaskView.addStagingAnimation(anim, startingTaskRect, tempRect,
                false /* fadeWithThumbnail */, true /* isStagedTask */);
+22 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ 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.IconView
import com.android.quickstep.views.TaskThumbnailView
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
@@ -52,21 +53,22 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
     * depending on the state of the surface from which the split was initiated
     */
    fun getFirstAnimInitViews(taskViewSupplier: Supplier<TaskView>,
                              splitSelectSourceSupplier: Supplier<SplitSelectSource>)
                              splitSelectSourceSupplier: Supplier<SplitSelectSource?>)
            : SplitAnimInitProps {
        val splitSelectSource = splitSelectSourceSupplier.get()
        if (!splitSelectStateController.isAnimateCurrentTaskDismissal) {
            // Initiating from home
            val splitSelectSource = splitSelectSourceSupplier.get()
            return SplitAnimInitProps(splitSelectSource.view, originalBitmap = null,
            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) {
                if (container.task.getKey().getId() == splitSelectStateController.initialTaskId) {
                    val drawable = getDrawable(container.iconView, splitSelectSource)
                    return SplitAnimInitProps(container.thumbnailView,
                            container.thumbnailView.thumbnail, container.iconView.drawable!!,
                            container.thumbnailView.thumbnail, drawable!!,
                            fadeWithThumbnail = true, isStagedTask = true,
                            iconView = container.iconView
                    )
@@ -77,13 +79,27 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
        } else {
            // Initiating split from overview on fullscreen task TaskView
            val taskView = taskViewSupplier.get()
            val drawable = getDrawable(taskView.iconView, splitSelectSource)
            return SplitAnimInitProps(taskView.thumbnail, taskView.thumbnail.thumbnail,
                    taskView.iconView.drawable!!, fadeWithThumbnail = true, isStagedTask = true,
                    drawable!!, fadeWithThumbnail = true, isStagedTask = true,
                    taskView.iconView
            )
        }
    }

    /**
     * Returns the drawable that's provided in iconView, however if that
     * is null it falls back to the drawable that's in splitSelectSource.
     * TaskView's icon drawable can be null if the TaskView is scrolled far enough off screen
     * @return [Drawable]
     */
    fun getDrawable(iconView: IconView, splitSelectSource: SplitSelectSource?) : Drawable? {
        if (iconView.drawable == null && splitSelectSource != null) {
            return splitSelectSource.drawable
        }
        return iconView.drawable
    }

    /**
     * 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
+165 −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.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.quickstep.views.GroupedTaskView
import com.android.quickstep.views.IconView
import com.android.quickstep.views.TaskThumbnailView
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
import com.android.systemui.shared.recents.model.Task
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever

@RunWith(AndroidJUnit4::class)
class SplitAnimationControllerTest {

    private val taskId = 9

    @Mock lateinit var mockSplitSelectStateController: SplitSelectStateController
    // TaskView
    @Mock lateinit var mockTaskView: TaskView
    @Mock lateinit var mockThumbnailView: TaskThumbnailView
    @Mock lateinit var mockBitmap: Bitmap
    @Mock lateinit var mockIconView: IconView
    @Mock lateinit var mockTaskViewDrawable: Drawable
    // GroupedTaskView
    @Mock lateinit var mockGroupedTaskView: GroupedTaskView
    @Mock lateinit var mockTask: Task
    @Mock lateinit var mockTaskKey: Task.TaskKey
    @Mock lateinit var mockTaskIdAttributeContainer: TaskIdAttributeContainer

    // SplitSelectSource
    @Mock lateinit var splitSelectSource: SplitConfigurationOptions.SplitSelectSource
    @Mock lateinit var mockSplitSourceDrawable: Drawable
    @Mock lateinit var mockSplitSourceView: View

    lateinit var splitAnimationController: SplitAnimationController

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)

        whenever(mockTaskView.thumbnail).thenReturn(mockThumbnailView)
        whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
        whenever(mockTaskView.iconView).thenReturn(mockIconView)
        whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)

        whenever(splitSelectSource.drawable).thenReturn(mockSplitSourceDrawable)
        whenever(splitSelectSource.view).thenReturn(mockSplitSourceView)

        splitAnimationController = SplitAnimationController(mockSplitSelectStateController)
    }

    @Test
    fun getFirstAnimInitViews_nullTaskViewIcon_useSplitSourceIcon() {
        // Hit fullscreen task dismissal state
        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)

        // Missing taskView icon
        whenever(mockIconView.drawable).thenReturn(null)

        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
                splitAnimationController.getFirstAnimInitViews(
                        { mockTaskView }, { splitSelectSource })

        assertEquals("Did not fallback to use splitSource icon drawable",
                mockSplitSourceDrawable, splitAnimInitProps.iconDrawable)
    }

    @Test
    fun getFirstAnimInitViews_validTaskViewIcon_useTaskViewIcon() {
        // Hit fullscreen task dismissal state
        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)

        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
                splitAnimationController.getFirstAnimInitViews(
                        { mockTaskView }, { splitSelectSource })

        assertEquals("Did not use taskView icon drawable", mockTaskViewDrawable,
                splitAnimInitProps.iconDrawable)
    }

    @Test
    fun getFirstAnimInitViews_validTaskViewNullSplitSource_useTaskViewIcon() {
        // Hit fullscreen task dismissal state
        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)

        // Set split source to null
        whenever(splitSelectSource.drawable).thenReturn(null)

        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
                splitAnimationController.getFirstAnimInitViews(
                        { mockTaskView }, { splitSelectSource })

        assertEquals("Did not use taskView icon drawable", mockTaskViewDrawable,
                splitAnimInitProps.iconDrawable)
    }

    @Test
    fun getFirstAnimInitViews_nullTaskViewValidSplitSource_noTaskDismissal() {
        // Hit initiating split from home
        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(false)
        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)

        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
                splitAnimationController.getFirstAnimInitViews(
                        { mockTaskView }, { splitSelectSource })

        assertEquals("Did not use splitSource icon drawable", mockSplitSourceDrawable,
                splitAnimInitProps.iconDrawable)
    }

    @Test
    fun getFirstAnimInitViews_nullTaskViewValidSplitSource_groupedTaskView() {
        // Hit groupedTaskView dismissal
        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(true)

        // Remove icon view from GroupedTaskView
        whenever(mockIconView.drawable).thenReturn(null)

        whenever(mockTaskIdAttributeContainer.task).thenReturn(mockTask)
        whenever(mockTaskIdAttributeContainer.iconView).thenReturn(mockIconView)
        whenever(mockTaskIdAttributeContainer.thumbnailView).thenReturn(mockThumbnailView)
        whenever(mockTask.getKey()).thenReturn(mockTaskKey)
        whenever(mockTaskKey.getId()).thenReturn(taskId)
        whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)
        whenever(mockGroupedTaskView.taskIdAttributeContainers)
                .thenReturn(Array(1) { mockTaskIdAttributeContainer })
        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
                splitAnimationController.getFirstAnimInitViews(
                        { mockGroupedTaskView }, { splitSelectSource })

        assertEquals("Did not use splitSource icon drawable", mockSplitSourceDrawable,
                splitAnimInitProps.iconDrawable)
    }
}
 No newline at end of file
+10 −2
Original line number Diff line number Diff line
@@ -200,8 +200,8 @@ public final class SplitConfigurationOptions {
        /** Keep in sync w/ ActivityTaskManager#INVALID_TASK_ID (unreference-able) */
        private static final int INVALID_TASK_ID = -1;

        public final View view;
        public final Drawable drawable;
        private View view;
        private Drawable drawable;
        public final Intent intent;
        public final SplitPositionOption position;
        public final ItemInfo itemInfo;
@@ -224,5 +224,13 @@ public final class SplitConfigurationOptions {
            this.itemInfo = itemInfo;
            this.splitEvent = splitEvent;
        }

        public Drawable getDrawable() {
            return drawable;
        }

        public View getView() {
            return view;
        }
    }
}