diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index 8c4ba97c07..cbdbdb5571 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -72,7 +72,13 @@ public interface TaskShortcutFactory { @Override public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskIdAttributeContainer taskContainer) { - return new AppInfo(activity, taskContainer.getItemInfo()); + TaskView taskView = taskContainer.getTaskView(); + AppInfo.SplitAccessibilityInfo accessibilityInfo = + new AppInfo.SplitAccessibilityInfo(taskView.containsMultipleTasks(), + TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()), + taskContainer.getA11yNodeId() + ); + return new AppInfo(activity, taskContainer.getItemInfo(), accessibilityInfo); } @Override diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 7778813200..e8077cf4a5 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -30,6 +30,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; +import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -38,6 +39,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.annotation.IdRes; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; @@ -1304,10 +1306,14 @@ public class TaskView extends FrameLayout implements Reusable { getContext().getText(R.string.accessibility_close))); final Context context = getContext(); - // TODO(b/200609838) Determine which task to run A11y action on when in split screen - for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, - mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) { - info.addAction(s.createAccessibilityAction(context)); + for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) { + if (taskContainer == null) { + continue; + } + for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, + mActivity.getDeviceProfile(), taskContainer)) { + info.addAction(s.createAccessibilityAction(context)); + } } if (mDigitalWellBeingToast.hasLimit()) { @@ -1338,12 +1344,16 @@ public class TaskView extends FrameLayout implements Reusable { return true; } - // TODO(b/200609838) Determine which task to run A11y action on when in split screen - for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, - mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) { - if (s.hasHandlerForAction(action)) { - s.onClick(this); - return true; + for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) { + if (taskContainer == null) { + continue; + } + for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, + mActivity.getDeviceProfile(), taskContainer)) { + if (s.hasHandlerForAction(action)) { + s.onClick(this); + return true; + } } } @@ -1560,7 +1570,6 @@ public class TaskView extends FrameLayout implements Reusable { mScale = previewWidth / (previewWidth + currentInsetsLeft + currentInsetsRight); } } - } public class TaskIdAttributeContainer { @@ -1569,6 +1578,8 @@ public class TaskView extends FrameLayout implements Reusable { private final IconView mIconView; /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */ private @SplitConfigurationOptions.StagePosition int mStagePosition; + @IdRes + private final int mA11yNodeId; public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView, IconView iconView, int stagePosition) { @@ -1576,6 +1587,8 @@ public class TaskView extends FrameLayout implements Reusable { this.mThumbnailView = thumbnailView; this.mIconView = iconView; this.mStagePosition = stagePosition; + this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ? + R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo; } public TaskThumbnailView getThumbnailView() { @@ -1605,5 +1618,9 @@ public class TaskView extends FrameLayout implements Reusable { void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) { this.mStagePosition = stagePosition; } + + public int getA11yNodeId() { + return mA11yNodeId; + } } } diff --git a/res/values/id.xml b/res/values/id.xml index ebc4075214..508caffd48 100644 --- a/res/values/id.xml +++ b/res/values/id.xml @@ -21,6 +21,10 @@ + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 5f53d4e24a..868b5f39b8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -40,9 +40,10 @@ Split screen - Split top - Split left - Split right + Split top + Split left + Split right + App info for %1$s diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 826c79b289..af872750a0 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -41,8 +41,8 @@ public abstract class SystemShortcut extend implements View.OnClickListener { private final int mIconResId; - private final int mLabelResId; - private final int mAccessibilityActionId; + protected final int mLabelResId; + protected int mAccessibilityActionId; protected final T mTarget; protected final ItemInfo mItemInfo; @@ -139,11 +139,43 @@ public abstract class SystemShortcut extend public static class AppInfo extends SystemShortcut { + @Nullable + private SplitAccessibilityInfo mSplitA11yInfo; + public AppInfo(T target, ItemInfo itemInfo) { super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target, itemInfo); } + /** + * Constructor used by overview for staged split to provide custom A11y information. + * + * Future improvements considerations: + * Have the logic in {@link #createAccessibilityAction(Context)} be moved to super + * call in {@link SystemShortcut#createAccessibilityAction(Context)} by having + * SystemShortcut be aware of TaskContainers and staged split. + * That way it could directly create the correct node info for any shortcut that supports + * split, but then we'll need custom resIDs for each pair of shortcuts. + */ + public AppInfo(T target, ItemInfo itemInfo, SplitAccessibilityInfo accessibilityInfo) { + this(target, itemInfo); + mSplitA11yInfo = accessibilityInfo; + mAccessibilityActionId = accessibilityInfo.nodeId; + } + + @Override + public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction( + Context context) { + if (mSplitA11yInfo != null && mSplitA11yInfo.containsMultipleTasks) { + String accessibilityLabel = context.getString(R.string.split_app_info_accessibility, + mSplitA11yInfo.taskTitle); + return new AccessibilityNodeInfo.AccessibilityAction(mAccessibilityActionId, + accessibilityLabel); + } else { + return super.createAccessibilityAction(context); + } + } + @Override public void onClick(View view) { dismissTaskMenuView(mTarget); @@ -153,6 +185,19 @@ public abstract class SystemShortcut extend mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP); } + + public static class SplitAccessibilityInfo { + public final boolean containsMultipleTasks; + public final CharSequence taskTitle; + public final int nodeId; + + public SplitAccessibilityInfo(boolean containsMultipleTasks, + CharSequence taskTitle, int nodeId) { + this.containsMultipleTasks = containsMultipleTasks; + this.taskTitle = taskTitle; + this.nodeId = nodeId; + } + } } public static final Factory INSTALL = (activity, itemInfo) -> {