Java Code Examples for android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED

The following examples show how to use android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED . 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: ScrollEventInterpreter.java    From talkback with Apache License 2.0 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event, EventId eventId) {
  switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
      // Window state changes clear the cache.
      cachedPositionInfo.clear();
      break;
    case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
      if (((event.getContentChangeTypes() & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) == 0)
          || !hasValidIndex(event)) {
        break;
      }
      // fall through
    case AccessibilityEvent.TYPE_VIEW_SCROLLED:
      ScrollEventInterpretation interpretation = interpret(event);

      if (interpretation.hasValidIndex && !interpretation.isDuplicateEvent) {
        cacheScrollPositionInfo(event);
      }

      notifyListenersWithInterpretation(event, interpretation, eventId);
      break;
    default:
      break;
  }
}
 
Example 2
Source File: ScrollFeedbackManager.java    From talkback with Apache License 2.0 6 votes vote down vote up
@Override
public void onAccessibilityEvent(
    AccessibilityEvent event, Performance.@Nullable EventId eventId) {
  if (shouldIgnoreEvent(event)) {
    return;
  }

  switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
      // Window state changes clear the cache.
      cachedFromValues.clear();
      cachedItemCounts.clear();
      handler.cancelScrollFeedback();
      break;
    case AccessibilityEvent.TYPE_VIEW_SCROLLED:
    case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
      handler.postScrollFeedback(event, eventId);
      break;
    default: // fall out
  }
}
 
Example 3
Source File: MyAccessibility.java    From MiHomePlus with MIT License 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    SharedPreferences settings = getSharedPreferences(data, 0);
    settingRoom = settings.getString(settingRoomField, "");
    settingDevices = settings.getString(settingDevicesField, "");

    if (settingRoom.equals("") || settingDevices.equals("")) {
        tellUser("配置檔不完整");
        return;
    }

    int eventType = event.getEventType();
    if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        preProcess(event);
        Log.i(TAG, "onAccessibilityEvent");
    }

}
 
Example 4
Source File: CustomLabelManager.java    From brailleback with Apache License 2.0 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    final Locale currentLocale = Locale.getDefault();
    if (!currentLocale.equals(mLastLocale)) {
        // Refresh cache if device locale has changed since the last event
        mLastLocale = currentLocale;
        refreshCacheInternal(null);
    }

    switch (event.getEventType()) {
        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
            prefetchLabelsFromEvent(event);
    }
}
 
Example 5
Source File: fool.java    From stynico with MIT License 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    AccessibilityNodeInfo nodeInfo = event.getSource();
    if (nodeInfo != null) {
        int eventType = event.getEventType();
        if (eventType== AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED ||
                eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            if (handledMap.get(event.getWindowId()) == null) {
                boolean handled = iterateNodesAndHandle(nodeInfo);
                if (handled) {
                    handledMap.put(event.getWindowId(), true);
                }
            }
        }
    }
}
 
Example 6
Source File: dili.java    From styT with Apache License 2.0 6 votes vote down vote up
private void openHongBao(AccessibilityEvent event) {
    String className = event.getClassName().toString();
    //Log.i(TAG,className);
    if (className.equals(QQ_CLASSNAME_WALLET) && isNeedBack) {
        performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
        isNeedBack = false;
    } else if (className.equals(QQ_CLASSNAME_CHAT) || (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && windowState)) {

        //Editor editor = sharedPreferences.edit();

        windowState = true;
        if (!runState) {
            AccessibilityNodeInfo info = event.getSource();
            if (info == null) return;
            getAllHongBao(info);
        }
    } else {
        windowState = false;
    }
}
 
Example 7
Source File: AnalystService.java    From AutoInteraction-Library with Apache License 2.0 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
    if (null == accessibilityEvent) {
        return;
    }
    switch (accessibilityEvent.getEventType()) {
        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
            Log.i("AnalystService.onAccessibilityEvent # AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED");
            mLastEventClassName = StringUtil.toNb(accessibilityEvent.getClassName());
            postEvent();
        }
        break;
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
            Log.i("AnalystService.onAccessibilityEvent # AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED");
            if (null != mLastEventClassName) {
                postEvent();
            }
        }
        break;
    }
}
 
Example 8
Source File: fool.java    From styT with Apache License 2.0 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    AccessibilityNodeInfo nodeInfo = event.getSource();
    if (nodeInfo != null) {
        int eventType = event.getEventType();
        if (eventType== AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED ||
                eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            if (handledMap.get(event.getWindowId()) == null) {
                boolean handled = iterateNodesAndHandle(nodeInfo);
                if (handled) {
                    handledMap.put(event.getWindowId(), true);
                }
            }
        }
    }
}
 
