Example usage for android.view.accessibility AccessibilityEvent TYPE_WINDOWS_CHANGED

List of usage examples for android.view.accessibility AccessibilityEvent TYPE_WINDOWS_CHANGED

Introduction

In this page you can find the example usage for android.view.accessibility AccessibilityEvent TYPE_WINDOWS_CHANGED.

Prototype

int TYPE_WINDOWS_CHANGED

To view the source code for android.view.accessibility AccessibilityEvent TYPE_WINDOWS_CHANGED.

Click Source Link

Document

Represents the event change in the system windows shown on the screen.

Usage

From source file:com.android.talkback.eventprocessor.ProcessorAccessibilityHints.java

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (!areHintsEnabled()) {
        return;/*from   w ww .  j a  v a 2 s .c  om*/
    }

    // Clear hints that were generated before a click or in an old window configuration.
    final int eventType = event.getEventType();
    if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED
            || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            || eventType == AccessibilityEvent.TYPE_WINDOWS_CHANGED) {
        cancelA11yHint();
        return;
    }

    if (eventType == AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
        EventState eventState = EventState.getInstance();
        if (eventState.checkAndClearRecentEvent(EventState.EVENT_SKIP_HINT_AFTER_GRANULARITY_MOVE)) {
            return;
        }
        if (eventState.checkAndClearRecentEvent(EventState.EVENT_SKIP_HINT_AFTER_CURSOR_CONTROL)) {
            return;
        }

        AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
        AccessibilityNodeInfoCompat source = record.getSource();
        if (source != null) {
            postA11yHintRunnable(source);
            // DO NOT RECYCLE. postA11yHintRunnable will save the node.
        }
    }
}

From source file:com.android.screenspeak.SavedNode.java

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
        clearCache();/*from w w w  .  ja v a 2s .  co  m*/
        break;
    case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED:
        AccessibilityNodeInfo source = event.getSource();
        if (source != null) {
            AccessibilityNodeInfoCompat copyNode = new AccessibilityNodeInfoCompat(
                    AccessibilityNodeInfo.obtain(source));
            Selection selection = new Selection(event.getFromIndex(), event.getToIndex());
            mSelectionCache.put(copyNode, selection);
        }
        break;
    }
}

From source file:com.android.utils.AccessibilityEventUtils.java

public static int[] getAllEventTypes() {
    return new int[] { AccessibilityEvent.TYPE_ANNOUNCEMENT, AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT,
            AccessibilityEvent.TYPE_GESTURE_DETECTION_END, AccessibilityEvent.TYPE_GESTURE_DETECTION_START,
            AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED,
            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START,
            AccessibilityEvent.TYPE_TOUCH_INTERACTION_END, AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED,
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, AccessibilityEvent.TYPE_VIEW_CLICKED,
            AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED, AccessibilityEvent.TYPE_VIEW_FOCUSED,
            AccessibilityEvent.TYPE_VIEW_HOVER_ENTER, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT,
            AccessibilityEvent.TYPE_VIEW_LONG_CLICKED, AccessibilityEvent.TYPE_VIEW_SCROLLED,
            AccessibilityEvent.TYPE_VIEW_SELECTED, AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED,
            AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
            AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
            AccessibilityEvent.TYPE_WINDOWS_CHANGED, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED };
}

