Add RTL support for A11yMenu ViewPager.

When in RTL languages, reverses the direction of the left & right buttons.
Demonstration video: https://x20web.corp.google.com/users/jo/jonesriley/fabFootage/viewPager2.mp4

Bug: 279191187
Flag: EXEMPT internal refactoring
Test: atest A11yMenuServiceTests
Change-Id: I9626f504a444928d717f3f9b03600d7058203c78
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index c881e07..c60eb61 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -36,7 +36,7 @@
         "androidx.coordinatorlayout_coordinatorlayout",
         "androidx.core_core",
         "androidx.preference_preference",
-        "androidx.viewpager_viewpager",
+        "androidx.viewpager2_viewpager2",
         "com_android_systemui_flags_lib",
         "SettingsLibDisplayUtils",
         "SettingsLibSettingsTheme",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml
index 462c90b..e1b6e63 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml
@@ -22,7 +22,7 @@
       android:orientation="horizontal">
 
     <ImageButton
-        android:id="@+id/menu_prev_button"
+        android:id="@+id/menu_left_button"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_weight="1"
@@ -38,7 +38,7 @@
         android:background="?android:attr/listDivider"/>
 
     <ImageButton
-        android:id="@+id/menu_next_button"
+        android:id="@+id/menu_right_button"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_weight="1"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml
index c198443..c0aa1b3 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml
@@ -2,7 +2,7 @@
 <GridView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/gridview"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="match_parent"
     android:horizontalSpacing="@dimen/a11ymenu_grid_layout_margin"
     android:listSelector="@android:color/transparent"
     android:numColumns="3"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
index 28a633e..6be7655 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
@@ -6,18 +6,16 @@
     android:background="@drawable/view_background"
     >
   <LinearLayout
-      android:layout_width="@dimen/row_width"
+      android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">
 
-    <androidx.viewpager.widget.ViewPager
+    <androidx.viewpager2.widget.ViewPager2
         android:id="@+id/view_pager"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingTop="@dimen/table_margin_top"
         android:paddingBottom="@dimen/a11ymenu_layout_margin"
-        android:paddingLeft="@dimen/a11ymenu_layout_margin"
-        android:paddingRight="@dimen/a11ymenu_layout_margin"
         android:layout_gravity="center"
         android:gravity="center"
         />
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
index 20c63df..78fbf01 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
@@ -16,7 +16,11 @@
 
 package com.android.systemui.accessibility.accessibilitymenu.view;
 
+import static android.view.View.LAYOUT_DIRECTION_LTR;
+
+import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.text.TextUtils;
 import android.view.TouchDelegate;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -37,46 +41,61 @@
     public interface A11yMenuFooterCallBack {
 
         /** Calls back when user clicks the left button. */
-        void onLeftButtonClicked();
+        void onNextButtonClicked();
 
         /** Calls back when user clicks the right button. */
-        void onRightButtonClicked();
+        void onPreviousButtonClicked();
     }
 
     private final FooterButtonClickListener mFooterButtonClickListener;
 
-    private ImageButton mPreviousPageBtn;
-    private ImageButton mNextPageBtn;
+    private ImageButton mPageLeftBtn;
+    private ImageButton mPageRightBtn;
     private View mTopListDivider;
     private View mBottomListDivider;
     private final A11yMenuFooterCallBack mCallBack;
