Implementation of Android T window click filtering function

background

Some applications may have transparent windows or interface abnormalities that prevent the current page from triggering click events. If you want to solve this problem from the input side, how should you deal with it?

Ideas

1. dumpsys SurfaceFlingerFind the currently problematic window
2. Clarify the process and find the code related to the filter window

3. Find the key method and try to modify it.
There is a call in the InputDispatcher::findTouchedWindowTargetsLocked method
sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked( displayId, x, y, isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
to find the windowHandle of the corresponding window.

sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
                                                                int32_t y, TouchState* touchState,
                                                                bool isStylus,
                                                                bool addOutsideTargets,
                                                                bool ignoreDragWindow) {
    
    
    if (addOutsideTargets && touchState == nullptr) {
    
    
        LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets");
    }
    // Traverse windows from front to back to find touched window.
    //遍历所有窗口
    const auto& windowHandles = getWindowHandlesLocked(displayId);
    for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
    
    
        if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
    
    
            continue;
        }

        const WindowInfo& info = *windowHandle->getInfo();
        //原生窗口过滤条件判断
        if (!info.isSpy() && windowAcceptsTouchAt(info, displayId, x, y, isStylus)) {
    
    
        	//打印log
            ALOGD("InputDispatcher findTouchedWindowAtLocked %s finded  ",windowHandle->getName().c_str());
            //我们需要找到对应窗口名称,例如我这里是找到带有“mysystemdialog”的窗口,可以通过dump SurfaceFlinger来查看当前你需要过滤的问题窗口
            if (windowHandle->getName().find("mysystemdialog")!= std::string::npos){
    
    //注:npos可以表示string的结束位子,是string::type_size 类型的,也就是find()返回的类型。find函数在找不到指定值得情况下会返回string::npos
                ALOGD("%s do not accept any motion ",windowHandle->getName().c_str());
                //跳过当前窗口(即事件不派发到该窗口上)
                continue;
            }
            //返回找到的窗口
            return windowHandle;
        }

        if (addOutsideTargets &&
            info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
    
    
            touchState->addOrUpdateWindow(windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
                                          BitSet32(0));
        }
    }
    return nullptr;
}

bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, int32_t x, int32_t y,
                          bool isStylus) {
    
    
    const auto inputConfig = windowInfo.inputConfig;
    if (windowInfo.displayId != displayId ||
        inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
    
    
        return false;
    }
    const bool windowCanInterceptTouch = isStylus && windowInfo.interceptsStylus();
    if (inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE) && !windowCanInterceptTouch) {
    
    
        return false;
    }
    if (!windowInfo.touchableRegionContainsPoint(x, y)) {
    
    
        return false;
    }
    ALOGD("windowAcceptsTouchAt return true");
    return true;
}

4. Verify the modification
and confirm the code and its modules
. Code path: frameworks/native/services/inputflinger
Compile module: make inputflinger
Generate package directory:
out/target/product/emulator_x86_64/system/lib/libinputflinger.so
out/target/product/emulator_x86_64/system /lib64/libinputflinger.so
push package verification
adb push libinputflinger.so system/lib
adb push libinputflinger.so system/lib64

Guess you like

Origin blog.csdn.net/yimelancholy/article/details/130504875