Example 9
Source File: OversecAccessibilityService.java    From oversec with GNU General Public License v3.0 6 votes vote down vote up
public void setMonitorEventTypesAll() {
    Ln.d("SERVICE: setMonitorEventTypesAll");

    int mask = AccessibilityEvent.TYPE_WINDOWS_CHANGED
            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
            | AccessibilityEvent.TYPE_VIEW_SCROLLED;

    String packagename = mCore.getCurrentPackageName();

    if (packagename == null || mDb.isShowInfoOnTap(packagename)) {
        Ln.d("SERVICE: setMonitorEventTypesAll adding TYPE_VIEW_CLICKED");
        mask |= AccessibilityEvent.TYPE_VIEW_CLICKED;
    }
    if (packagename == null || mDb.isShowInfoOnLongTap(packagename) || mDb.isToggleEncryptButtonOnLongTap(packagename)) {
        Ln.d("SERVICE: setMonitorEventTypesAll adding TYPE_VIEW_LONG_CLICKED");
        mask |= AccessibilityEvent.TYPE_VIEW_LONG_CLICKED;
    }

    boolean includeNotImportantViews = packagename == null ? true : mDb.isIncludeNonImportantViews(packagename);

    setMonitorEventTypes(mask, includeNotImportantViews, true);


}
 
Example 10
Source File: Until.java    From JsDroidCmd with Mozilla Public License 2.0 6 votes vote down vote up
/** Returns a condition that depends on a new window having appeared. */
public static EventCondition<Boolean> newWindow() {
    return new EventCondition<Boolean>() {
        private int mMask = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED |
                AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;

        @Override
        Boolean apply(AccessibilityEvent event) {
            mMask &= ~event.getEventType();
            return mMask == 0;
        }

        @Override
        Boolean getResult() {
            return mMask == 0;
        }
    };
}
 
Example 11
Source File: WechatService.java    From WechatHook-Dusan with Apache License 2.0 6 votes vote down vote up
private void handleEvent(AccessibilityEvent event) {
    final int eventType = event.getEventType();
    String className = event.getClassName().toString();

    //通知栏事件
    if (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
        handleNotificationEvent(event);//64
    } else if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
        if (WechatUI.UI_LUANCHER.equals(className)) {
            enterNearby(service);
            startTime = System.currentTimeMillis();
        }
    } else if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        mockNearByFriends(event);
        backHome(className);
    } else if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
        //CommonUtil.init().sendText(service);
    } else if (AccessibilityEvent.TYPE_VIEW_SCROLLED == eventType) {//4096
        timeOutAndQuit();
    }
}
 