+    private final ViewGroup mMenuLayout;
+    private int mRightToLeftDirection = LAYOUT_DIRECTION_LTR;
 
     public A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack) {
         this.mCallBack = callBack;
         mFooterButtonClickListener = new FooterButtonClickListener();
         configureFooterLayout(menuLayout);
+        mMenuLayout = menuLayout;
     }
 
     public @Nullable ImageButton getPreviousPageBtn() {
-        return mPreviousPageBtn;
+        return mRightToLeftDirection == LAYOUT_DIRECTION_LTR
+                ? mPageLeftBtn : mPageRightBtn;
     }
 
     public @Nullable ImageButton getNextPageBtn() {
-        return mNextPageBtn;
+        return mRightToLeftDirection == LAYOUT_DIRECTION_LTR
+                ? mPageRightBtn : mPageLeftBtn;
+    }
+
+    /** Sets right to left direction of footer. */
+    public void updateRightToLeftDirection(Configuration configuration) {
+        mRightToLeftDirection = TextUtils.getLayoutDirectionFromLocale(
+                configuration.getLocales().get(0));
+        getPreviousPageBtn().setContentDescription(mMenuLayout.getResources().getString(
+                R.string.previous_button_content_description));
+        getNextPageBtn().setContentDescription(mMenuLayout.getResources().getString(
+                R.string.next_button_content_description));
     }
 
     private void configureFooterLayout(ViewGroup menuLayout) {
         ViewGroup footerContainer = menuLayout.findViewById(R.id.footerlayout);
         footerContainer.setVisibility(View.VISIBLE);
 
-        mPreviousPageBtn = menuLayout.findViewById(R.id.menu_prev_button);
-        mNextPageBtn = menuLayout.findViewById(R.id.menu_next_button);
+        mPageLeftBtn = menuLayout.findViewById(R.id.menu_left_button);
+        mPageRightBtn = menuLayout.findViewById(R.id.menu_right_button);
         mTopListDivider = menuLayout.findViewById(R.id.top_listDivider);
         mBottomListDivider = menuLayout.findViewById(R.id.bottom_listDivider);
 
         // Registers listeners for footer buttons.
-        setListener(mPreviousPageBtn);
-        setListener(mNextPageBtn);
+        setListener(mPageLeftBtn);
+        setListener(mPageRightBtn);
 
         menuLayout
                 .getViewTreeObserver()
@@ -85,8 +104,8 @@
                             @Override
                             public void onGlobalLayout() {
                                 menuLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                                expandBtnTouchArea(mPreviousPageBtn, menuLayout);
-                                expandBtnTouchArea(mNextPageBtn, (View) mNextPageBtn.getParent());
+                                expandBtnTouchArea(mPageLeftBtn, menuLayout);
+                                expandBtnTouchArea(mPageRightBtn, (View) mPageRightBtn.getParent());
                             }
                         });
     }
@@ -115,10 +134,10 @@
     private class FooterButtonClickListener implements OnClickListener {
         @Override
         public void onClick(View view) {
-            if (view.getId() == R.id.menu_prev_button) {
-                mCallBack.onLeftButtonClicked();
-            } else if (view.getId() == R.id.menu_next_button) {
-                mCallBack.onRightButtonClicked();
+            if (view.getId() == getPreviousPageBtn().getId()) {
+                mCallBack.onPreviousButtonClicked();
+            } else if (view.getId() == getNextPageBtn().getId()) {
+                mCallBack.onNextButtonClicked();
             }
         }
     }
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index 6bea30f..de3c472 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -145,13 +145,14 @@
         final Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
         final Context context = mService.createDisplayContext(display).createWindowContext(
                 TYPE_ACCESSIBILITY_OVERLAY, null);
-        mLayout = new FrameLayout(context);
+        mLayout = new A11yMenuFrameLayout(context);
         updateLayoutPosition();
         inflateLayoutAndSetOnTouchListener(mLayout, context);
         mA11yMenuViewPager = new A11yMenuViewPager(mService, context);
         mA11yMenuViewPager.configureViewPagerAndFooter(mLayout, createShortcutList(), pageIndex);
         mWindowManager.addView(mLayout, mLayoutParameter);
         mLayout.setVisibility(lastVisibilityState);
+        mA11yMenuViewPager.updateFooterState();
 
         return mLayout;
     }
@@ -393,4 +394,16 @@
                         }
                     }), timeoutDurationMs);
     }
