Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83ea6f71 authored by Winson Chung's avatar Winson Chung
Browse files

Fixing a few accessibility issues.

- Fixing issue with accessibility focus being incorrect when animating from home
- Fixing issue with accessibility focus being reset too aggressively when the
  list is scrolled
- Ensuring that recents handles forward/backwards scrolling

Bug: 19997561
Change-Id: I042666775862f4a20e8f22960e1f34e45fc5664e
parent 3aa16d76
Loading
Loading
Loading
Loading
+94 −38
Original line number Diff line number Diff line
@@ -22,10 +22,12 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
@@ -133,6 +135,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                }
            }
        });
        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
    }

    /** Sets the callbacks */
@@ -350,6 +353,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
            mTmpTaskViewMap.clear();
            List<TaskView> taskViews = getTaskViews();
            int taskViewCount = taskViews.size();
            boolean reaquireAccessibilityFocus = false;
            for (int i = taskViewCount - 1; i >= 0; i--) {
                TaskView tv = taskViews.get(i);
                Task task = tv.getTask();
@@ -358,6 +362,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                    mTmpTaskViewMap.put(task, tv);
                } else {
                    mViewPool.returnViewToPool(tv);
                    reaquireAccessibilityFocus |= (i == mPrevAccessibilityFocusedIndex);

                    // Hide the dismiss button if the front most task is invisible
                    if (task == mStack.getFrontMostTask()) {
@@ -402,9 +407,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal

                // Request accessibility focus on the next view if we removed the task
                // that previously held accessibility focus
                if (reaquireAccessibilityFocus) {
                    taskViews = getTaskViews();
                    taskViewCount = taskViews.size();
                if (taskViewCount > 0 && ssp.isTouchExplorationEnabled()) {
                    if (taskViewCount > 0 && ssp.isTouchExplorationEnabled() &&
                            mPrevAccessibilityFocusedIndex != -1) {
                        TaskView atv = taskViews.get(taskViewCount - 1);
                        int indexOfTask = mStack.indexOfTask(atv.getTask());
                        if (mPrevAccessibilityFocusedIndex != indexOfTask) {
@@ -413,6 +420,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                        }
                    }
                }
            }

            // Reset the request-synchronize params
            mStackViewsAnimationDuration = 0;
@@ -496,25 +504,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal

        if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
            mFocusedTaskIndex = taskIndex;
            mPrevAccessibilityFocusedIndex = taskIndex;

            // Focus the view if possible, otherwise, focus the view after we scroll into position
            Task t = mStack.getTasks().get(taskIndex);
            TaskView tv = getChildViewForTask(t);
            Runnable postScrollRunnable = null;
            if (tv != null) {
                tv.setFocusedTask(animateFocusedState);
            } else {
                postScrollRunnable = new Runnable() {
            final Task t = mStack.getTasks().get(mFocusedTaskIndex);
            Runnable postScrollRunnable = new Runnable() {
                @Override
                public void run() {
                        Task t = mStack.getTasks().get(mFocusedTaskIndex);
                    TaskView tv = getChildViewForTask(t);
                    if (tv != null) {
                        tv.setFocusedTask(animateFocusedState);
                        tv.requestAccessibilityFocus();
                    }
                }
            };
            }

            // Scroll the view into position (just center it in the curve)
            if (scrollToNewPosition) {
@@ -534,25 +537,30 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
     * Ensures that there is a task focused, if nothing is focused, then we will use the task
     * at the center of the visible stack.
     */
    public boolean ensureFocusedTask() {
    public boolean ensureFocusedTask(boolean findClosestToCenter) {
        if (mFocusedTaskIndex < 0) {
            List<TaskView> taskViews = getTaskViews();
            int taskViewCount = taskViews.size();
            if (findClosestToCenter) {
                // If there is no task focused, then find the task that is closes to the center
                // of the screen and use that as the currently focused task
                int x = mLayoutAlgorithm.mStackVisibleRect.centerX();
                int y = mLayoutAlgorithm.mStackVisibleRect.centerY();
            List<TaskView> taskViews = getTaskViews();
            int taskViewCount = taskViews.size();
                for (int i = taskViewCount - 1; i >= 0; i--) {
                    TaskView tv = taskViews.get(i);
                    tv.getHitRect(mTmpRect);
                    if (mTmpRect.contains(x, y)) {
                        mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
                        mPrevAccessibilityFocusedIndex = mFocusedTaskIndex;
                        break;
                    }
                }
            }
            // If we can't find the center task, then use the front most index
            if (mFocusedTaskIndex < 0 && taskViewCount > 0) {
                mFocusedTaskIndex = taskViewCount - 1;
                TaskView tv = taskViews.get(taskViewCount - 1);
                mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
                mPrevAccessibilityFocusedIndex = mFocusedTaskIndex;
            }
        }
        return mFocusedTaskIndex >= 0;
@@ -600,6 +608,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
            }
        }
        mFocusedTaskIndex = -1;
        mPrevAccessibilityFocusedIndex = -1;
    }

    @Override
@@ -619,6 +628,53 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
        event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP));
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        if (taskViewCount > 1 && mPrevAccessibilityFocusedIndex != -1) {
            info.setScrollable(true);
            if (mPrevAccessibilityFocusedIndex > 0) {
                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            }
            if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
            }
        }
    }

    @Override
    public CharSequence getAccessibilityClassName() {
        return TaskStackView.class.getName();
    }

    @Override
    public boolean performAccessibilityAction(int action, Bundle arguments) {
        if (super.performAccessibilityAction(action, arguments)) {
            return true;
        }
        if (ensureFocusedTask(false)) {
            switch (action) {
                case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
                    if (mPrevAccessibilityFocusedIndex > 0) {
                        focusNextTask(true, false);
                        return true;
                    }
                }
                break;
                case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
                    if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
                        focusNextTask(false, false);
                        return true;
                    }
                }
                break;
            }
        }
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mTouchHandler.onInterceptTouchEvent(ev);
+2 −2
Original line number Diff line number Diff line
@@ -396,11 +396,11 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                    // Find the front most task and scroll the next task to the front
                    float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
                    if (vScroll > 0) {
                        if (mSv.ensureFocusedTask()) {
                        if (mSv.ensureFocusedTask(true)) {
                            mSv.focusNextTask(true, false);
                        }
                    } else {
                        if (mSv.ensureFocusedTask()) {
                        if (mSv.ensureFocusedTask(true)) {
                            mSv.focusNextTask(false, false);
                        }
                    }