Android焦点之FocusWindow切换流程

关键调用是setInputWindows

InputDispatcher::dispatchFocusLocked:在这里打印日志"Focus entering" 或 "Focus leaving"

SurfaceFlinger::updateInputFlinger
    notifyWindowInfos();
        mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, mInputWindowCommands.syncInputWindows);
@frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
            listener->onWindowInfosChanged(windowInfos, shouldSync ? mWindowInfosReportedListener : nullptr);
                setInputWindows(handlesPerDisplay);
                    InputDispatcher::setInputWindowsLocked
                        // 对每一个windowInfo进行判断和处理
                        //更新mWindowHandlesByDisplay这个map,然后通过getWindowHandlesLocked()找newFocusedWindowHandle
                        updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);
                            std::vector<sp<WindowInfoHandle>> newHandles;
                            newHandles.push_back(handle);
                            mWindowHandlesByDisplay[displayId] = newHandles;
                        const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
                            auto it = mWindowHandlesByDisplay.find(displayId);
                            return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES;
@frameworks/native/services/inputflinger/dispatcher/FocusResolver.cpp        
                        // 对FocusChanges进行处理,同步给FocusResolver来更新窗口状态
                        std::optional<FocusResolver::FocusChanges> changes = mFocusResolver.setInputWindows(displayId, windowHandles);
                            //当窗口属性更改时,将调用“setInputWindows”。这里我们将检查当前聚焦的窗口是否可以保持聚焦
                            //如果当前聚焦的窗口仍然有资格获得焦点(“isTokenFocusable”返回 OK),那么我们将继续授予它焦点
                            const sp<IBinder> currentFocus = getFocusedWindowToken(displayId); // 获取当前的焦点窗口
                            const std::optional<FocusRequest> request = getFocusRequest(displayId); //请求焦点,WMS把focusRequest发给surfaceFlinger,surfaceFlinger传递到这里。
                            // 根据最新的 FocusRequest 查找下一个焦点令牌。如果请求的焦点窗口无法获得焦点,则焦点将被移除。
                            if (request) {
                                const Focusability result = isTokenFocusable(requestedFocus, windows);
                                // 遍历InputDispatcher中保存的所有窗口信息
                                for (const sp<WindowInfoHandle>& window : windows) {
                                    if (window->getToken() != token) { continue; } // 一直走这个分支的话,就是找不到目标窗口
                                    windowFound = true;
                                    if (window->getInfo()->visible) { visibleWindowFound = true;  } // 窗口可见的
                                    if (!window->getInfo()->focusable) { allWindowsAreFocusable = false; } //窗口就是不能获取焦点
                                // 根据前面的遍历查找结果设置焦点窗口状态
                                if (!windowFound) { return Focusability::NO_WINDOW;  }
                                if (!allWindowsAreFocusable) { return Focusability::NOT_FOCUSABLE; }
                                if (!visibleWindowFound) { return Focusability::NOT_VISIBLE; }
                                return Focusability::OK;  // 仅当窗口可以聚焦时才ok
                                if (result == Focusability::OK) { //只有获取的状态为ok
                                    // 如果可以获取焦点,则更新焦点窗口
                                    return updateFocusedWindow(displayId, "Window became focusable. Previous reason: " + NamedEnum::string(previousResult), requestedFocus, request->windowName);
                            // 无法获取焦点,则焦点为空
                            return updateFocusedWindow(displayId, removeFocusReason, nullptr);
                        if (changes) {  onFocusChangedLocked(*changes); }        //Focus entering 5e40cef org.mozilla.firefox/org.mozilla.fenix.HomeActivity (server), reason=Window became focusable. Previous reason: NOT_VISIBLE 
                            enqueueFocusEventLocked(changes.newFocus, true /*hasFocus*/, changes.reason);
@frameworks/native/services/inputflinger/InputManager.cpp                            
    for (const auto& focusRequest : mInputWindowCommands.focusRequests) { mInputFlinger->setFocusedWindow(focusRequest); }
         /* 将焦点设置到由标记标识的窗口。必须在更新任何输入窗口句柄后调用此函数。Params:
         *  request.token - 输入通道令牌用于标识应该获得焦点的窗口
         *  request.focusedToken - 调用者期望当前关注的令牌。如果指定的令牌与当前聚焦的窗口不匹配,则该请求将被丢弃。
         *                      如果指定的焦点标记与当前焦点窗口匹配,则调用将成功。如果无论当前聚焦的令牌是什么,此调用都应该成功,则将其设置为“null”
         *  request.timestamp - 请求焦点更改时客户端 (wm) 设置的 SYSTEM_TIME_MONOTONIC 时间戳(以纳秒为单位)。如果存在来自另一个源(例如指针向下)的焦点更改请求,这将确定哪个请求优先。*/
        mDispatcher->setFocusedWindow(request);
@frameworks/native/services/inputflinger/dispatcher/FocusResolver.cpp
             //当窗口属性更改时,将调用“setInputWindows”。这里我们将检查当前聚焦的窗口是否可以保持聚焦
             //如果当前聚焦的窗口仍然有资格获得焦点(“isTokenFocusable”返回 OK),那么我们将继续授予它焦点,否则我们将检查先前的焦点请求是否有资格获得焦点。
            std::optional<FocusResolver::FocusChanges> changes = mFocusResolver.setFocusedWindow(request, getWindowHandlesLocked(request.displayId));
                const sp<IBinder> currentFocus = getFocusedWindowToken(displayId);  // 获取当前的焦点窗口
                mFocusRequestByDisplay[displayId] = request;  //赋值mFocusRequestByDisplay
            if (changes) { onFocusChangedLocked(*changes); }  //Focus leaving 9fd3baa org.mozilla.firefox/org.mozilla.fenix.HomeActivity (server), reason=Waiting for window because NO_WINDOW
                if (changes.newFocus) { enqueueFocusEventLocked(changes.newFocus, true /*hasFocus*/, changes.reason); }
                    //该事件应该位于队列的前面,但位于所有其他焦点事件之后,找到最后一个焦点事件,并在其后面插入mInboundQueue队列
                    std::deque<std::shared_ptr<EventEntry>>::reverse_iterator it =  std::find_if(mInboundQueue.rbegin(), mInboundQueue.rend(), [](const std::shared_ptr<EventEntry>& event) { return event->type == EventEntry::Type::FOCUS; });
                    // 维护焦点事件的顺序。在所有其他焦点事件之后插入条目
                    mInboundQueue.insert(it.base(), std::move(focusEntry));
                    
InputDispatcher::dispatchOnce
    dispatchOnceInnerLocked(&nextWakeupTime);
        mPendingEvent = mInboundQueue.front();
        case EventEntry::Type::FOCUS: {
            //关键log"Focus entering" 或 "Focus leaving" 打印地方
            dispatchFocusLocked(currentTime, typedEntry);
                std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") + channel->getName();
                std::string reason = std::string("reason=").append(entry->reason);
                android_log_event_list(LOGTAG_INPUT_FOCUS) << message << reason << LOG_ID_EVENTS;
                dispatchEventLocked(currentTime, entry, {target});

 

相关推荐

  1. Android焦点FocusWindow切换流程

    2024-07-16 15:36:04       20 阅读
  2. Android焦点Focused Window的更新(二)

    2024-07-16 15:36:04       20 阅读
  3. Android 音频焦点管理

    2024-07-16 15:36:04       55 阅读
  4. Android音频焦点

    2024-07-16 15:36:04       26 阅读
  5. Android Audio Focus 音频焦点

    2024-07-16 15:36:04       64 阅读
  6. 自定义android音频焦点

    2024-07-16 15:36:04       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 15:36:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 15:36:04       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 15:36:04       58 阅读
  4. Python语言-面向对象

    2024-07-16 15:36:04       69 阅读

热门阅读

  1. 观察者模式:构建响应式系统的基石

    2024-07-16 15:36:04       25 阅读
  2. 日常学习--Linux命令梳理--20240715

    2024-07-16 15:36:04       20 阅读
  3. Scala学习笔记17: Try与异常处理

    2024-07-16 15:36:04       22 阅读
  4. 全局变量 y1 会和 cmath 标准库中的变量产生冲突

    2024-07-16 15:36:04       19 阅读
  5. Solus Linux简介

    2024-07-16 15:36:04       22 阅读
  6. 0基础学python-8:if,while,for

    2024-07-16 15:36:04       23 阅读
  7. RPC 的原理和示例

    2024-07-16 15:36:04       24 阅读