+
+    private class A11yMenuFrameLayout extends FrameLayout {
+        A11yMenuFrameLayout(@NonNull Context context) {
+            super(context);
+        }
+
+        @Override
+        public void dispatchConfigurationChanged(Configuration newConfig) {
+            super.dispatchConfigurationChanged(newConfig);
+            mA11yMenuViewPager.mA11yMenuFooter.updateRightToLeftDirection(newConfig);
+        }
+    }
 }
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
index b969017..08bbf19 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -20,7 +20,6 @@
 import android.content.res.Configuration;
 import android.graphics.Insets;
 import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -29,7 +28,7 @@
 import android.view.WindowMetrics;
 import android.widget.GridView;
 
-import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager2.widget.ViewPager2;
 
 import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
 import com.android.systemui.accessibility.accessibilitymenu.R;
@@ -133,9 +132,9 @@
      * The pager widget, which handles animation and allows swiping horizontally to access previous
      * and next gridView pages.
      */
-    protected ViewPager mViewPager;
+    protected ViewPager2 mViewPager;
 
-    private ViewPagerAdapter<GridView> mViewPagerAdapter;
+    private ViewPagerAdapter mViewPagerAdapter;
     private final List<GridView> mGridPageList = new ArrayList<>();
 
     /** The footer, which provides buttons to switch between pages */
@@ -169,6 +168,8 @@
         initViewPager();
         initChildPage();
         mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks);
+        mA11yMenuFooter.updateRightToLeftDirection(
+                a11yMenuLayout.getResources().getConfiguration());
         updateFooterState();
         registerOnGlobalLayoutListener();
         goToPage(pageIndex);