From source file:com.android.talkback.eventprocessor.ProcessorScreen.java

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    if (eventType != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            && eventType != AccessibilityEvent.TYPE_WINDOWS_CHANGED) {
        return;/* www  .ja v  a2s.c  o  m*/
    }

    int windowIdABefore = mWindowIdA;
    CharSequence windowTitleABefore = getWindowTitle(mWindowIdA);
    int windowIdBBefore = mWindowIdB;
    CharSequence windowTitleBBefore = getWindowTitle(mWindowIdB);
    int accessibilityOverlayWindowIdBefore = mAccessibilityOverlayWindowId;
    CharSequence accessibilityOverlayWindowTitleBefore = getWindowTitle(mAccessibilityOverlayWindowId);

    updateWindowTitlesMap(event);
    updateScreenState(event);

    // If there is no screen update, do not provide spoken feedback.
    if (windowIdABefore == mWindowIdA && TextUtils.equals(windowTitleABefore, getWindowTitle(mWindowIdA))
            && windowIdBBefore == mWindowIdB && TextUtils.equals(windowTitleBBefore, getWindowTitle(mWindowIdB))
            && accessibilityOverlayWindowIdBefore == mAccessibilityOverlayWindowId && TextUtils.equals(
                    accessibilityOverlayWindowTitleBefore, getWindowTitle(mAccessibilityOverlayWindowId))) {
        return;
    }

    // If the user performs a cursor control(copy, paste, start selection mode, etc) in the
    // local context menu and lands back to the edit text, a TYPE_WINDOWS_CHANGED and a
    // TYPE_WINDOW_STATE_CHANGED events will be fired. We should skip these two events to
    // avoid announcing the window title.
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED && EventState.getInstance()
            .checkAndClearRecentEvent(EventState.EVENT_SKIP_WINDOWS_CHANGED_PROCESSING_AFTER_CURSOR_CONTROL)) {
        return;
    }
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            && EventState.getInstance().checkAndClearRecentEvent(
                    EventState.EVENT_SKIP_WINDOW_STATE_CHANGED_PROCESSING_AFTER_CURSOR_CONTROL)) {
        return;
    }

    // Generate spoken feedback.
    CharSequence utterance;
    boolean isUiStabilized;
    if (mAccessibilityOverlayWindowId != WINDOW_ID_NONE) {
        // Case where accessibility overlay is shown. Use separated logic for accessibility
        // overlay not to say out of split screen mode, e.g. accessibility overlay is shown when
        // user is in split screen mode.
        utterance = getWindowTitleForFeedback(mAccessibilityOverlayWindowId);
        isUiStabilized = true;
    } else if (mWindowIdB == WINDOW_ID_NONE) {
        // Single window mode.
        CharSequence windowTitleA = getWindowTitle(mWindowIdA);
        if (windowTitleA == null) {
            // In single window mode, do not provide feedback if window title is not set.
            return;
        }

        utterance = getWindowTitleForFeedback(mWindowIdA);

        if (IS_IN_ARC) {
            // If windowIdABefore was WINDOW_ID_NONE, we consider it as the focus comes into Arc
            // window.
            utterance = formatAnnouncementForArc(utterance,
                    windowIdABefore == WINDOW_ID_NONE /* focusIntoArc */);
        }

        // Consider UI is stabilized if it's alert dialog to provide faster feedback.
        isUiStabilized = !mIsSplitScreenModeAvailable || isAlertDialog(mWindowIdA);
    } else {
        // Split screen mode.
        int feedbackTemplate;
        if (mService.isScreenOrientationLandscape()) {
            if (mService.isScreenLayoutRTL()) {
                feedbackTemplate = R.string.template_split_screen_mode_landscape_rtl;
            } else {
                feedbackTemplate = R.string.template_split_screen_mode_landscape_ltr;
            }
        } else {
            feedbackTemplate = R.string.template_split_screen_mode_portrait;
        }

        utterance = mService.getString(feedbackTemplate, getWindowTitleForFeedback(mWindowIdA),
                getWindowTitleForFeedback(mWindowIdB));
        isUiStabilized = !mIsSplitScreenModeAvailable || isAlertDialog(mWindowIdA) || isAlertDialog(mWindowIdB);
    }

    // Speak.
    if (!isUiStabilized) {
        // If UI is not stabilized, wait SCREEN_FEEDBACK_DELAY for next accessibility event.
        speakLater(utterance, SCREEN_FEEDBACK_DELAY);
    } else {
        speak(utterance);
    }
}

From source file:com.android.talkback.formatter.TouchExplorationFormatter.java

