在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 lockstd::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