Andorid 11 InputDispatcher FocusedApplication设置过程分析

在Input ANR中,有一类ANR打印的reason 为 “xx does not have a focused window” ,表明 输入事件 5s 内,只有FocusedApplication,而没找到focused window。本文分析下FocusedApplication的设置过程。

setFocusedApp
源码路径:frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

setFocusedApp被几处地方调用,最常见的就是打开应用时,在realStartActivityLocked方法里面调用。调用链如下:

07-01 13:27:36.475   456  2006 D test    : java.lang.Exception
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.DisplayContent.setFocusedApp(DisplayContent.java:3356)
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.DisplayContent.setFocusedApp(DisplayContent.java:5603)
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.ActivityTaskManagerService.setResumedActivityUncheckLocked(ActivityTaskManagerService.java:5482)
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.Task.onActivityStateChanged(Task.java:1897)
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.ActivityRecord.setState(ActivityRecord.java:4425)
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.ActivityStack.minimalResumeActivityLocked(ActivityStack.java:947)
07-01 13:27:36.475   456  2006 D test    : 	at com.android.server.wm.ActivityStackSupervisor.realStartActivityLocked(ActivityStackSupervisor.java:919)

直接从setFocusedApp开始分析

//frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
boolean setFocusedApp(ActivityRecord newFocus) {
	//省略
    mFocusedApp = newFocus; //可以在dumpsys window 中看到,在wms端,焦点app是哪个
    getInputMonitor().setFocusedAppLw(newFocus);
    updateTouchExcludeRegion();
    return true;
}

setFocusedAppLw

//frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
public void setFocusedAppLw(ActivityRecord newApp) {
	// Focused app has changed.
	mService.mInputManager.setFocusedApplication(mDisplayId,
                newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null);
}

setFocusedApplication

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setFocusedApplication(int displayId, InputApplicationHandle application) {
	nativeSetFocusedApplication(mPtr, displayId, application);
}

接下来就进入到Native层

nativeSetFocusedApplication

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
        jlong ptr, jint displayId, jobject applicationHandleObj) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    im->setFocusedApplication(env, displayId, applicationHandleObj);
}

void NativeInputManager::setFocusedApplication(JNIEnv* env, int32_t displayId,
        jobject applicationHandleObj) {
    sp<InputApplicationHandle> applicationHandle =
            android_view_InputApplicationHandle_getHandle(env, applicationHandleObj);
    mInputManager->getDispatcher()->setFocusedApplication(displayId, applicationHandle);
}

setFocusedApplication

void InputDispatcher::setFocusedApplication(
        int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
    if (DEBUG_FOCUS) {
        ALOGD("setFocusedApplication displayId=%" PRId32 " %s", displayId,
              inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
    }
    { // acquire lock
        std::scoped_lock _l(mLock);

        sp<InputApplicationHandle> oldFocusedApplicationHandle =
                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

        if (oldFocusedApplicationHandle == mAwaitedFocusedApplication &&
            inputApplicationHandle != oldFocusedApplicationHandle) {
            resetNoFocusedWindowTimeoutLocked();
        }

        if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
            if (oldFocusedApplicationHandle != inputApplicationHandle) {
                mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;//保存到mFocusedApplicationHandlesByDisplay容器中
            }
        } else if (oldFocusedApplicationHandle != nullptr) {
            oldFocusedApplicationHandle.clear();
            mFocusedApplicationHandlesByDisplay.erase(displayId);
        }
    } // release lock

    // Wake up poll loop since it may need to make new input dispatching choices.
    mLooper->wake();
}

可以看出,最终保存到 mFocusedApplicationHandlesByDisplay容器中。 key事件的传输过程中,去查找焦点app时,就是在该容器中查找

总结

FocusedApplication的设置是直接由WMS设置给了InputDispatcher,不需要经过Surfaceflinger

在这里插入图片描述

上一篇:线程交互现象


下一篇:ozon跨境电商可以做吗,俄罗斯ozon跨境电商可不可以做