/**
 * Resets cached scrollable state when touch exploration after window state
 * changes.//from   w ww.j a  v  a2s  . co m
 */
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        // Reset cached scrollable state.
        mLastNodeWasScrollable = false;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Store window title in the map.
            List<CharSequence> titles = event.getText();
            if (titles.size() > 0) {
                AccessibilityNodeInfo node = event.getSource();
                if (node != null) {
                    int windowType = getWindowType(node);
                    if (windowType == AccessibilityWindowInfo.TYPE_APPLICATION
                            || windowType == AccessibilityWindowInfo.TYPE_SYSTEM) {
                        mWindowTitlesMap.put(node.getWindowId(), titles.get(0));
                    }
                    node.recycle();
                }
            }
        }
        break;
    case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Copy key set not to modify original map.
            HashSet<Integer> windowIdsToBeRemoved = new HashSet<Integer>();
            windowIdsToBeRemoved.addAll(mWindowTitlesMap.keySet());

            // Enumerate window ids to be removed.
            List<AccessibilityWindowInfo> windows = mService.getWindows();
            for (AccessibilityWindowInfo window : windows) {
                windowIdsToBeRemoved.remove(window.getId());
            }

            // Delete titles of non-existing window ids.
            for (Integer windowId : windowIdsToBeRemoved) {
                mWindowTitlesMap.remove(windowId);
            }
        }
        break;
    }
}

From source file:com.android.screenspeak.eventprocessor.AccessibilityEventProcessor.java

public void onAccessibilityEvent(AccessibilityEvent event) {
    if (mTestingListener != null) {
        mTestingListener.onAccessibilityEvent(event);
    }//from  w w w.ja  v  a  2 s . com

    // Chrome clears and set a11y focus for each scroll event, it is not intended to be spoken
    // to the user. Remove this when chromium is fixed.
    int eventType = event.getEventType();
    if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED) {
        if (sGetSourceNodeIdMethod != null) {
            try {
                mLastClearedSourceId = (long) sGetSourceNodeIdMethod.invoke(event);
                mLastClearedWindowId = event.getWindowId();
                mLastClearA11yFocus = System.currentTimeMillis();
                if (mLastClearedSourceId != mLastPronouncedSourceId
                        || mLastClearedWindowId != mLastPronouncedWindowId) {
                    // something strange. not accessibility focused node sends clear focus event
                    // b/22108305
                    mLastClearedSourceId = -1;
                    mLastClearedWindowId = -1;
                    mLastClearA11yFocus = 0;
                }
            } catch (Exception e) {
                Log.d(LOGTAG, "Exception accessing field: " + e.toString());
            }
        }

        return;
    }

    if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
        if (System.currentTimeMillis() - mLastClearA11yFocus < CLEAR_SET_A11Y_FOCUS_WINDOW) {
            if (sGetSourceNodeIdMethod != null) {
                try {
                    long sourceId = (long) sGetSourceNodeIdMethod.invoke(event);
                    int windowId = event.getWindowId();
                    if (sourceId == mLastClearedSourceId && windowId == mLastClearedWindowId) {
                        return;
                    }
                    mLastPronouncedSourceId = sourceId;
                    mLastPronouncedWindowId = windowId;
                } catch (Exception e) {
                    Log.d(LOGTAG, "Exception accessing field: " + e.toString());
                }
            }
        }
    }

    if (shouldDropEvent(event)) {
        return;
    }

    maintainExplorationState(event);

    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
            || event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            || event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED) {
        mService.setRootDirty(true);
    }

    processEvent(event);
}

From source file:com.android.talkback.eventprocessor.AccessibilityEventProcessor.java

public void onAccessibilityEvent(AccessibilityEvent event) {
    if (mTestingListener != null) {
        mTestingListener.onAccessibilityEvent(event);
    }//from  w w w .  j a  v a  2s  . com

    if ((mDumpEventMask & event.getEventType()) != 0) {
        Log.v(DUMP_EVNET_LOG_TAG, event.toString());
    }

    if (shouldDropRefocusEvent(event)) {
        return;
    }

    if (shouldDropEvent(event)) {
        return;
    }

    maintainExplorationState(event);

    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
            || event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            || event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED) {
        mService.setRootDirty(true);
    }

    // We need to save the last focused event so that we can filter out related selected events.
    if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
        if (mLastFocusedEvent != null) {
            mLastFocusedEvent.recycle();
        }

        mLastFocusedEvent = AccessibilityEvent.obtain(event);
    }

    if (AccessibilityEventUtils.eventMatchesAnyType(event, MASK_DELAYED_EVENT_TYPES)) {
        mHandler.postProcessEvent(event);
    } else {
        processEvent(event);
    }

    if (mTestingListener != null) {
        mTestingListener.afterAccessibilityEvent(event);
    }
}

