diff options
4 files changed, 88 insertions, 55 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index 9fb8bd557b90..2c5c437bfab0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -34,6 +34,7 @@ import android.util.IntProperty; import android.util.Property; import android.util.TypedValue; import android.view.View; +import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewStub; @@ -285,6 +286,26 @@ public class Utilities { } /** + * Returns whether this view, or one of its descendants have accessibility focus. + */ + public static boolean isDescendentAccessibilityFocused(View v) { + if (v.isAccessibilityFocused()) { + return true; + } + + if (v instanceof ViewGroup) { + ViewGroup vg = (ViewGroup) v; + int childCount = vg.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (isDescendentAccessibilityFocused(vg.getChildAt(i))) { + return true; + } + } + } + return false; + } + + /** * Returns the application configuration, which is independent of the activity's current * configuration in multiwindow. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 231360e46ae9..586a8bcd8920 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -44,6 +44,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import android.widget.ScrollView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; @@ -170,7 +171,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @ViewDebug.ExportedProperty(category="recents") private boolean mEnterAnimationComplete = false; @ViewDebug.ExportedProperty(category="recents") - private boolean mTouchExplorationEnabled; + boolean mTouchExplorationEnabled; @ViewDebug.ExportedProperty(category="recents") boolean mScreenPinningEnabled; @@ -579,7 +580,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (task.isFreeformTask() || (transform != null && transform.visible)) { mTmpTaskViewMap.put(task.key, tv); } else { - if (mTouchExplorationEnabled) { + if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) { lastFocusedTaskIndex = taskIndex; resetFocusedTask(task); } @@ -630,12 +631,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Update the focus if the previous focused task was returned to the view pool if (lastFocusedTaskIndex != -1) { - if (lastFocusedTaskIndex < visibleTaskRange[1]) { - setFocusedTask(visibleTaskRange[1], false /* scrollToTask */, - true /* requestViewFocus */); - } else { - setFocusedTask(visibleTaskRange[0], false /* scrollToTask */, - true /* requestViewFocus */); + int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1]) + ? visibleTaskRange[1] + : visibleTaskRange[0]; + setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */, + true /* requestViewFocus */); + TaskView focusedTaskView = getChildViewForTask(mFocusedTask); + if (focusedTaskView != null) { + focusedTaskView.requestAccessibilityFocus(); } } } @@ -938,24 +941,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * focus. */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) { - setRelativeFocusedTask(forward, stackTasksOnly, animated, false); - } - - /** - * Sets the focused task relative to the currently focused task. - * - * @param forward whether to go to the next task in the stack (along the curve) or the previous - * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and - * if the currently focused task is not a stack task, will set the focus - * to the first visible stack task - * @param animated determines whether to actually draw the highlight along with the change in - * focus. - * @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll - * happens. - */ - public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated, - boolean cancelWindowAnimations) { - setRelativeFocusedTask(forward, stackTasksOnly, animated, cancelWindowAnimations, 0); + setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0); } /** @@ -972,13 +958,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated, - boolean cancelWindowAnimations, - int timerIndicatorDuration) { - int newIndex = mStack.indexOfStackTask(mFocusedTask); - if (mFocusedTask != null) { + boolean cancelWindowAnimations, int timerIndicatorDuration) { + Task focusedTask = getFocusedTask(); + int newIndex = mStack.indexOfStackTask(focusedTask); + if (focusedTask != null) { if (stackTasksOnly) { List<Task> tasks = mStack.getStackTasks(); - if (mFocusedTask.isFreeformTask()) { + if (focusedTask.isFreeformTask()) { // Try and focus the front most stack task TaskView tv = getFrontMostTaskView(stackTasksOnly); if (tv != null) { @@ -1054,6 +1040,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal return mFocusedTask; } + /** + * Returns the accessibility focused task. + */ + Task getAccessibilityFocusedTask() { + List<TaskView> taskViews = getTaskViews(); + int taskViewCount = taskViews.size(); + for (int i = 0; i < taskViewCount; i++) { + TaskView tv = taskViews.get(i); + if (Utilities.isDescendentAccessibilityFocused(tv)) { + return tv.getTask(); + } + } + TaskView frontTv = getFrontMostTaskView(true /* stackTasksOnly */); + if (frontTv != null) { + return frontTv.getTask(); + } + return null; + } + @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); @@ -1078,21 +1083,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal super.onInitializeAccessibilityNodeInfo(info); List<TaskView> taskViews = getTaskViews(); int taskViewCount = taskViews.size(); - if (taskViewCount > 1 && mFocusedTask != null) { + if (taskViewCount > 1) { + // Find the accessibility focused task + Task focusedTask = getAccessibilityFocusedTask(); info.setScrollable(true); - int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask); + int focusedTaskIndex = mStack.indexOfStackTask(focusedTask); if (focusedTaskIndex > 0) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); - } - if (focusedTaskIndex < mStack.getTaskCount() - 1) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); } + if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + } } } @Override public CharSequence getAccessibilityClassName() { - return TaskStackView.class.getName(); + return ScrollView.class.getName(); } @Override @@ -1100,14 +1107,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (super.performAccessibilityAction(action, arguments)) { return true; } - switch (action) { - case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { - setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */); - return true; - } - case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { - setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */); - return true; + Task focusedTask = getAccessibilityFocusedTask(); + int taskIndex = mStack.indexOfStackTask(focusedTask); + if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) { + switch (action) { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */, + 0); + return true; + } + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */, + 0); + return true; + } } } return false; @@ -1489,6 +1502,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal unbindTaskView(tv, task); // Reset the view properties and view state + tv.clearAccessibilityFocus(); tv.resetViewProperties(); tv.setFocusedState(false, false /* requestViewFocus */); tv.setClipViewInStack(false); @@ -1949,6 +1963,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal RecentsActivityLaunchState launchState = config.getLaunchState(); setFocusedTask(mStack.indexOfStackTask(mFocusedTask), false /* scrollToTask */, launchState.launchedWithAltTab); + TaskView focusedTaskView = getChildViewForTask(mFocusedTask); + if (mTouchExplorationEnabled && focusedTaskView != null) { + focusedTaskView.requestAccessibilityFocus(); + } } EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java index b554a467c7ce..67a2595c90cd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -343,7 +343,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { } // Reset the focused task after the user has scrolled - mSv.resetFocusedTask(mSv.getFocusedTask()); + if (!mSv.mTouchExplorationEnabled) { + mSv.resetFocusedTask(mSv.getFocusedTask()); + } } else if (mActiveTaskView == null) { // This tap didn't start on a task. maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 612c41d07a04..4ecdd7788001 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -133,8 +133,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @ViewDebug.ExportedProperty(deepExport=true, prefix="task_") private Task mTask; @ViewDebug.ExportedProperty(category="recents") - private boolean mTaskDataLoaded; - @ViewDebug.ExportedProperty(category="recents") private boolean mClipViewInStack = true; @ViewDebug.ExportedProperty(category="recents") private boolean mTouchExplorationEnabled; @@ -451,16 +449,12 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks * Explicitly sets the focused state of this task. */ public void setFocusedState(boolean isFocused, boolean requestViewFocus) { - SystemServicesProxy ssp = Recents.getSystemServices(); if (isFocused) { if (requestViewFocus && !isFocused()) { requestFocus(); } - if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { - requestAccessibilityFocus(); - } } else { - if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { + if (isAccessibilityFocused() && mTouchExplorationEnabled) { clearAccessibilityFocus(); } } @@ -622,7 +616,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks // Update each of the views to the new task data mThumbnailView.onTaskDataLoaded(thumbnailInfo); mHeaderView.onTaskDataLoaded(); - mTaskDataLoaded = true; } @Override @@ -631,7 +624,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mTask.removeCallback(this); mThumbnailView.unbindFromTask(); mHeaderView.unbindFromTask(mTouchExplorationEnabled); - mTaskDataLoaded = false; } @Override |