diff options
| -rw-r--r-- | core/java/com/android/internal/policy/PhoneWindow.java | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 33595f2b9b37..7ad88ca6b1b2 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -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) { - 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 focused view ID. + final View focusedView = mContentParent.findFocus(); + if (focusedView != null && focusedView.getId() != View.NO_ID) { + outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); + } + + // 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. * |