From source file:com.android.talkback.eventprocessor.ProcessorScreen.java

private void updateWindowTitlesMap(AccessibilityEvent event) {
    switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
        // If split screen mode is NOT available, we only need to care single window.
        if (!mIsSplitScreenModeAvailable) {
            mWindowTitlesMap.clear();//from  w  ww.  j  a  v  a  2  s.  c o m
        }

        int windowId = getWindowId(event);
        boolean shouldAnnounceEvent = shouldAnnounceEvent(event, windowId);
        CharSequence title = getWindowTitleFromEvent(event, shouldAnnounceEvent /* useContentDescription */);
        if (title != null) {
            if (shouldAnnounceEvent) {
                // When software keyboard is shown or hidden, TYPE_WINDOW_STATE_CHANGED
                // is dispatched with text describing the visibility of the keyboard.
                speakWithFeedback(title);
            } else {
                mWindowTitlesMap.put(windowId, title);

                if (getWindowType(event) == AccessibilityWindowInfo.TYPE_SYSTEM) {
                    mSystemWindowIdsSet.add(windowId);
                }

                CharSequence eventWindowClassName = event.getClassName();
                mWindowToClassName.put(windowId, eventWindowClassName);
                mWindowToPackageName.put(windowId, event.getPackageName());
            }
        }
    }
        break;
    case AccessibilityEvent.TYPE_WINDOWS_CHANGED: {
        HashSet<Integer> windowIdsToBeRemoved = new HashSet<Integer>(mWindowTitlesMap.keySet());
        List<AccessibilityWindowInfo> windows = mService.getWindows();
        for (AccessibilityWindowInfo window : windows) {
            windowIdsToBeRemoved.remove(window.getId());
        }
        for (Integer windowId : windowIdsToBeRemoved) {
            mWindowTitlesMap.remove(windowId);
            mSystemWindowIdsSet.remove(windowId);
            mWindowToClassName.remove(windowId);
            mWindowToPackageName.remove(windowId);
        }
    }
        break;
    }
}

From source file:com.android.talkback.eventprocessor.ProcessorScreen.java

private void updateScreenState(AccessibilityEvent event) {
    switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        // Do nothing if split screen mode is available since it can be covered by
        // TYPE_WINDOWS_CHANGED events.
        if (mIsSplitScreenModeAvailable) {
            return;
        }//from   w  w  w .ja  v  a 2  s  .co  m

        mWindowIdA = getWindowId(event);
        break;
    case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
        // Do nothing if split screen mode is NOT available since it can be covered by
        // TYPE_WINDOW_STATE_CHANGED events.
        if (!mIsSplitScreenModeAvailable) {
            return;
        }

        ArrayList<AccessibilityWindowInfo> applicationWindows = new ArrayList<>();
        ArrayList<AccessibilityWindowInfo> systemWindows = new ArrayList<>();
        ArrayList<AccessibilityWindowInfo> accessibilityOverlayWindows = new ArrayList<>();
        List<AccessibilityWindowInfo> windows = mService.getWindows();

        // If there are no windows available, clear the cached IDs.
        if (windows.isEmpty()) {
            mAccessibilityOverlayWindowId = WINDOW_ID_NONE;
            mWindowIdA = WINDOW_ID_NONE;
            mWindowIdB = WINDOW_ID_NONE;
            return;
        }

        for (int i = 0; i < windows.size(); i++) {
            AccessibilityWindowInfo window = windows.get(i);
            switch (window.getType()) {
            case AccessibilityWindowInfo.TYPE_APPLICATION:
                if (window.getParent() == null) {
                    applicationWindows.add(window);
                }
                break;
            case AccessibilityWindowInfo.TYPE_SYSTEM:
                systemWindows.add(window);
                break;
            case AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY:
                accessibilityOverlayWindows.add(window);
                break;
            }
        }

        if (accessibilityOverlayWindows.size() == windows.size()) {
            // TODO: investigate whether there is a case where we have more than one
            // accessibility overlay, and add a logic for it if there is.
            mAccessibilityOverlayWindowId = accessibilityOverlayWindows.get(0).getId();
            return;
        }

        mAccessibilityOverlayWindowId = WINDOW_ID_NONE;

        if (applicationWindows.size() == 0) {
            mWindowIdA = WINDOW_ID_NONE;
            mWindowIdB = WINDOW_ID_NONE;

            // If there is no application window but a system window, consider it as a
            // current window. This logic handles notification shade and lock screen.
            if (systemWindows.size() > 0) {
                Collections.sort(systemWindows,
                        new WindowManager.WindowPositionComparator(mService.isScreenLayoutRTL()));

                mWindowIdA = systemWindows.get(0).getId();
            }
        } else if (applicationWindows.size() == 1) {
            mWindowIdA = applicationWindows.get(0).getId();
            mWindowIdB = WINDOW_ID_NONE;
        } else if (applicationWindows.size() == 2) {
            Collections.sort(applicationWindows,
                    new WindowManager.WindowPositionComparator(mService.isScreenLayoutRTL()));

            mWindowIdA = applicationWindows.get(0).getId();
            mWindowIdB = applicationWindows.get(1).getId();
        } else {
            // If there are more than 2 windows, report the active window as the current
            // window.
            for (AccessibilityWindowInfo applicationWindow : applicationWindows) {
                if (applicationWindow.isActive()) {
                    mWindowIdA = applicationWindow.getId();
                    mWindowIdB = WINDOW_ID_NONE;
                    return;
                }
            }
        }
        break;
    }
}