Example 12
Source File: AccessibilityUtils.java    From litho with Apache License 2.0 6 votes vote down vote up
public static boolean enabledServiceCanFocusAndRetrieveWindowContent(
    AccessibilityManager manager) {
  List<AccessibilityServiceInfo> enabledServices =
      manager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

  if (enabledServices == null) {
    return false;
  }

  for (AccessibilityServiceInfo serviceInfo : enabledServices) {
    int eventTypes = serviceInfo.eventTypes;
    if ((eventTypes & AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
        != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
      continue;
    }
    int capabilities = AccessibilityServiceInfoCompat.getCapabilities(serviceInfo);
    if ((capabilities & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT)
        == AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) {
      return true;
    }
  }

  return false;
}
 
Example 13
Source File: ContentChangeWatcher.java    From SoloPi with Apache License 2.0 5 votes vote down vote up
@Subscriber(@Param(value = Constant.EVENT_ACCESSIBILITY_EVENT, sticky = false))
public void onAccessibilityEvent(UniversalEventBean eventBean) {
    Integer eventType = eventBean.getParam(Constant.KEY_ACCESSIBILITY_TYPE);
    LogUtil.d(TAG, "【ChangeWatcher】收到辅助功能事件=%d", eventType);
    if (eventType != null) {
        switch (eventType) {
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
            case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
                lastWatchingTime = System.currentTimeMillis();
                break;
        }
    }
}
 
Example 14
Source File: MemoryAccessibilityService.java    From FileManager with Apache License 2.0 5 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    mRootNodeInfo = event.getSource();

    if (event.getClassName().equals("com.android.settings.applications.InstalledAppDetailsTop")) {
        switch (event.getEventType()) {
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                //进行强制停止后的检查
                checkStop();
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                //查找停止按钮
                mForceStopNode = getTextNode(getString(R.string.accessibility_stop));
                if (mForceStopNode != null && mCertainNode == null) {
                    //判断是否可用点击,不可以点击直接跳过
                    if (mForceStopNode.isClickable() && mForceStopNode.isEnabled()) {
                        mForceStopNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }

                //查找确定按钮,直接点击结束。这里需要附带forcestop按钮的原因是因为某些设置页面也会有"确定"按钮,为了防止误点。
                //当两个条件都满足的时候才认为是进程关闭页面
                mCertainNode = getTextNode(getString(R.string.accessibility_ok));
                if (mCertainNode != null) {
                    mCertainNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
                break;
        }
    }
}
 
Example 15
Source File: WindowChangeEventProvider.java    From PrivacyStreams with Apache License 2.0 5 votes vote down vote up
public void handleAccessibilityEvent(AccessibilityEvent event, AccessibilityNodeInfo rootNode){
    int eventType = event.getEventType();
    if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
            || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            || eventType == AccessibilityEvent.TYPE_WINDOWS_CHANGED
            || eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED)
    {
        this.output(new AccEvent(event, rootNode));
    }

}
 
Example 16
Source File: AutofillManager.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
@Override
public int getRelevantEventTypes(int relevantEventTypes) {
    return relevantEventTypes | AccessibilityEvent.TYPE_VIEW_FOCUSED
            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
            | AccessibilityEvent.TYPE_VIEW_CLICKED
            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
}
 
Example 17
Source File: peService.java    From styT with Apache License 2.0 4 votes vote down vote up
/**
 * 描述:所有事件响应的时候会回调
 * 作者:卜俊文
 * 邮箱:[email protected]
 * 日期:2017/11/6 上午9:26
 */
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    SharedPreferences sharedPreferences = getSharedPreferences("nico.styTool_preferences", MODE_PRIVATE);
    boolean isFirstRun = sharedPreferences.getBoolean("ok_c", true);
    //Editor editor = sharedPreferences.edit();
    if (isFirstRun) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setContentTitle("妮哩");
        builder.setContentText("QQ抢红包正在运行");
        builder.setOngoing(true);
        Notification notification = builder.build();
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(57, notification);
    } else {

    }
    //验证抢红包的开关
    if (!invalidEnable()) {
        return;
    }

    //事件类型
    int eventType = event.getEventType();

    //获取包名
    CharSequence packageName = event.getPackageName();
    if (TextUtils.isEmpty(packageName)) {
        return;
    }

    switch (eventType) {

        //状态栏变化
        case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:

            if (QQConstant.QQ_PACKAGE_NAME.equals(packageName)) {
                //处理状态栏上QQ的消息,如果是红包就跳转过去
                progressQQStatusBar(event);
            }
            break;

        //窗口切换的时候回调
        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
            if (QQConstant.QQ_PACKAGE_NAME.equals(packageName)) {
                //处理正在QQ聊天窗口页面,有其他群或者人有新的红包提醒,跳转过去。
                progressNewMessage(event);
                //处理聊天页面的红包
                progressQQChat(event);
            }

            break;
    }


}
 
Example 18
Source File: AccessibilityEventUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
public static String typeToString(int eventType) {
  switch (eventType) {
    case AccessibilityEvent.TYPE_ANNOUNCEMENT:
      return "TYPE_ANNOUNCEMENT";
    case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT:
      return "TYPE_ASSIST_READING_CONTEXT";
    case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
      return "TYPE_GESTURE_DETECTION_END";
    case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
      return "TYPE_GESTURE_DETECTION_START";
    case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
      return "TYPE_NOTIFICATION_STATE_CHANGED";
    case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
      return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
    case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
      return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
    case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
      return "TYPE_TOUCH_INTERACTION_END";
    case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
      return "TYPE_TOUCH_INTERACTION_START";
    case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
      return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
    case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
      return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
    case AccessibilityEvent.TYPE_VIEW_CLICKED:
      return "TYPE_VIEW_CLICKED";
    case AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED:
      return "TYPE_VIEW_CONTEXT_CLICKED";
    case AccessibilityEvent.TYPE_VIEW_FOCUSED:
      return "TYPE_VIEW_FOCUSED";
    case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
      return "TYPE_VIEW_HOVER_ENTER";
    case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
      return "TYPE_VIEW_HOVER_EXIT";
    case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED:
      return "TYPE_VIEW_LONG_CLICKED";
    case AccessibilityEvent.TYPE_VIEW_SCROLLED:
      return "TYPE_VIEW_SCROLLED";
    case AccessibilityEvent.TYPE_VIEW_SELECTED:
      return "TYPE_VIEW_SELECTED";
    case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
      return "TYPE_VIEW_TEXT_CHANGED";
    case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED:
      return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
    case AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY:
      return "TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY";
    case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
      return "TYPE_WINDOWS_CHANGED";
    case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
      return "TYPE_WINDOW_CONTENT_CHANGED";
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
      return "TYPE_WINDOW_STATE_CHANGED";
    default:
      return "(unhandled)";
  }
}
 
