• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package foo.bar.testback;
18 
19 import static foo.bar.testback.AccessibilityNodeInfoUtils.findParent;
20 
21 import android.text.TextUtils;
22 import android.view.accessibility.AccessibilityNodeInfo;
23 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
24 
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.function.Predicate;
29 
30 /**
31  * Helper class to manage accessibility focus
32  */
33 public class AccessibilityFocusManager {
34     private static final AccessibilityAction[] IGNORED_ACTIONS_FOR_A11Y_FOCUS = {
35             AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS,
36             AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
37             AccessibilityAction.ACTION_SELECT,
38             AccessibilityAction.ACTION_CLEAR_SELECTION,
39             AccessibilityAction.ACTION_SHOW_ON_SCREEN
40     };
41 
canTakeAccessibilityFocus(AccessibilityNodeInfo nodeInfo)42     public static final boolean canTakeAccessibilityFocus(AccessibilityNodeInfo nodeInfo) {
43         if (nodeInfo.isFocusable() || nodeInfo.isScreenReaderFocusable()) {
44             return true;
45         }
46 
47         List<AccessibilityAction> actions = new ArrayList<>(nodeInfo.getActionList());
48         actions.removeAll(Arrays.asList(IGNORED_ACTIONS_FOR_A11Y_FOCUS));
49 
50         // Nodes with relevant actions are always focusable
51         if (!actions.isEmpty()) {
52             return true;
53         }
54 
55         // If a parent is specifically marked focusable, then this node should not be.
56         if (findParent(nodeInfo,
57                 (parent) -> parent.isFocusable() || parent.isScreenReaderFocusable()) != null) {
58             return false;
59         }
60 
61         return !TextUtils.isEmpty(nodeInfo.getText())
62                 || !TextUtils.isEmpty(nodeInfo.getContentDescription());
63     };
64 }
65