From source file:com.android.talkback.controller.CursorControllerApp.java

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    if (eventType == AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
        final AccessibilityNodeInfo node = event.getSource();
        if (node == null) {
            if (LogUtils.LOG_LEVEL <= Log.WARN) {
                Log.w(LOGTAG, "TYPE_VIEW_ACCESSIBILITY_FOCUSED event without a source.");
            }/* w w  w  . ja  v a  2 s. co  m*/
            return;
        }

        // When a new view gets focus, clear the state of the granularity
        // manager if this event came from a different node than the locked
        // node but from the same window.
        final AccessibilityNodeInfoCompat nodeCompat = new AccessibilityNodeInfoCompat(node);
        mGranularityManager.onNodeFocused(nodeCompat);
        if (mSwitchNodeWithGranularityDirection == AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY) {
            mGranularityManager.navigate(AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
        } else if (mSwitchNodeWithGranularityDirection == AccessibilityNodeInfoCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY) {
            mGranularityManager.startFromLastNode();
            mGranularityManager.navigate(AccessibilityNodeInfoCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
        }
        mSwitchNodeWithGranularityDirection = 0;
        nodeCompat.recycle();
        mReachedEdge = false;
        mGranularityNavigationReachedEdge = false;
    } else if (eventType == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
        final AccessibilityNodeInfo node = event.getSource();
        if (node != null) {
            final AccessibilityNodeInfoCompat nodeCompat = new AccessibilityNodeInfoCompat(node);

            // Note: we also need to check ROLE_EDIT_TEXT for JB MR1 and lower and for
            // Chrome/WebView 51 and lower. We should check isEditable() first because it's
            // more semantically appropriate for what we want.
            if (nodeCompat.isEditable() || Role.getRole(nodeCompat) == Role.ROLE_EDIT_TEXT) {
                AccessibilityNodeInfoUtils.recycleNodes(mLastEditable);
                mLastEditable = nodeCompat;
            } else {
                nodeCompat.recycle();
            }
        }
    } else if (mIsWindowNavigationAvailable && eventType == AccessibilityEvent.TYPE_WINDOWS_CHANGED) {
        // Remove last focused nodes of non-existing windows.
        Set<Integer> windowIdsToBeRemoved = new HashSet(mLastFocusedNodeMap.keySet());
        for (AccessibilityWindowInfo window : mService.getWindows()) {
            windowIdsToBeRemoved.remove(window.getId());
        }
        for (Integer windowIdToBeRemoved : windowIdsToBeRemoved) {
            AccessibilityNodeInfoCompat removedNode = mLastFocusedNodeMap.remove(windowIdToBeRemoved);
            if (removedNode != null) {
                removedNode.recycle();
            }
        }
    }
}