Java Code Examples for android.view.accessibility.AccessibilityEvent#getEventTime()
The following examples show how to use
android.view.accessibility.AccessibilityEvent#getEventTime() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: TimeCatMonitorService.java From timecat with Apache License 2.0 | 6 votes |
private int getClickType(AccessibilityEvent event) { int type = event.getEventType(); long time = event.getEventTime(); long id = getSourceNodeId(event); if (type != TYPE_VIEW_CLICKED) { mLastClickTime = time; mLastSourceNodeId = -1; return type; } if (id == -1) { mLastClickTime = time; mLastSourceNodeId = -1; return type; } if (type == TYPE_VIEW_CLICKED && time - mLastClickTime <= double_click_interval && id == mLastSourceNodeId) { mLastClickTime = -1; mLastSourceNodeId = -1; return TYPE_VIEW_DOUBLD_CLICKED; } else { mLastClickTime = time; mLastSourceNodeId = id; return type; } }
Example 2
Source File: ScrollEventInterpreter.java From talkback with Apache License 2.0 | 6 votes |
/** Returns AutoScrollRecord if the {@code event} is resulted from cached auto-scroll action. */ private @Nullable AutoScrollRecord isFromAutoScrollAction(AccessibilityEvent event) { @Nullable AutoScrollRecord autoScrollRecord = actorState.getScrollerState().getAutoScrollRecord(); if (autoScrollRecord == null) { return null; } // Note that both TYPE_VIEW_SCROLLED and TYPE_WINDOW_CONTENT_CHANGED events could result from // auto-scroll action. And a single scroll action can trigger multiple scroll events, we'll keep // the autoScrollRecord until next auto scroll happened and use the time diff to distinguish if // the current scroll is from the same scroll action. long timeDiff = event.getEventTime() - autoScrollRecord.autoScrolledTime; if ((timeDiff < 0L) || (timeDiff > SCROLL_TIMEOUT_MS)) { return null; } AccessibilityNodeInfoCompat node = null; try { node = AccessibilityNodeInfoUtils.toCompat(event.getSource()); return autoScrollRecord.scrolledNodeMatches(node) ? autoScrollRecord : null; } finally { AccessibilityNodeInfoUtils.recycleNodes(node); } }
Example 3
Source File: InputFocusInterpreter.java From talkback with Apache License 2.0 | 6 votes |
private boolean isFromSavedFocusAction(AccessibilityEvent event) { if (isLastFocusActionHandled()) { return false; } AccessibilityNodeInfoCompat node = AccessibilityNodeInfoUtils.toCompat(event.getSource()); if (node == null) { return false; } long timeDiff = event.getEventTime() - focuserState.getInputFocusActionRecord().actionTime; boolean isFromFocusAction = ((timeDiff >= 0L) && (timeDiff < INPUT_FOCUS_ACTION_TIMEOUT)) && node.equals(focuserState.getInputFocusActionRecord().inputFocusedNode); AccessibilityNodeInfoUtils.recycleNodes(node); return isFromFocusAction; }
Example 4
Source File: PushMonitorAccessibilityService.java From NewsPushMonitor with Apache License 2.0 | 5 votes |
@Override public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) { int type = accessibilityEvent.getEventType(); if (type != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) { return; } String pkg = accessibilityEvent.getPackageName().toString(); long time = accessibilityEvent.getEventTime(); Notification notification = (Notification) accessibilityEvent.getParcelableData(); List<CharSequence> texts = accessibilityEvent.getText(); StringBuilder sb = new StringBuilder(); for (CharSequence text : texts) { sb.append(text).append("###"); } LogWriter.i(TAG, "onAccessibilityEvent " + "package=" + pkg + ",time=" + time + ",text=" + sb.toString()); LogWriter.i(TAG, "Parse notification for " + pkg + " begin!"); BaseNotificationParser notificationParser = NotificationParserFactory.getNotificationParser(pkg); BaseNotificationParser.NewsInfo newsInfo = notificationParser.parse(notification); LogWriter.i(TAG, "when:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(newsInfo.when)); LogWriter.i(TAG, "ContentTitle:" + newsInfo.contentTitle); LogWriter.i(TAG, "ContentText:" + newsInfo.contentText); LogWriter.i(TAG, "Url:" + newsInfo.url); LogWriter.i(TAG, "Parse notification for " + pkg + " end!"); LogWriter.i(TAG, "##################################################################"); commitNewsInfoToServer(newsInfo); showNewsInfo(newsInfo); }
Example 5
Source File: EventFilter.java From talkback with Apache License 2.0 | 5 votes |
private boolean dropTextChangeEvent(AccessibilityEvent event) { // Drop text change event if we're still waiting for a select event and // the change occurred too soon after the previous change. final long eventTime = event.getEventTime(); if (textEventHistory.getTextChangesAwaitingSelection() > 0) { // If the state is still consistent, update the count and drop // the event, except when running on locales that don't support // text replacement due to character combination complexity. final boolean hasDelayElapsed = ((eventTime - textEventHistory.getLastTextChangeTime()) >= TEXT_CHANGED_DELAY); final boolean hasPackageChanged = !TextUtils.equals( event.getPackageName(), textEventHistory.getLastTextChangePackageName()); boolean canReplace = context.getResources().getBoolean(R.bool.supports_text_replacement); if (!hasDelayElapsed && !hasPackageChanged && canReplace) { textEventHistory.incrementTextChangesAwaitingSelection(1); textEventHistory.setLastTextChangeTime(eventTime); return true; } // The state became inconsistent, so reset the counter. textEventHistory.setTextChangesAwaitingSelection(0); } return false; }
Example 6
Source File: EventFilter.java From talkback with Apache License 2.0 | 5 votes |
private boolean shouldSkipCursorMovementEvent(AccessibilityEvent event) { AccessibilityEvent lastKeptTextSelection = textEventHistory.getLastKeptTextSelection(); if (lastKeptTextSelection == null) { return false; } // If event is at least X later than previous event, then keep it. if (event.getEventTime() - lastKeptTextSelection.getEventTime() > CURSOR_MOVEMENT_EVENTS_DELAY) { textEventHistory.setLastKeptTextSelection(null); return false; } // If event has the same type as previous, it is from a different action, so keep it. if (event.getEventType() == lastKeptTextSelection.getEventType()) { return false; } // If text-selection-change is followed by text-move-with-granularity, skip movement. if (lastKeptTextSelection.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED && event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY) { return true; } return false; }
Example 7
Source File: AccessibilityEventProcessor.java From talkback with Apache License 2.0 | 5 votes |
/** * Helper method for {@link #shouldDropEvent} that filters out selected events that occur in close * proximity to focused events. * * <p>A selected event should be kept if: - The most recent focused event occurred over {@link * #DELAY_SELECTED_AFTER_FOCUS} ms ago. - The most recent focused event occurred on a different * branch of the accessibility node tree, i.e., not in an ancestor or descendant of the selected * event. * * @param event The view-selected event to consider retaining. * @return Whether to retain the event. */ private boolean shouldKeepViewSelectedEvent(final AccessibilityEvent event) { if (lastFocusedEvent == null) { return true; } if (event.getEventTime() - lastFocusedEvent.getEventTime() > DELAY_SELECTED_AFTER_FOCUS) { return true; } // AccessibilityEvent.getSource will obtain() an AccessibilityNodeInfo, so it is our // responsibility to recycle() it. AccessibilityNodeInfo selectedSource = event.getSource(); AccessibilityNodeInfo focusedSource = lastFocusedEvent.getSource(); try { // Note: AccessibilityNodeInfoCompat constructor will silently succeed when wrapping // a null object. if (selectedSource != null && focusedSource != null) { AccessibilityNodeInfoCompat selectedSourceCompat = AccessibilityNodeInfoUtils.toCompat(selectedSource); AccessibilityNodeInfoCompat focusedSourceCompat = AccessibilityNodeInfoUtils.toCompat(focusedSource); if (AccessibilityNodeInfoUtils.areInSameBranch(selectedSourceCompat, focusedSourceCompat)) { return false; } } // In different branch (or we could not check branches of accessibility node tree). return true; } finally { if (selectedSource != null) { selectedSource.recycle(); } if (focusedSource != null) { focusedSource.recycle(); } } }
Example 8
Source File: AccessibilityFocusActionHistory.java From talkback with Apache License 2.0 | 5 votes |
/** * Matches {@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED} event to the source action. * * @param event The {@link AccessibilityEvent} queried. * @return The matched FocusActionRecord or null. */ @Nullable public FocusActionRecord matchFocusActionRecordFromEvent(AccessibilityEvent event) { if (!AccessibilityEventUtils.eventMatchesAnyType( event, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)) { return null; } AccessibilityNodeInfoCompat eventNode = AccessibilityNodeInfoUtils.toCompat(event.getSource()); if (eventNode == null) { return null; } long eventTime = event.getEventTime(); tryMatchingPendingFocusAction(eventNode, eventTime); FocusActionRecord result = null; // Iterate from the newest(last) record to the eldest(first) record. Iterator<FocusActionRecord> iterator = focusActionRecordList.descendingIterator(); while (iterator.hasNext()) { FocusActionRecord record = iterator.next(); long timeDiff = eventTime - record.getActionTime(); AccessibilityNodeInfoCompat recordNode = record.getFocusedNode(); boolean timeMatches = timeDiff >= 0 && timeDiff < TIMEOUT_TOLERANCE_MS; boolean nodeMatches = eventNode.equals(recordNode); AccessibilityNodeInfoUtils.recycleNodes(recordNode); if (timeMatches && nodeMatches) { result = FocusActionRecord.copy(record); break; } } AccessibilityNodeInfoUtils.recycleNodes(eventNode); return result; }
Example 9
Source File: InputFocusInterpreter.java From talkback with Apache License 2.0 | 5 votes |
void registerWindowStateChangeEvent(AccessibilityEvent event) { lastWindowStateChangeEventTime = event.getEventTime(); if (getLastWindowId() != event.getWindowId() && !shouldIgnoreWindowChangeEvent(event)) { setLastWindowIdFromEvent(event.getWindowId()); isFirstFocusInWindow = true; } }
Example 10
Source File: InputFocusInterpreter.java From talkback with Apache License 2.0 | 5 votes |
boolean shouldProcessFocusEvent(AccessibilityEvent event) { boolean isFirstFocus = isFirstFocusInWindow; isFirstFocusInWindow = false; if (getLastWindowId() != event.getWindowId()) { setLastWindowIdFromEvent(event.getWindowId()); return false; } int focusDelay = FeatureSupport.isTv(context) ? MISS_FOCUS_DELAY_TV : MISS_FOCUS_DELAY_NORMAL; return !isFirstFocus || event.getEventTime() - lastWindowStateChangeEventTime > focusDelay; }
Example 11
Source File: ScreenStateMonitor.java From talkback with Apache License 2.0 | 5 votes |
@Override public void onAccessibilityEvent(AccessibilityEvent event, EventId eventId) { if (shouldIgnoreEvent(event)) { return; } List<AccessibilityWindowInfo> currentWindows = AccessibilityServiceCompatUtils.getWindows(service); AccessibilityWindowInfo sourceWindow = getWindowInfoById(currentWindows, event.getWindowId()); // Update window transition info if the windowId is valid. // For pre-P devices, it's mostly a TYPE_WINDOW_STATE_CHANGED event. // For p-devices, it could be either TYPE_WINDOWS_CHANGED or TYPE_WINDOW_STATE_CHANGED event. windowTransitionInfo.updateTransitionInfoFromEvent(sourceWindow, event); ScreenState currentScreenState = createScreenStateSnapShot( currentWindows, AccessibilityServiceCompatUtils.getActiveWidow(service)); if (currentScreenState.equals(lastStableScreenState)) { // If screen state changes several times in a short time, but eventually falls back to the // original stable state, clear the window transition and do not notify screen state changes. cancelPendingScreenStateChangedAndClearCache(); return; } if (latestScreenStateDuringTransition == null) { // This is the first screen state captured during the transition. screenTransitionStartTime = event.getEventTime(); } // Called when any window ID or window title is added/removed/replaced. postDelayNotifyingScreenStateChanged(currentScreenState, eventId); }
Example 12
Source File: AccessibilityEventProcessor.java From PUMA with Apache License 2.0 | 4 votes |
public static AccessibilityEvent waitForLastEvent(final int eventType, final long timeoutMillis) { synchronized (mLock) { mEventQueue.clear(); mWaitingForEventDelivery = true; } AccessibilityEvent ret = null; int eventCnt = 0; long avgDelayMillis = 0, currDelayMillis = 0, EWMAMillis = 0; double ALPHA = 0.5; long lastEventTimeMillis = -1L, currEventTimeMillis; long mTimeoutMillis = timeoutMillis; long startTimeMillis = SystemClock.uptimeMillis(); long restartTimeMillis = startTimeMillis; synchronized (mLock) { try { while (true) { // Drain the event queue while (!mEventQueue.isEmpty()) { AccessibilityEvent event = mEventQueue.remove(0); // Ignore events fromIndex previous interactions. if (event.getEventTime() < startTimeMillis) { continue; } if ((event.getEventType() & eventType) != 0) { currEventTimeMillis = event.getEventTime(); if (lastEventTimeMillis > 0) { currDelayMillis = currEventTimeMillis - lastEventTimeMillis; avgDelayMillis = (eventCnt * avgDelayMillis + currDelayMillis) / (eventCnt + 1); EWMAMillis = (long) (currDelayMillis * ALPHA + avgDelayMillis * (1 - ALPHA)); mTimeoutMillis = Math.min(EWMAMillis, timeoutMillis); } restartTimeMillis = currEventTimeMillis; lastEventTimeMillis = currEventTimeMillis; eventCnt++; ret = event; // Util.log("Got event: " + event); // Util.log("EWMAMillis=" + EWMAMillis + ", mTimeoutMillis=" + mTimeoutMillis); } // event.recycle(); } long elapsedTimeMillis = SystemClock.uptimeMillis() - restartTimeMillis; long remainingTimeMillis = mTimeoutMillis - elapsedTimeMillis; // Util.log("remainingTimeMillis=" + remainingTimeMillis); if (remainingTimeMillis <= 0) { // throw new RuntimeException("No event"); Util.log("TIMEOUT"); break; } try { mLock.wait(remainingTimeMillis); } catch (InterruptedException ie) { } } } finally { mWaitingForEventDelivery = false; mEventQueue.clear(); mLock.notifyAll(); } } return ret; }
Example 13
Source File: UiAutomation.java From android_9.0.0_r45 with Apache License 2.0 | 4 votes |
/** * Executes a command and waits for a specific accessibility event up to a * given wait timeout. To detect a sequence of events one can implement a * filter that keeps track of seen events of the expected sequence and * returns true after the last event of that sequence is received. * <p> * <strong>Note:</strong> It is caller's responsibility to recycle the returned event. * </p> * @param command The command to execute. * @param filter Filter that recognizes the expected event. * @param timeoutMillis The wait timeout in milliseconds. * * @throws TimeoutException If the expected event is not received within the timeout. */ public AccessibilityEvent executeAndWaitForEvent(Runnable command, AccessibilityEventFilter filter, long timeoutMillis) throws TimeoutException { // Acquire the lock and prepare for receiving events. synchronized (mLock) { throwIfNotConnectedLocked(); mEventQueue.clear(); // Prepare to wait for an event. mWaitingForEventDelivery = true; } // Note: We have to release the lock since calling out with this lock held // can bite. We will correctly filter out events from other interactions, // so starting to collect events before running the action is just fine. // We will ignore events from previous interactions. final long executionStartTimeMillis = SystemClock.uptimeMillis(); // Execute the command *without* the lock being held. command.run(); List<AccessibilityEvent> receivedEvents = new ArrayList<>(); // Acquire the lock and wait for the event. try { // Wait for the event. final long startTimeMillis = SystemClock.uptimeMillis(); while (true) { List<AccessibilityEvent> localEvents = new ArrayList<>(); synchronized (mLock) { localEvents.addAll(mEventQueue); mEventQueue.clear(); } // Drain the event queue while (!localEvents.isEmpty()) { AccessibilityEvent event = localEvents.remove(0); // Ignore events from previous interactions. if (event.getEventTime() < executionStartTimeMillis) { continue; } if (filter.accept(event)) { return event; } receivedEvents.add(event); } // Check if timed out and if not wait. final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis; if (remainingTimeMillis <= 0) { throw new TimeoutException("Expected event not received within: " + timeoutMillis + " ms among: " + receivedEvents); } synchronized (mLock) { if (mEventQueue.isEmpty()) { try { mLock.wait(remainingTimeMillis); } catch (InterruptedException ie) { /* ignore */ } } } } } finally { int size = receivedEvents.size(); for (int i = 0; i < size; i++) { receivedEvents.get(i).recycle(); } synchronized (mLock) { mWaitingForEventDelivery = false; mEventQueue.clear(); mLock.notifyAll(); } } }
Example 14
Source File: AccessibilityEventProcessor.java From talkback with Apache License 2.0 | 4 votes |
/** * Returns whether the device should drop this event. Caches notifications if necessary. * * @param event The current event. * @return {@code true} if the event should be dropped. */ private boolean shouldDropEvent(AccessibilityEvent event) { // Always drop null events. if (event == null) { return true; } // Always drop events if the service is suspended. if (!TalkBackService.isServiceActive()) { return true; } // If touch exploration is enabled, drop automatically generated events // that are sent immediately after a window state change... unless we // decide to keep the event. if (AccessibilityManagerCompat.isTouchExplorationEnabled(accessibilityManager) && ((event.getEventType() & AUTOMATIC_AFTER_STATE_CHANGE) != 0) && ((event.getEventTime() - lastWindowStateChanged) < DELAY_AUTO_AFTER_STATE) && !shouldKeepAutomaticEvent(event)) { LogUtils.v(TAG, "Drop event after window state change"); return true; } // Some view-selected events are spurious if sent immediately after a focused event. if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SELECTED && !shouldKeepViewSelectedEvent(event)) { LogUtils.v(TAG, "Drop selected event after focused event"); return true; } boolean isPhoneRinging = voiceActionMonitor != null && voiceActionMonitor.getCurrentCallState() == TelephonyManager.CALL_STATE_RINGING; // Sometimes the dialer's window-state-changed event gets sent right before the // TelephonyManager transitions to CALL_STATE_RINGING, so we need to check isDialerEvent(). isPhoneRinging |= isDialerEvent(event); if (ringerModeAndScreenMonitor != null && !ringerModeAndScreenMonitor.isScreenOn() && !isPhoneRinging) { boolean isNotification = AccessibilityEventUtils.isNotificationEvent(event); if (!speakWhenScreenOff) { // If the user doesn't allow speech when the screen is // off, drop the event immediately. LogUtils.v(TAG, "Drop event due to screen state and user pref"); return true; } else if (!isNotification) { // If the user allows speech when the screen is off, drop // all non-notification events. LogUtils.v(TAG, "Drop non-notification event due to screen state"); return true; } } final boolean canInterruptRadialMenu = AccessibilityEventUtils.eventMatchesAnyType(event, MASK_EVENT_TYPES_INTERRUPT_RADIAL_MENU); final boolean silencedByRadialMenu = (service.getMenuManager().isMenuShowing() && !canInterruptRadialMenu); // Don't speak events that cannot interrupt the radial menu, if showing if (silencedByRadialMenu) { LogUtils.v(TAG, "Drop event due to radial menu state"); return true; } final int touchscreenState = service.getResources().getConfiguration().touchscreen; final boolean isTouchInteractionStateChange = AccessibilityEventUtils.eventMatchesAnyType(event, MASK_EVENT_TYPES_TOUCH_STATE_CHANGES); // Drop all events related to touch interaction state on devices that don't support touch. return (touchscreenState == Configuration.TOUCHSCREEN_NOTOUCH) && isTouchInteractionStateChange; }
Example 15
Source File: InputFocusInterpreter.java From talkback with Apache License 2.0 | 4 votes |
/** * Returns {@code true} if the inputFocusActionRecord is valid, and we're still trying to match it * with TYPE_VIEW_FOCUSED event. */ private boolean conflictWithFocusActionRecord(AccessibilityEvent event) { return !isLastFocusActionHandled() && (event.getEventTime() - focuserState.getInputFocusActionRecord().actionTime < INPUT_FOCUS_ACTION_TIMEOUT); }
Example 16
Source File: EventFilter.java From talkback with Apache License 2.0 | 4 votes |
private boolean shouldDropTextSelectionEvent(AccessibilityEvent event) { // Keep all events other than text-selection. final int eventType = event.getEventType(); if (eventType != AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) { return false; } // Drop selected events until we've matched the number of changed // events. This prevents TalkBack from speaking automatic cursor // movement events that result from typing. if (textEventHistory.getTextChangesAwaitingSelection() > 0) { final boolean hasDelayElapsed = ((event.getEventTime() - textEventHistory.getLastTextChangeTime()) >= TEXT_SELECTION_DELAY); final boolean hasPackageChanged = !TextUtils.equals( event.getPackageName(), textEventHistory.getLastTextChangePackageName()); // If the state is still consistent, update the count and drop the event. if (!hasDelayElapsed && !hasPackageChanged) { textEventHistory.incrementTextChangesAwaitingSelection(-1); textEventHistory.setLastFromIndex(event.getFromIndex()); textEventHistory.setLastToIndex(event.getToIndex()); textEventHistory.setLastNode(event.getSource()); return true; } // The state became inconsistent, so reset the counter. textEventHistory.setTextChangesAwaitingSelection(0); } // Drop selection events from views that don't have input focus. final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event); final AccessibilityNodeInfoCompat source = record.getSource(); boolean isFocused = source != null && source.isFocused(); AccessibilityNodeInfoUtils.recycleNodes(source); if (!isFocused) { LogUtils.v(TAG, "Dropped text-selection event from non-focused field"); return true; } return false; }
Example 17
Source File: AccessibilityEventUtils.java From brailleback with Apache License 2.0 | 4 votes |
/** * @return If the <code>first</code> event is equal to the <code>second</code>. */ public static boolean eventEquals(AccessibilityEvent first, AccessibilityEvent second) { // TODO: The framework should implement AccessibilityEvent#equals() if (first == null || second == null) { return false; } if (first.getEventType() != second.getEventType()) { return false; } if (first.getPackageName() == null) { if (second.getPackageName() != null) { return false; } } else if (!first.getPackageName().equals(second.getPackageName())) { return false; } if (first.getClassName() == null) { if (second.getClassName() != null) { return false; } } else if (!first.getClassName().equals(second.getClassName())) { return false; } if (!first.getText().equals(second.getText())) { // The result of getText() is never null. return false; } if (first.getContentDescription() == null) { if (second.getContentDescription() != null) { return false; } } else if (!first.getContentDescription().equals(second.getContentDescription())) { return false; } if (first.getBeforeText() == null) { if (second.getBeforeText() != null) { return false; } } else if (!first.getBeforeText().equals(second.getBeforeText())) { return false; } if (first.getParcelableData() != null) { // Parcelable data may not implement equals() correctly. return false; } if (first.getAddedCount() != second.getAddedCount()) { return false; } if (first.isChecked() != second.isChecked()) { return false; } if (first.isEnabled() != second.isEnabled()) { return false; } if (first.getFromIndex() != second.getFromIndex()) { return false; } if (first.isFullScreen() != second.isFullScreen()) { return false; } if (first.getCurrentItemIndex() != second.getCurrentItemIndex()) { return false; } if (first.getItemCount() != second.getItemCount()) { return false; } if (first.isPassword() != second.isPassword()) { return false; } if (first.getRemovedCount() != second.getRemovedCount()) { return false; } if (first.getEventTime() != second.getEventTime()) { return false; } return true; }
Example 18
Source File: Performance.java From talkback with Apache License 2.0 | 2 votes |
/** * Constructs an EventId without tracking the event's times. Useful for recreating an id from an * event that was tracked by onEventReceived(), when the event is available but id is not. Try to * use this as little as possible, and instead pass the EventId from onEventReceived(). * * @param event Event that has already been tracked by onEventReceived() * @return EventId of event */ @NonNull public EventId toEventId(@NonNull AccessibilityEvent event) { return new EventId(event.getEventTime(), EVENT_TYPE_ACCESSIBILITY, event.getEventType()); }