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

This commit is contained in:
Vinit Nayak
2023-04-03 14:58:29 +00:00
committed by Android (Google) Code Review
4 changed files with 198 additions and 9 deletions

View File

@@ -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 */);

View File

@@ -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

View File

@@ -0,0 +1,165 @@
/*
* 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)
}
}

View File

@@ -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;
}
}
}