Add a contentDescription to splitscreen's first staged task

Currently, when we stage the first app in a split, the floatingTaskView has no contentDescription and is announced by screen readers as "unlabeled".

This CL allows FloatingTaskView to copy a contentDescription from the underlying task or ItemInfo when it is created.

Also changes SplitConfigurationOptions#itemInfo to a private field with a public getter for mockito compatibility.

Fixes: 319783133
Test: Confirmed with TalkBack on Overview, contextual and Intent splits
Flag: EXEMPT bugfix
Change-Id: Ia5a95e403bfe8623e17d2ceac9073ef15c7bb476
This commit is contained in:
Jeremy Sim
2024-08-13 16:50:15 -07:00
parent 9df623644a
commit 2e59268f3b
6 changed files with 24 additions and 9 deletions
@@ -232,7 +232,7 @@ public class TaskbarUIController {
}
recentsView.getSplitSelectController().findLastActiveTasksAndRunCallback(
Collections.singletonList(splitSelectSource.itemInfo.getComponentKey()),
Collections.singletonList(splitSelectSource.getItemInfo().getComponentKey()),
false /* findExactPairMatch */,
foundTasks -> {
@Nullable Task foundTask = foundTasks[0];
@@ -729,7 +729,7 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
// Check if there is already an instance of this app running, if so, initiate the split
// using that.
mSplitSelectStateController.findLastActiveTasksAndRunCallback(
Collections.singletonList(splitSelectSource.itemInfo.getComponentKey()),
Collections.singletonList(splitSelectSource.getItemInfo().getComponentKey()),
false /* findExactPairMatch */,
foundTasks -> {
@Nullable Task foundTask = foundTasks[0];
@@ -756,7 +756,7 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
Rect tempRect = new Rect();
mSplitSelectStateController.setInitialTaskSelect(source.intent,
source.position.stagePosition, source.itemInfo, source.splitEvent,
source.position.stagePosition, source.getItemInfo(), source.splitEvent,
source.alreadyRunningTaskId);
RecentsView recentsView = getOverviewPanel();
@@ -774,6 +774,8 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
floatingTaskView.setOnClickListener(view ->
mSplitSelectStateController.getSplitAnimationController().
playAnimPlaceholderToFullscreen(this, view, Optional.empty()));
floatingTaskView.setContentDescription(source.getItemInfo().contentDescription);
mSplitSelectStateController.setFirstFloatingTaskView(floatingTaskView);
anim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -91,7 +91,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
val iconDrawable: Drawable,
val fadeWithThumbnail: Boolean,
val isStagedTask: Boolean,
val iconView: View?
val iconView: View?,
val contentDescription: CharSequence?
)
}
@@ -112,7 +113,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
splitSelectSource.drawable,
fadeWithThumbnail = false,
isStagedTask = true,
iconView = null
iconView = null,
splitSelectSource.itemInfo.contentDescription
)
} else if (splitSelectStateController.isDismissingFromSplitPair) {
// Initiating split from overview, but on a split pair
@@ -126,7 +128,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
drawable,
fadeWithThumbnail = true,
isStagedTask = true,
iconView = container.iconView.asView()
iconView = container.iconView.asView(),
container.task.titleDescription
)
}
}
@@ -145,7 +148,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
drawable,
fadeWithThumbnail = true,
isStagedTask = true,
iconView = it.iconView.asView()
iconView = it.iconView.asView(),
it.task.titleDescription
)
}
}
@@ -3447,6 +3447,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
mSplitSelectStateController.getSplitAnimationController().
playAnimPlaceholderToFullscreen(mContainer, view,
Optional.of(() -> resetFromSplitSelectionState())));
firstFloatingTaskView.setContentDescription(splitAnimInitProps.getContentDescription());
// SplitInstructionsView: animate in
safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
@@ -4880,7 +4881,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
mSplitSelectStateController.setDismissingFromSplitPair(mSplitHiddenTaskView != null
&& mSplitHiddenTaskView instanceof GroupedTaskView);
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
splitSelectSource.position.stagePosition, splitSelectSource.getItemInfo(),
splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
updateDesktopTaskVisibility(false /* visible */);
}
@@ -27,6 +27,7 @@ import android.view.View
import android.window.TransitionInfo
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.apppairs.AppPairIcon
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
import com.android.launcher3.taskbar.TaskbarActivityContext
@@ -76,6 +77,7 @@ class SplitAnimationControllerTest {
private val splitSelectSource: SplitConfigurationOptions.SplitSelectSource = mock()
private val mockSplitSourceDrawable: Drawable = mock()
private val mockSplitSourceView: View = mock()
private val mockItemInfo: ItemInfo = mock()
private val stateManager: StateManager<*, *> = mock()
private val depthController: DepthController = mock()
@@ -89,11 +91,13 @@ class SplitAnimationControllerTest {
whenever(mockTaskContainer.snapshotView).thenReturn(mockSnapshotView)
whenever(mockTaskContainer.splitAnimationThumbnail).thenReturn(mockBitmap)
whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
whenever(mockTaskContainer.task).thenReturn(mockTask)
whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)
whenever(mockTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer })
whenever(splitSelectSource.drawable).thenReturn(mockSplitSourceDrawable)
whenever(splitSelectSource.view).thenReturn(mockSplitSourceView)
whenever(splitSelectSource.itemInfo).thenReturn(mockItemInfo)
splitAnimationController = SplitAnimationController(mockSplitSelectStateController)
}
@@ -211,7 +211,7 @@ public final class SplitConfigurationOptions {
private Drawable drawable;
public final Intent intent;
public final SplitPositionOption position;
public final ItemInfo itemInfo;
private ItemInfo itemInfo;
public final StatsLogManager.EventEnum splitEvent;
/** Represents the taskId of the first app to start in split screen */
public int alreadyRunningTaskId = INVALID_TASK_ID;
@@ -239,5 +239,9 @@ public final class SplitConfigurationOptions {
public View getView() {
return view;
}
public ItemInfo getItemInfo() {
return itemInfo;
}
}
}