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

Commit 72810404 authored by Tony Huang's avatar Tony Huang
Browse files

Revert "Fix broken a11y function"

This reverts commit f6bf0054.
Revert this because previous code can work in current build.

Bug: 144819035
Test: atest DocumentsUIGoogleTests
Change-Id: I8d482ab495ce5c1d6a1302d09f79fc155e999de5
parent f83ebd5d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@
                android:id="@+id/horizontal_breadcrumb"
                android:layout_marginRight="20dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
                android:layout_height="match_parent" />

        </androidx.appcompat.widget.Toolbar>

+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:duplicateParentState="true"
        android:textAppearance="@style/ToolbarTitle"
        android:textAppearance="@android:style/TextAppearance.Material.Widget.ActionBar.Title"
        android:background="@drawable/breadcrumb_item_background" />

    <ImageView
+10 −12
Original line number Diff line number Diff line
@@ -71,8 +71,15 @@ public final class HorizontalBreadcrumb extends RecyclerView
        mLayoutManager = new LinearLayoutManager(
                getContext(), LinearLayoutManager.HORIZONTAL, false);
        mAdapter = new BreadcrumbAdapter(
                state, env, new ItemDragListener<>(this), this::onKey,
                new AccessibilityEventRouter(this::onAccessibilityClick, null));
                state, env, new ItemDragListener<>(this), this::onKey);
        // Since we are using GestureDetector to detect click events, a11y services don't know which
        // views are clickable because we aren't using View.OnClickListener. Thus, we need to use a
        // custom accessibility delegate to route click events correctly.
        // See AccessibilityClickEventRouter for more details on how we are routing these a11y
        // events.
        setAccessibilityDelegateCompat(
                new AccessibilityEventRouter(this,
                        (View child) -> onAccessibilityClick(child), null));

        setLayoutManager(mLayoutManager);
        addOnItemTouchListener(new ClickListener(getContext(), this::onSingleTapUp));
@@ -186,20 +193,17 @@ public final class HorizontalBreadcrumb extends RecyclerView
        private final com.android.documentsui.base.State mState;
        private final OnDragListener mDragListener;
        private final View.OnKeyListener mClickListener;
        private final View.AccessibilityDelegate mAccessibilityDelegate;
        // We keep the old item size so the breadcrumb will only re-render views that are necessary
        private int mLastItemSize;

        public BreadcrumbAdapter(com.android.documentsui.base.State state,
                Environment env,
                OnDragListener dragListener,
                View.OnKeyListener clickListener,
                View.AccessibilityDelegate accessibilityDelegate) {
                View.OnKeyListener clickListener) {
            mState = state;
            mEnv = env;
            mDragListener = dragListener;
            mClickListener = clickListener;
            mAccessibilityDelegate = accessibilityDelegate;
            mLastItemSize = mState.stack.size();
        }

@@ -232,12 +236,6 @@ public final class HorizontalBreadcrumb extends RecyclerView
            }
            holder.itemView.setOnDragListener(mDragListener);
            holder.itemView.setOnKeyListener(mClickListener);
            // Since we are using GestureDetector to detect click events, a11y services don't know
            // which views are clickable because we aren't using View.OnClickListener. Thus, we
            // need to use a custom accessibility delegate to route click events correctly.
            // See AccessibilityClickEventRouter for more details on how we are routing these
            // a11y events.
            holder.itemView.setAccessibilityDelegate(mAccessibilityDelegate);
        }

        private DocumentInfo getItem(int position) {
+44 −22
Original line number Diff line number Diff line
@@ -18,15 +18,19 @@ package com.android.documentsui.dirlist;

import android.os.Bundle;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.AccessibilityDelegateCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;

import java.util.function.Function;

/**
 * Custom Accessibility Delegate for item views in RecyclerViews to route click events to
 * Custom Accessibility Delegate for RecyclerViews to route click events on its child views to
 * proper handlers, and to surface selection state to a11y events.
 * <p>
 * The majority of event handling isdone using TouchDetector instead of View.OnCLickListener, which
@@ -39,41 +43,59 @@ import java.util.function.Function;
 * for marking a view as selected. We will surface that selection state to a11y services in this
 * class.
 */
public class AccessibilityEventRouter extends View.AccessibilityDelegate {
public class AccessibilityEventRouter extends RecyclerViewAccessibilityDelegate {

    private final ItemDelegate mItemDelegate;
    private final Function<View, Boolean> mClickCallback;
    private final Function<View, Boolean> mLongClickCallback;

    public AccessibilityEventRouter(
            @NonNull Function<View, Boolean> clickCallback,
            RecyclerView recyclerView, @NonNull Function<View, Boolean> clickCallback,
            @Nullable Function<View, Boolean> longClickCallback) {
        super();
        super(recyclerView);
        mClickCallback = clickCallback;
        mLongClickCallback = longClickCallback;
    }

        mItemDelegate = new ItemDelegate(this) {
            @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
            public void onInitializeAccessibilityNodeInfo(View host,
                    AccessibilityNodeInfoCompat info) {
                super.onInitializeAccessibilityNodeInfo(host, info);
                final RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(host);
                // if the viewHolder is a DocumentsHolder instance and the ItemDetails
                // is null, it can't be clicked
                if (holder instanceof DocumentHolder) {
                    if (((DocumentHolder) holder).getItemDetails() != null) {
                        addAction(info);
                    }
                } else {
                    addAction(info);
                }
                info.setSelected(host.isActivated());
            }

            @Override
            public boolean performAccessibilityAction(View host, int action, Bundle args) {
                // We are only handling click events; route all other to default implementation
        if (action == AccessibilityNodeInfo.ACTION_CLICK) {
                if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
                    return mClickCallback.apply(host);
        } else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK
                } else if (action == AccessibilityNodeInfoCompat.ACTION_LONG_CLICK
                        && mLongClickCallback != null) {
                    return mLongClickCallback.apply(host);
                }
                return super.performAccessibilityAction(host, action, args);
            }
        };
    }

    @Override
    public AccessibilityDelegateCompat getItemDelegate() {
        return mItemDelegate;
    }

    private void addAction(AccessibilityNodeInfo info) {
        info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
    private void addAction(AccessibilityNodeInfoCompat info) {
        info.addAction(AccessibilityActionCompat.ACTION_CLICK);
        if (mLongClickCallback != null) {
            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
            info.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK);
        }
    }
}
 No newline at end of file
+4 −4
Original line number Diff line number Diff line
@@ -331,6 +331,10 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
        mFocusManager = mInjector.getFocusManager(mRecView, mModel);
        mActions = mInjector.getActionHandler(mContentLock);

        mRecView.setAccessibilityDelegateCompat(
                new AccessibilityEventRouter(mRecView,
                        (View child) -> onAccessibilityClick(child),
                        (View child) -> onAccessibilityLongClick(child)));
        mSelectionMetadata = new SelectionMetadata(mModel::getItem);
        mDetailsLookup = new DocsItemDetailsLookup(mRecView);

@@ -1290,10 +1294,6 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
        @Override
        public void onBindDocumentHolder(DocumentHolder holder, Cursor cursor) {
            setupDragAndDropOnDocumentView(holder.itemView, cursor);
            holder.itemView.setAccessibilityDelegate(new AccessibilityEventRouter(
                    DirectoryFragment.this::onAccessibilityClick,
                    DirectoryFragment.this::onAccessibilityLongClick
            ));
        }

        @Override
Loading