Example 19
Source File: SaiyAccessibilityService.java    From Saiy-PS with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
     * Set the content this service should be receiving
     */
    private void setDynamicContent() {
        if (DEBUG) {
            MyLog.i(CLS_NAME, "setDynamicContent: interceptGoogle: " + initInterceptGoogle);
            MyLog.i(CLS_NAME, "setDynamicContent: announceNotifications: " + initAnnounceNotifications);
        }

        if (!initInterceptGoogle && !initAnnounceNotifications) {
            if (DEBUG) {
                MyLog.i(CLS_NAME, "setDynamicContent: none required: finishing");
            }

//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//                this.disableSelf();
//            }
//
//            this.stopSelf();

        } else {
            if (DEBUG) {
                MyLog.i(CLS_NAME, "setDynamicContent: updating content");
            }

            final AccessibilityServiceInfo serviceInfo = new AccessibilityServiceInfo();

            serviceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
            serviceInfo.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
            serviceInfo.notificationTimeout = UPDATE_TIMEOUT;

            if (initInterceptGoogle && initAnnounceNotifications) {
                serviceInfo.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
                        | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
                        | AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
            } else if (initInterceptGoogle) {
                serviceInfo.packageNames = new String[]{Installed.PACKAGE_NAME_GOOGLE_NOW};
                serviceInfo.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
                        | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
            } else {
                serviceInfo.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
            }

            this.setServiceInfo(serviceInfo);
        }
    }
 
Example 20
Source File: ScrollEventInterpreter.java    From talkback with Apache License 2.0 4 votes vote down vote up
private ScrollEventInterpretation interpret(AccessibilityEvent event) {
  AccessibilityNodeInfo sourceNode = event.getSource();
  if (sourceNode == null) {
    return ScrollEventInterpretation.DEFAULT_INTERPRETATION;
  }

  // . We get scroll position WINDOW_CONTENT_CHANGED events to provide more fine-grained
  // scroll action detection. We need to carefully handle these events. Event if the position
  // changes, it might not result from scroll action. We need a solid strategy to protect against
  // this issue. It's difficult. The least effort we can do is to filter out non-scrollable node.
  if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
      && !AccessibilityNodeInfoUtils.isScrollable(AccessibilityNodeInfoCompat.wrap(sourceNode))) {
    return ScrollEventInterpretation.DEFAULT_INTERPRETATION;
  }

  final NodeIdentifier sourceNodeIdentifier = new NodeIdentifier(sourceNode);
  AccessibilityNodeInfoUtils.recycleNodes(sourceNode);

  @SearchDirectionOrUnknown
  final int scrollDirection = getScrollDirection(sourceNodeIdentifier, event);
  @UserAction final int userAction;
  final int scrollInstanceId;

  @Nullable AutoScrollRecord autoScrollRecord = isFromAutoScrollAction(event);
  if (autoScrollRecord == null) {
    scrollInstanceId = SCROLL_INSTANCE_ID_UNDEFINED;
    // Note that TYPE_WINDOW_CONTENT_CHANGED events can also be interpreted as manual scroll
    // action. TYPE_VIEW_SCROLLED events are filed at very coarse granularity. If we rely only on
    // TYPE_VIEW_SCROLLED events to detect manual scroll action, it happens when the user slightly
    // scroll a list and accessibility focus goes off screen, we don't receive
    // TYPE_VIEW_SCROLLED event thus we don't update accessibility focus. If user performs linear
    // navigation after that, accessibility focus might go to the beginning of screen.
    // We take into account TYPE_WINDOW_CONTENT_CHANGED events to provide more
    // fine-grained manual scroll callback.
    userAction =
        scrollDirection == TraversalStrategy.SEARCH_FOCUS_UNKNOWN
            ? ACTION_UNKNOWN
            : ACTION_MANUAL_SCROLL;
  } else {
    scrollInstanceId = autoScrollRecord.scrollInstanceId;
    userAction = autoScrollRecord.userAction;
  }

  final boolean hasValidIndex = hasValidIndex(event);
  final boolean isDuplicateEvent = hasValidIndex && isDuplicateEvent(sourceNodeIdentifier, event);

  return new ScrollEventInterpretation(
      userAction, scrollDirection, hasValidIndex, isDuplicateEvent, scrollInstanceId);
}