@@ -177,18 +178,12 @@
     /** Initializes viewPager and its adapter. */
     private void initViewPager() {
         mViewPager = mA11yMenuLayout.findViewById(R.id.view_pager);
-        mViewPagerAdapter = new ViewPagerAdapter<>();
+        mViewPagerAdapter = new ViewPagerAdapter(mService);
+        mViewPager.setOffscreenPageLimit(2);
         mViewPager.setAdapter(mViewPagerAdapter);
         mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
-        mViewPager.addOnPageChangeListener(
-                new ViewPager.OnPageChangeListener() {
-                    @Override
-                    public void onPageScrollStateChanged(int state) {}
-
-                    @Override
-                    public void onPageScrolled(
-                            int position, float positionOffset, int positionOffsetPixels) {}
-
+        mViewPager.registerOnPageChangeCallback(
+                new ViewPager2.OnPageChangeCallback() {
                     @Override
                     public void onPageSelected(int position) {
                         updateFooterState();
@@ -206,31 +201,14 @@
             mGridPageList.clear();
         }
 
-        // Generate pages by calculating # of items per grid.
-        for (List<A11yMenuShortcut> page : GridViewParams.generateShortcutSubLists(
-                GridViewParams.getGridItemCount(mService), mA11yMenuShortcutList)
-        ) {
-            addGridPage(page);
-        }
-
-        mViewPagerAdapter.set(mGridPageList);
-    }
-
-    private void addGridPage(List<A11yMenuShortcut> shortcutDataListInPage) {
-        LayoutInflater inflater = LayoutInflater.from(mDisplayContext);
-        View view = inflater.inflate(R.layout.grid_view, null);
-        GridView gridView = view.findViewById(R.id.gridview);
-        A11yMenuAdapter adapter = new A11yMenuAdapter(
-                mService, mDisplayContext, shortcutDataListInPage);
-        gridView.setNumColumns(GridViewParams.getGridColumnCount(mService));
-        gridView.setAdapter(adapter);
-        mGridPageList.add(gridView);
+        mViewPagerAdapter.set(GridViewParams.generateShortcutSubLists(
+                GridViewParams.getGridItemCount(mService), mA11yMenuShortcutList));
     }
 
     /** Updates footer's state by index of current page in view pager. */
-    private void updateFooterState() {
+    public void updateFooterState() {
         int currentPage = mViewPager.getCurrentItem();
-        int lastPage = mViewPager.getAdapter().getCount() - 1;
+        int lastPage = mViewPager.getAdapter().getItemCount() - 1;
         mA11yMenuFooter.getPreviousPageBtn().setEnabled(currentPage > 0);
         mA11yMenuFooter.getNextPageBtn().setEnabled(currentPage < lastPage);
     }
@@ -239,7 +217,7 @@
         if (mViewPager == null) {
             return;
         }
-        if ((pageIndex >= 0) && (pageIndex < mViewPager.getAdapter().getCount())) {
+        if ((pageIndex >= 0) && (pageIndex < mViewPager.getAdapter().getItemCount())) {
             mViewPager.setCurrentItem(pageIndex);
         }
     }
@@ -341,7 +319,7 @@
     protected A11yMenuFooterCallBack mFooterCallbacks =
             new A11yMenuFooterCallBack() {
                 @Override
-                public void onLeftButtonClicked() {
+                public void onPreviousButtonClicked() {
                     // Moves to previous page.
                     int targetPage = mViewPager.getCurrentItem() - 1;
                     goToPage(targetPage);
@@ -349,7 +327,7 @@
                 }
 
                 @Override
-                public void onRightButtonClicked() {
+                public void onNextButtonClicked() {
                     // Moves to next page.
                     int targetPage = mViewPager.getCurrentItem() + 1;
                     goToPage(targetPage);
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
index 5670d72..43ec956 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
@@ -16,55 +16,64 @@
 
 package com.android.systemui.accessibility.accessibilitymenu.view;
 
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.GridView;
 
-import androidx.viewpager.widget.PagerAdapter;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
+import com.android.systemui.accessibility.accessibilitymenu.R;
+import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
 
 import java.util.List;
 
 /** The pager adapter, which provides the pages to the view pager widget. */
-class ViewPagerAdapter<T extends View> extends PagerAdapter {
+class ViewPagerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
 
-    /** The widget list in each page of view pager. */
-    private List<T> mWidgetList;
+    /** List of shortcuts, split into sub lists per page */
+    private List<List<A11yMenuShortcut>> mShortcutList;
+    private final AccessibilityMenuService mService;
 
-    ViewPagerAdapter() {}
+    ViewPagerAdapter(AccessibilityMenuService service) {
+        mService = service;
+    }
 
-    public void set(List<T> tList) {
-        mWidgetList = tList;
+    public void set(List<List<A11yMenuShortcut>> tList) {
+        mShortcutList = tList;
         notifyDataSetChanged();
     }
 
+    @NonNull
     @Override
-    public int getCount() {
-        if (mWidgetList == null) {
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        View view = inflater.inflate(R.layout.grid_view, parent, false);
+        return new MenuViewHolder(view.findViewById(R.id.gridview));
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+        A11yMenuAdapter adapter = new A11yMenuAdapter(
+                mService, holder.itemView.getContext(), mShortcutList.get(position));
+        GridView gridView = (GridView) holder.itemView;
+        gridView.setNumColumns(A11yMenuViewPager.GridViewParams.getGridColumnCount(mService));
+        gridView.setAdapter(adapter);
+    }
+
+    @Override
+    public int getItemCount() {
+        if (mShortcutList == null) {
             return 0;
         }
-        return mWidgetList.size();
+        return mShortcutList.size();
     }
 
-    @Override
-    public int getItemPosition(Object object) {
-        return POSITION_NONE;
-    }
-
-    @Override
-    public boolean isViewFromObject(View view, Object object) {
-        return view == object;
-    }
-
-    @Override
-    public Object instantiateItem(ViewGroup container, int position) {
-        if (mWidgetList == null) {
-            return null;
+    static class MenuViewHolder extends RecyclerView.ViewHolder {
+        MenuViewHolder(View itemView) {
+            super(itemView);
         }
-        container.addView(mWidgetList.get(position));
-        return mWidgetList.get(position);
     }
-
-    @Override
-    public void destroyItem(ViewGroup container, int position, Object object) {
-        container.removeView((View) object);
-    }
-}
+}
\ No newline at end of file