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

Commit abd89024 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Manage accessibility focus during PhoneWindow save and restore"

parents 31710114 ec6cf184
Loading
Loading
Loading
Loading
+59 −11
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@ import android.util.SparseArray;
import android.util.TypedValue;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -2000,6 +2002,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
    }

    static private final String FOCUSED_ID_TAG = "android:focusedViewId";
    static private final String ACCESSIBILITY_FOCUSED_ID_TAG = "android:accessibilityFocusedViewId";
    static private final String ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG =
            "android:accessibilityFocusedVirtualViewId";
    static private final String VIEWS_TAG = "android:views";
    static private final String PANELS_TAG = "android:Panels";
    static private final String ACTION_BAR_TAG = "android:ActionBar";
@@ -2016,16 +2021,25 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
        mContentParent.saveHierarchyState(states);
        outState.putSparseParcelableArray(VIEWS_TAG, states);

        // save the focused view id
        View focusedView = mContentParent.findFocus();
        if (focusedView != null) {
            if (focusedView.getId() != View.NO_ID) {
        // Save the focused view ID.
        final View focusedView = mContentParent.findFocus();
        if (focusedView != null && focusedView.getId() != View.NO_ID) {
            outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
            } else {
                if (false) {
                    Log.d(TAG, "couldn't save which view has focus because the focused view "
                            + focusedView + " has no id.");
        }

        // Save the accessibility focused view ID.
        final ViewRootImpl viewRootImpl = mContentParent.getViewRootImpl();
        final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost();
        if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) {
            outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId());

            // If we have a focused virtual node ID, save that too.
            final AccessibilityNodeInfo accessFocusedNode =
                    viewRootImpl.getAccessibilityFocusedVirtualView();
            if (accessFocusedNode != null) {
                final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
                        accessFocusedNode.getSourceNodeId());
                outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId);
            }
        }

@@ -2071,7 +2085,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
            }
        }

        // restore the panels
        // Restore the accessibility focused view.
        final int accessFocusHostViewId = savedInstanceState.getInt(
                ACCESSIBILITY_FOCUSED_ID_TAG, View.NO_ID);
        final int accessFocusVirtualViewId = savedInstanceState.getInt(
                ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, AccessibilityNodeInfo.UNDEFINED_ITEM_ID);
        tryRestoreAccessibilityFocus(accessFocusHostViewId, accessFocusVirtualViewId);

        // Restore the panels.
        SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
        if (panelStates != null) {
            restorePanelState(panelStates);
@@ -2090,6 +2111,33 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
        }
    }

    private void tryRestoreAccessibilityFocus(int hostViewId, int virtualViewId) {
        if (hostViewId != View.NO_ID) {
            final View needsAccessFocus = mContentParent.findViewById(hostViewId);
            if (needsAccessFocus != null) {
                if (!tryFocusingVirtualView(needsAccessFocus, virtualViewId)
                        && !needsAccessFocus.requestAccessibilityFocus()) {
                    Log.w(TAG, "Failed to restore focus to previously accessibility"
                            + " focused view with id " + hostViewId);
                }
            } else {
                Log.w(TAG, "Previously accessibility focused view reported id " + hostViewId
                        + " during save, but can't be found during restore.");
            }
        }
    }

    private boolean tryFocusingVirtualView(View host, int virtualViewId) {
        if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
            final AccessibilityNodeProvider nodeProvider = host.getAccessibilityNodeProvider();
            if (nodeProvider != null) {
                return nodeProvider.performAction(virtualViewId,
                        AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
            }
        }
        return false;
    }

    /**
     * Invoked when the panels should freeze their state.
     *