Fixing several issues with accessibility

- Only reset the focused task if the task that we removed actually had 
  accessibility focus.
- Only reset the focused task on scroll if we are not in touch 
  exploration mode
- Ensure the focused view has accessibility focus when entering recents
  in touch exploration mode
- Instead of using the focused task, query for the accessibility focused
  task view when setting the focused task in response to the scroll 
  gesture.  In addition, use this accessibility focused task to 
  determine whether we need to add the accessibility actions
- No longer explicitly requesting accessibility focus on view focus
- Removing some unused code

Bug: 29046351
Change-Id: I5701a408bd919e47990f0d2fc6e4686eb9530d8e
This commit is contained in:
Winson
2016-06-01 12:22:55 -07:00
parent 9675f16bba
commit f00098805c
4 changed files with 88 additions and 55 deletions

View File

@@ -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;
@@ -284,6 +285,26 @@ public class Utilities {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
/**
* 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.

View File

@@ -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());

View File

@@ -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());

View File

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