/** * returns true if there is no window with windowType after baseWindow */ public boolean isLastWindow(AccessibilityWindowInfo baseWindow, int windowType) { int index = getWindowIndex(baseWindow); if (index == WRONG_INDEX) { return true; } int count = mWindows.size(); for (int i = index + 1; i < count; i++) { AccessibilityWindowInfo window = mWindows.get(i); if (window != null && window.getType() == windowType) { return false; } } return true; }
/** * returns true if there is no window with windowType before baseWindow */ public boolean isFirstWindow(AccessibilityWindowInfo baseWindow, int windowType) { int index = getWindowIndex(baseWindow); if (index <= 0) { return true; } for (int i = index - 1; i > 0; i--) { AccessibilityWindowInfo window = mWindows.get(i); if (window != null && window.getType() == windowType) { return false; } } return true; }
/** * @return window that currently accessibilityFocused window. * If there is no accessibility focused window it returns first window that has TYPE_APPLICATION * or null if there is no window with TYPE_APPLICATION type */ public AccessibilityWindowInfo getCurrentWindow(boolean useInputFocus) { int currentWindowIndex = getFocusedWindowIndex(mWindows, AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); if (currentWindowIndex != WRONG_INDEX) { return mWindows.get(currentWindowIndex); } if (!useInputFocus) { return null; } currentWindowIndex = getFocusedWindowIndex(mWindows, AccessibilityNodeInfo.FOCUS_INPUT); if (currentWindowIndex != WRONG_INDEX) { return mWindows.get(currentWindowIndex); } return null; }
/** * Gets the window whose anchor equals the given node. */ public AccessibilityWindowInfo getAnchoredWindow( @Nullable AccessibilityNodeInfoCompat targetAnchor) { if (!BuildCompat.isAtLeastN() || targetAnchor == null) { return null; } int windowCount = mWindows.size(); for (int i = 0; i < windowCount; ++i) { AccessibilityWindowInfo window = mWindows.get(i); if (window != null) { AccessibilityNodeInfo anchor = window.getAnchor(); if (anchor != null) { try { if (anchor.equals(targetAnchor.getInfo())) { return window; } } finally { anchor.recycle(); } } } } return null; }
private AccessibilityWindowInfo getWindow(AccessibilityWindowInfo pivotWindow, int direction) { if (mWindows == null || pivotWindow == null || (direction != NEXT && direction != PREVIOUS)) { return null; } int currentWindowIndex = getWindowIndex(pivotWindow); int resultIndex; if (direction == NEXT) { resultIndex = getNextWindowIndex(currentWindowIndex); } else { resultIndex = getPreviousWindowIndex(currentWindowIndex); } if (resultIndex == WRONG_INDEX) { return null; } return mWindows.get(resultIndex); }
private static int getFocusedWindowIndex(List<AccessibilityWindowInfo> windows, int focusType) { if (windows == null) { return WRONG_INDEX; } for (int i = 0, size = windows.size(); i < size; i++) { AccessibilityWindowInfo window = windows.get(i); if (window == null) { continue; } if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY && window.isAccessibilityFocused()) { return i; } else if (focusType == AccessibilityNodeInfo.FOCUS_INPUT && window.isFocused()) { return i; } } return WRONG_INDEX; }
@Override public OptionScanNode addWindowListToTree(List<SwitchAccessWindowInfo> windowList, OptionScanNode tree) { if (windowList != null) { List<SwitchAccessWindowInfo> wList = new ArrayList<>(windowList); sortWindowListForTraversalOrder(wList); removeSystemButtonsWindowFromWindowList(wList); if (mOptionScanningEnabled) { return mOptionScanTreeBuilder.addWindowListToTree(wList, tree); } for (SwitchAccessWindowInfo window : wList) { SwitchAccessNodeCompat windowRoot = window.getRoot(); if (windowRoot != null) { if (window.getType() == AccessibilityWindowInfo.TYPE_INPUT_METHOD) { tree = mRowColumnTreeBuilder.addViewHierarchyToTree(windowRoot, tree); } else { tree = addViewHierarchyToTree(windowRoot, tree); } windowRoot.recycle(); } } } return tree; }
private CharSequence getWindowTitle(int windowId) { // Try to get window title from the map. CharSequence windowTitle = mWindowTitlesMap.get(windowId); if (windowTitle != null) { return windowTitle; } if (!BuildCompat.isAtLeastN()) { return null; } // Do not try to get system window title from AccessibilityWindowInfo.getTitle, it can // return non-translated value. if (isSystemWindow(windowId)) { return null; } // Try to get window title from AccessibilityWindowInfo. for (AccessibilityWindowInfo window : mService.getWindows()) { if (window.getId() == windowId) { return window.getTitle(); } } return null; }
private boolean isSystemWindow(int windowId) { if (mSystemWindowIdsSet.contains(windowId)) { return true; } if (!mIsSplitScreenModeAvailable) { return false; } for (AccessibilityWindowInfo window : mService.getWindows()) { if (window.getId() == windowId && window.getType() == AccessibilityWindowInfo.TYPE_SYSTEM) { return true; } } return false; }
@Override public boolean onMenuItemClick(MenuItem item) { if (mAnchor != null) { WindowManager windowManager = new WindowManager(mService.isScreenLayoutRTL()); windowManager.setWindows(mService.getWindows()); AccessibilityWindowInfo anchoredWindow = windowManager.getAnchoredWindow(mAnchor); if (anchoredWindow != null) { AccessibilityNodeInfoCompat firstNode = getFirstNode(anchoredWindow); if (firstNode != null) { CursorController cursorController = mService.getCursorController(); cursorController.setCursor(firstNode); firstNode.recycle(); } } mAnchor.recycle(); mAnchor = null; } return true; }
private AccessibilityNodeInfoCompat getFirstNode(AccessibilityWindowInfo window) { AccessibilityNodeInfo root = window.getRoot(); if (root != null) { AccessibilityNodeInfoCompat compatRoot = new AccessibilityNodeInfoCompat(root); TraversalStrategy traversalStrategy = TraversalStrategyUtils.getTraversalStrategy( compatRoot, TraversalStrategy.SEARCH_FOCUS_FORWARD); AccessibilityNodeInfoCompat firstNode = AccessibilityNodeInfoUtils.searchFocus( traversalStrategy, compatRoot, TraversalStrategy.SEARCH_FOCUS_FORWARD, AccessibilityNodeInfoUtils.FILTER_SHOULD_FOCUS); compatRoot.recycle(); // This will also recycle the underlying node (root). return firstNode; } return null; }
/** * @return root node of the window that currently has accessibility focus */ public static AccessibilityNodeInfoCompat getRootInAccessibilityFocusedWindow( AccessibilityService service) { if (service == null) { return null; } AccessibilityNodeInfo focusedRoot = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { List<AccessibilityWindowInfo> windows = service.getWindows(); // Create window manager with fake value of isInRTL = false. This is okay here since // isInRTL will not change the result of getCurrentWindow. WindowManager manager = new WindowManager(false /* isInRTL */); manager.setWindows(windows); AccessibilityWindowInfo accessibilityFocusedWindow = manager.getCurrentWindow(false /* useInputFocus */); if (accessibilityFocusedWindow != null) { focusedRoot = accessibilityFocusedWindow.getRoot(); } } if (focusedRoot == null) { focusedRoot = service.getRootInActiveWindow(); } if (focusedRoot == null) { return null; } return new AccessibilityNodeInfoCompat(focusedRoot); }
/** * Returns a fresh copy of node by traversing the given window for a similar node. * For example, the node that you want might be in a popup window that has closed and re-opened, * causing the accessibility IDs of its views to be different. * Note: you must recycle the node that is returned from this method. */ public static AccessibilityNodeInfoCompat refreshNodeFuzzy( final AccessibilityNodeInfoCompat node, AccessibilityWindowInfo window) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return null; } if (window == null || node == null) { return null; } AccessibilityNodeInfo root = window.getRoot(); if (root == null) { return null; } NodeFilter similarFilter = new NodeFilter() { @Override public boolean accept(AccessibilityNodeInfoCompat other) { return other != null && TextUtils.equals(node.getText(), other.getText()); } }; AccessibilityNodeInfoCompat rootCompat = new AccessibilityNodeInfoCompat(root); try { return getMatchingDescendant(rootCompat, similarFilter); } finally { rootCompat.recycle(); } }
/** * Returns the node to which the given node's window is anchored, if there is an anchor. * Note: you must recycle the node that is returned from this method. */ public static AccessibilityNodeInfoCompat getAnchor( @Nullable AccessibilityNodeInfoCompat node) { if (!BuildCompat.isAtLeastN()) { return null; } if (node == null) { return null; } AccessibilityNodeInfo nativeNode = (AccessibilityNodeInfo) node.getInfo(); if (nativeNode == null) { return null; } AccessibilityWindowInfo nativeWindow = nativeNode.getWindow(); if (nativeWindow == null) { return null; } AccessibilityNodeInfo nativeAnchor = nativeWindow.getAnchor(); if (nativeAnchor == null) { return null; } return new AccessibilityNodeInfoCompat(nativeAnchor); }
@Override public int compare(AccessibilityWindowInfo windowA, AccessibilityWindowInfo windowB) { windowA.getBoundsInScreen(mRectA); windowB.getBoundsInScreen(mRectB); if (mRectA.top != mRectB.top) { return mRectA.top - mRectB.top; } else { return mIsInRTL ? mRectB.right - mRectA.right : mRectA.left - mRectB.left; } }
/** * Set windows that would be used by WindowManager * @param windows Set the windows on the screen. */ public void setWindows(List<AccessibilityWindowInfo> windows) { // Copy list not to sort the original one. mWindows.clear(); mWindows.addAll(windows); Collections.sort(mWindows, new WindowPositionComparator(mIsInRTL)); }
public boolean isInputWindowOnScreen() { if (mWindows == null) { return false; } for (AccessibilityWindowInfo window : mWindows) { if (window != null && window.getType() == AccessibilityWindowInfo.TYPE_INPUT_METHOD) { return true; } } return false; }
public int getWindowType(int windowId) { if (mWindows != null) { for (AccessibilityWindowInfo window : mWindows) { if (window != null && window.getId() == windowId) { return window.getType(); } } } return WRONG_WINDOW_TYPE; }
public boolean isStatusBar(int windowId) { if (mWindows == null || mWindows.size() == 0) { return false; } return mWindows.get(0).getId() == windowId && mWindows.get(0).getType() == AccessibilityWindowInfo.TYPE_SYSTEM; }
public boolean isNavigationBar(int windowId) { if (mWindows == null || mWindows.size() < 2) { return false; } int lastIndex = mWindows.size() - 1; return mWindows.get(lastIndex).getId() == windowId && mWindows.get(lastIndex).getType() == AccessibilityWindowInfo.TYPE_SYSTEM; }
private int getWindowIndex(AccessibilityWindowInfo windowInfo) { if (mWindows == null || windowInfo == null) { return WRONG_INDEX; } int windowSize = mWindows.size(); for (int i = 0; i < windowSize; i++) { if (windowInfo.equals(mWindows.get(i))) { return i; } } return WRONG_INDEX; }
private static AccessibilityWindowInfo getDefaultWindow(List<AccessibilityWindowInfo> windows) { if (windows.size() == 0) { return null; } for (AccessibilityWindowInfo window : windows) { if (window != null && window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) { return window; } } return windows.get(0); }
/** * Sort windows so that the IME is traversed first, and the system windows last. Note that * the list comes out backwards, which makes it easy to iterate through it when building the * tree from the bottom up. * @param windowList The list to be sorted. */ private static void sortWindowListForTraversalOrder(List<SwitchAccessWindowInfo> windowList) { Collections.sort(windowList, new Comparator<SwitchAccessWindowInfo>() { @Override public int compare(SwitchAccessWindowInfo arg0, SwitchAccessWindowInfo arg1) { // Compare based on window type final int type0 = arg0.getType(); final int type1 = arg1.getType(); if (type0 == type1) { return 0; } /* Present IME windows first */ if (type0 == AccessibilityWindowInfo.TYPE_INPUT_METHOD) { return 1; } if (type1 == AccessibilityWindowInfo.TYPE_INPUT_METHOD) { return -1; } /* Present system windows last */ if (type0 == AccessibilityWindowInfo.TYPE_SYSTEM) { return -1; } if (type1 == AccessibilityWindowInfo.TYPE_SYSTEM) { return 1; } /* Others are don't care */ return 0; } }); }
private void removeSystemButtonsWindowFromWindowList(List<SwitchAccessWindowInfo> windowList) { final WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); final Display display = wm.getDefaultDisplay(); final Point screenSize = new Point(); display.getSize(screenSize); final Iterator<SwitchAccessWindowInfo> windowIterator = windowList.iterator(); while (windowIterator.hasNext()) { SwitchAccessWindowInfo window = windowIterator.next(); /* Keep all non-system buttons */ if (window.getType() != AccessibilityWindowInfo.TYPE_SYSTEM) { continue; } final Rect windowBounds = new Rect(); window.getBoundsInScreen(windowBounds); /* Keep system dialogs (app has crashed), which don't border any edge */ if ((windowBounds.top > 0) && (windowBounds.bottom < screenSize.y) && (windowBounds.left > 0) && (windowBounds.right < screenSize.x)) { continue; } /* Keep notifications, which start at the top and cover more than half the width */ if ((windowBounds.top <= 0) && (windowBounds.width() > screenSize.x / 2)) { continue; } /* Keep large system overlays like the context menu */ final int windowArea = windowBounds.width() * windowBounds.height(); final int screenArea = screenSize.x * screenSize.y; if (windowArea > (screenArea / 2)) { continue; } windowIterator.remove(); } }
/** * @param info The info to wrap * @param windowsAbove The windows sitting on top of the current one. This * list is used to compute visibility. */ public SwitchAccessNodeCompat(Object info, List<AccessibilityWindowInfo> windowsAbove) { super(info); if (info == null) { throw new NullPointerException(); } if (windowsAbove == null) { mWindowsAbove = Collections.emptyList(); } else { mWindowsAbove = new ArrayList<>(windowsAbove); } }
/** * Convert a list of standard {@code AccessibilityWindowInfo} objects into a list of * {@code ExtendedWindowInfo} objects. * * @param originalList The original list in Z order (as the framework returns it) * @return The new list in the same order as the original */ static public List<SwitchAccessWindowInfo> convertZOrderWindowList(List<AccessibilityWindowInfo> originalList) { List<SwitchAccessWindowInfo> newList = new ArrayList<>(originalList.size()); for (int i = 0; i < originalList.size(); i++) { newList.add(new SwitchAccessWindowInfo( originalList.get(i), originalList.subList(0, i))); } return newList; }
/** * @param accessibilityWindowInfo The windowInfo to wrap * @param listOfWindowsAbove A list of all windows above this one */ public SwitchAccessWindowInfo(AccessibilityWindowInfo accessibilityWindowInfo, List<AccessibilityWindowInfo> listOfWindowsAbove) { if (accessibilityWindowInfo == null) { throw new NullPointerException(); } mAccessibilityWindowInfo = accessibilityWindowInfo; mListOfWindowsAbove = listOfWindowsAbove; }
private void addEarconWhenAccessibilityFocusMovesToTheDivider(Utterance utterance, AccessibilityNodeInfoCompat announcedNode) { if (!BuildCompat.isAtLeastN() || mLastFocusedWindowId == announcedNode.getWindowId()) { return; } // TODO: Use AccessibilityWindowInfoCompat.TYPE_SPLIT_SCREEN_DIVIDER once it's // added. if (getWindowType(announcedNode) != AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER) { return; } utterance.addAuditory(R.raw.complete); }
private boolean isKeyboardEvent(AccessibilityEvent event) { if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { return false; } if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { // For platform since lollipop, check that the current window is an // Input Method. final AccessibilityNodeInfo source = event.getSource(); if (source == null) { return false; } int windowId = source.getWindowId(); WindowManager manager = new WindowManager(mService.isScreenLayoutRTL()); manager.setWindows(mService.getWindows()); return manager.getWindowType(windowId) == AccessibilityWindowInfo.TYPE_INPUT_METHOD; } else { // For old platforms, we can't check the window type directly, so just // manually check the classname. if (event.getClassName() != null) { return event.getClassName().equals("com.android.inputmethod.keyboard.Key"); } else { return false; } } }
private CharSequence getWindowTitleForFeedback(int windowId) { CharSequence title = getWindowTitle(windowId); // Try to fall back to application label if window title is not available. if (title == null) { CharSequence packageName = mWindowToPackageName.get(windowId); // Try to get package name from accessibility window info if it's not in the map. if (packageName == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { for (AccessibilityWindowInfo window : mService.getWindows()) { if (window.getId() == windowId) { AccessibilityNodeInfo rootNode = window.getRoot(); if (rootNode != null) { packageName = rootNode.getPackageName(); rootNode.recycle(); } } } } if (packageName != null) { title = mService.getApplicationLabel(packageName); } } title = WindowManager.formatWindowTitleForFeedback(title, mService); if (isAlertDialog(windowId)) { title = mService.getString(R.string.template_alert_dialog_template, title); } return title; }
@SuppressLint("InlinedApi") private boolean needPauseInTraversalAfterCurrentWindow( @TraversalStrategy.SearchDirection int direction) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { // always pause before loop in one-window conditions return true; } WindowManager windowManager = new WindowManager(mService.isScreenLayoutRTL()); windowManager.setWindows(mService.getWindows()); if (!windowManager.isApplicationWindowFocused() && !windowManager.isSplitScreenDividerFocused()) { // need pause before looping traversal in non-application window return true; } @TraversalStrategy.SearchDirection int logicalDirection = TraversalStrategyUtils.getLogicalDirection(direction, mService.isScreenLayoutRTL()); if (logicalDirection == TraversalStrategy.SEARCH_FOCUS_FORWARD) { return windowManager.isLastWindow( windowManager.getCurrentWindow(false /* useInputFocus */), AccessibilityWindowInfo.TYPE_APPLICATION); } else if (logicalDirection == TraversalStrategy.SEARCH_FOCUS_BACKWARD) { return windowManager.isFirstWindow( windowManager.getCurrentWindow(false /* useInputFocus */), AccessibilityWindowInfo.TYPE_APPLICATION); } else { throw new IllegalStateException("Unknown logical direction"); } }
private boolean matchWindowType(AccessibilityWindowInfo window, int windowTypeFilter) { int windowType = window.getType(); if ((windowTypeFilter & WINDOW_TYPE_SYSTEM) != 0 && windowType == AccessibilityWindowInfo.TYPE_SYSTEM) { return true; } else if ((windowTypeFilter & WINDOW_TYPE_APPLICATION) != 0 && windowType == AccessibilityWindowInfo.TYPE_APPLICATION) { return true; } else if ((windowTypeFilter & WINDOW_TYPE_SPLIT_SCREEN_DIVIDER) != 0 && windowType == AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER) { return true; } else { return false; } }
@Override public boolean accept(TalkBackService service, AccessibilityNodeInfoCompat node) { if (!BuildCompat.isAtLeastN()) { return false; } // Only accept for "Jump to suggestions" if we're in an edit field. if (Role.getRole(node) == Role.ROLE_EDIT_TEXT) { WindowManager windowManager = new WindowManager(service.isScreenLayoutRTL()); windowManager.setWindows(service.getWindows()); AccessibilityWindowInfo anchoredWindow = windowManager.getAnchoredWindow(node); if (anchoredWindow != null) { return true; } } // Only accept for "Return to edit field" if the anchor is an edit field. AccessibilityNodeInfoCompat anchor = AccessibilityNodeInfoUtils.getAnchor(node); if (anchor != null) { try { if (Role.getRole(anchor) == Role.ROLE_EDIT_TEXT) { return true; } } finally { anchor.recycle(); } } return false; }
@Override public List<ContextMenuItem> getMenuItemsForNode(TalkBackService service, ContextMenuItemBuilder menuItemBuilder, AccessibilityNodeInfoCompat node) { final LinkedList<ContextMenuItem> items = new LinkedList<>(); if (Role.getRole(node) == Role.ROLE_EDIT_TEXT) { WindowManager windowManager = new WindowManager(service.isScreenLayoutRTL()); windowManager.setWindows(service.getWindows()); AccessibilityWindowInfo anchoredWindow = windowManager.getAnchoredWindow(node); if (anchoredWindow != null) { final ContextMenuItem viewSuggestions = menuItemBuilder.createMenuItem(service, Menu.NONE, R.id.suggestions_breakout_suggestions, Menu.NONE, service.getString(R.string.title_suggestions_breakout_suggestions)); viewSuggestions.setOnMenuItemClickListener(new ViewSuggestionsItemClickListener( AccessibilityNodeInfoCompat.obtain(node), service)); viewSuggestions.setSkipRefocusEvents(true); items.add(viewSuggestions); } } AccessibilityNodeInfoCompat anchor = AccessibilityNodeInfoUtils.getAnchor(node); if (anchor != null) { if (Role.getRole(anchor) == Role.ROLE_EDIT_TEXT) { final ContextMenuItem returnToAnchor = menuItemBuilder.createMenuItem(service, Menu.NONE, R.id.suggestions_breakout_anchor, Menu.NONE, service.getString(R.string.title_suggestions_breakout_anchor)); returnToAnchor.setOnMenuItemClickListener(new ReturnToAnchorItemClickListener( anchor, service)); returnToAnchor.setSkipRefocusEvents(true); items.add(returnToAnchor); // Don't recycle anchor here because we gave it to the listener. } else { anchor.recycle(); } } return items; }
boolean isInputWindowOnScreen() { TalkBackService service = TalkBackService.getInstance(); if (service == null) { return false; } WindowManager windowManager = new WindowManager(service.isScreenLayoutRTL()); List<AccessibilityWindowInfo> windows = service.getWindows(); windowManager.setWindows(windows); return windowManager.isInputWindowOnScreen(); }
/** * Resets the accessibility focus to an item inside an anchored window. * We must delay slightly in order for the anchored window to reappear in the windows list * before attempting to place the accessibility focus. Furthermore, we cannot find the exact * previously-focused item again; we must do a fuzzy search for it instead. */ private void resetFocusedNodeInAnchoredWindow(AccessibilityNodeInfoCompat node, AccessibilityNodeInfoCompat anchor, long delay) { if (node == null || anchor == null) { return; } final AccessibilityNodeInfoCompat obtainedNode = AccessibilityNodeInfoCompat.obtain(node); final AccessibilityNodeInfoCompat obtainedAnchor = AccessibilityNodeInfoCompat.obtain(anchor); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { com.android.utils.WindowManager windowManager = new com.android.utils.WindowManager(isScreenLayoutRTL()); windowManager.setWindows(getWindows()); AccessibilityWindowInfo anchoredWindow = windowManager.getAnchoredWindow(obtainedAnchor); AccessibilityNodeInfoCompat refreshed = AccessibilityNodeInfoUtils.refreshNodeFuzzy(obtainedNode, anchoredWindow); if (refreshed != null) { PerformActionUtils.performAction(refreshed, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS); refreshed.recycle(); } obtainedNode.recycle(); obtainedAnchor.recycle(); } }, delay); }
@Test public void testNoFocusedWindowGetCurrent_returnNull() { List<AccessibilityWindowInfo> windows = new ArrayList<>(); for (int i = 0; i < 3; i++) { windows.add(AccessibilityWindowInfo.obtain()); ShadowAccessibilityWindowInfo shadowWindow = (ShadowAccessibilityWindowInfo) ShadowExtractor.extract(windows.get(i)); shadowWindow.setId(i); shadowWindow.setType(AccessibilityWindowInfo.TYPE_APPLICATION); } WindowManager manager = new WindowManager(false /* isInRTL */); manager.setWindows(windows); assertNull(manager.getCurrentWindow(false /* useInputFocus */)); }
@Test public void testFocusedWindowLastGetNext_returnFirstWindow() { List<AccessibilityWindowInfo> windows = initList(3, 2); WindowManager manager = new WindowManager(false /* isInRTL */); manager.setWindows(windows); AccessibilityWindowInfo currentWindow = manager.getCurrentWindow(false /* useInputFocus */); assertEquals(windows.get(0).getId(), manager.getNextWindow(currentWindow).getId()); }
@Test public void testFocusedWindowNotLastGetNext_returnsNextWindow() { List<AccessibilityWindowInfo> windows = initList(3, 1); WindowManager manager = new WindowManager(false /* isInRTL */); manager.setWindows(windows); AccessibilityWindowInfo currentWindow = manager.getCurrentWindow(false /* useInputFocus */); assertEquals(windows.get(2).getId(), manager.getNextWindow(currentWindow).getId()); }
@Test public void testFocusedWindowFirstGetPrevious_returnsLastWindow() { List<AccessibilityWindowInfo> windows = initList(3, 0); WindowManager manager = new WindowManager(false /* isInRTL */); manager.setWindows(windows); AccessibilityWindowInfo currentWindow = manager.getCurrentWindow(false /* useInputFocus */); assertEquals(windows.get(2).getId(), manager.getPreviousWindow(currentWindow).getId()); }