InputMonitor层面分析
更多内容qqun:422901085 https://ke.qq.com/course/5992266#term_id=106217431
首先来看一下InputMonitor重要调用几个方法:
void updateInputWindowsLw(boolean force) {
//省略
scheduleUpdateInputWindows();
}
private void scheduleUpdateInputWindows() {
if (mDisplayRemoved) {
return;
}
if (!mUpdateInputWindowsPending) {
mUpdateInputWindowsPending = true;
mHandler.post(mUpdateInputWindows);
}
}
private class UpdateInputWindows implements Runnable {
@Override
public void run() {
synchronized (mService.mGlobalLock) {
mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);//调用updateInputWindows
}
}
}
updateInputWindowsLw属于经常被外部调用的方法,它会最后触发到UpdateInputWindows的run方法执行, 这里调用地方比较多,具体可以自己打印一下堆栈,这里只列出以下几个:
新加入Task时候
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.InputMonitor.updateInputWindowsLw(InputMonitor.java:331)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.DisplayContent.layoutAndAssignWindowLayersIfNeeded(DisplayContent.java:3790)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.Task.onChildPositionChanged(Task.java:5995)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.WindowContainer.onChildAdded(WindowContainer.java:761)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.WindowContainer.setParent(WindowContainer.java:561)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:751)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.TaskFragment.addChild(TaskFragment.java:1835)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.Task.addChild(Task.java:1429)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.ActivityStarter.addOrReparentStartingActivity(ActivityStarter.java:2927)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.ActivityStarter.setNewTask(ActivityStarter.java:2877)
03-30 14:54:49.879 566 765 I WindowManager: at com.android.server.wm.ActivityStarter.startActivityInner(ActivityStarter.java:1864)
TaskDisplayArea.positionChildTaskAt时候
03-30 14:54:49.886 566 765 I WindowManager: java.lang.Exception
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.InputMonitor.updateInputWindowsLw(InputMonitor.java:331)
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.DisplayContent.layoutAndAssignWindowLayersIfNeeded(DisplayContent.java:3790)
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.TaskDisplayArea.positionChildTaskAt(TaskDisplayArea.java:417)
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.TaskDisplayArea.positionChildAt(TaskDisplayArea.java:376)
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.Task.moveToFrontInner(Task.java:4687)
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.Task.moveToFront(Task.java:4662)
03-30 14:54:49.886 566 765 I WindowManager: at com.android.server.wm.ActivityStarter.startActivityInner(ActivityStarter.java:1870)
performSurfacePlacemen时候
03-30 14:54:49.924 566 765 I WindowManager: updateInputWindowsLw
03-30 14:54:49.924 566 765 I WindowManager: java.lang.Exception
03-30 14:54:49.924 566 765 I WindowManager: at com.android.server.wm.InputMonitor.updateInputWindowsLw(InputMonitor.java:331)
03-30 14:54:49.924 566 765 I WindowManager: at com.android.server.wm.RootWindowContainer.lambda$performSurfacePlacementNoTrace$8(RootWindowContainer.java:951)
03-30 14:54:49.924 566 765 I WindowManager: at com.android.server.wm.RootWindowContainer$$ExternalSyntheticLambda49.accept(Unknown Source:2)
03-30 14:54:49.924 566 765 I WindowManager: at com.android.server.wm.RootWindowContainer.forAllDisplays(RootWindowContainer.java:1261)
还有许多地方。。。不列举了
最后会调用到mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);这个关键方法:
private void updateInputWindows(boolean inDrag) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");
//省略
mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */);
updateInputFocusRequest(mRecentsAnimationInputConsumer);
if (!mUpdateInputWindowsImmediately) {
mDisplayContent.getPendingTransaction().merge(mInputTransaction);
mDisplayContent.scheduleAnimation();
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
这里有调用了 mDisplayContent.forAllWindows方法来遍历每一个windowstate执行
自己的accept方法:
@Override
public void accept(WindowState w) {
final InputWindowHandleWrapper inputWindowHandle = w.mInputWindowHandle;
//省略部分
//这里会对每个WindowState转换成inputWindowHandle信息,不过要求得有surface才可以,意味处于NO_SURFACE是不会进入
if (w.mWinAnimator.hasSurface()) {
populateInputWindowHandle(inputWindowHandle, w);
setInputWindowInfoIfNeeded(mInputTransaction,
w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
}
}
}
把WindowState转换成inputWindowHandle后接下来会把这个inputWindowHandle信息设置给mSurfaceControl
@VisibleForTesting
static void setInputWindowInfoIfNeeded(SurfaceControl.Transaction t, SurfaceControl sc,
InputWindowHandleWrapper inputWindowHandle) {
if (inputWindowHandle.isChanged()) {
//这里又调用的是inputWindowHandle.applyChangesToSurface
inputWindowHandle.applyChangesToSurface(t, sc);
}
}
void applyChangesToSurface(@NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl sc) {
t.setInputWindowInfo(sc, mHandle);
//mHandle就是InputWindowHandle对象,调用transitionaction对应方法进行设置
mChanged = false;
}
接下来来到SurfaceControl.java的
public Transaction setInputWindowInfo(SurfaceControl sc, InputWindowHandle handle) {
checkPreconditions(sc);
nativeSetInputWindowInfo(mNativeObject, sc.mNativeObject, handle);
return this;
}
这里一看就是调用是nativeSetInputWindowInfo方法
static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jobject inputWindow) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
sp<NativeInputWindowHandle> handle = android_view_InputWindowHandle_getHandle(
env, inputWindow);//拿java层面的InputWindowHandle构造NativeInputWindowHandle
handle->updateInfo();//关键调用了updateInfo把java层面对象数据进行拷贝到我们的native对象NativeInputWindowHandle中的mInfo中
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
transaction->setInputWindowInfo(ctrl, *handle->getInfo());
}
sp<NativeInputWindowHandle> android_view_InputWindowHandle_getHandle(
JNIEnv* env, jobject inputWindowHandleObj) {
if (!inputWindowHandleObj) {
return NULL;
}
AutoMutex _l(gHandleMutex);
jlong ptr = env->GetLongField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
NativeInputWindowHandle* handle;
if (ptr) {//这个java端的ptr变量,主要功能就是为了保存对应native层面指针地址
handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
} else {
jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
handle = new NativeInputWindowHandle(objWeak);
//java层面对象作为了参数,方便后面调用java对象相关属性
handle->incStrong((void*)android_view_InputWindowHandle_getHandle);
env->SetLongField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
reinterpret_cast<jlong>(handle));
}
return handle;
}
重点看看 handle->updateInfo(),这个只截取部分:
bool NativeInputWindowHandle::updateInfo() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject obj = env->NewLocalRef(mObjWeak);
if (!obj) {
releaseChannel();
return false;
}
mInfo.touchableRegion.clear();
jobject tokenObj = env->GetObjectField(obj, gInputWindowHandleClassInfo.token);
if (tokenObj) {
mInfo.token = ibinderForJavaObject(env, tokenObj);
env->DeleteLocalRef(tokenObj);
} else {
mInfo.token.clear();
}
mInfo.name = getStringField(env, obj, gInputWindowHandleClassInfo.name, "<null>");
mInfo.dispatchingTimeout = std::chrono::milliseconds(
env->GetLongField(obj, gInputWindowHandleClassInfo.dispatchingTimeoutMillis));
//这里可以看出主要就是对java的数据拷贝到这个mInfo
mInfo.frameLeft = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameLeft);
env->DeleteLocalRef(obj);
return true;
}
接下来看看
transaction->setInputWindowInfo(ctrl, *handle->getInfo());
这里较为简单,知识把对应的WindowInfo数据传递给对应的layer_state_t,其实对应就是Layer
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
const sp<SurfaceControl>& sc, const WindowInfo& info) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
s->windowInfoHandle = new WindowInfoHandle(info);
s->what |= layer_state_t::eInputInfoChanged;
return *this;
}
那么到此总结一下:
1、InputMonitior遍历每个WindowState相关数据,当然得有surface的,毕竟和surfaceflinger打交道
2、然后把数据java 的InputWindow数据转化native的InputWindow数据,通过一步步传递到transition中,即保存到了layer_state_t中
调用transition的apply方法:
status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay) {
//省略遍历目前mComposerStates对象,这里面包好目前的所有inputwindow
for (auto const& kv : mComposerStates){
composerStates.add(kv.second);
}
//跨进程调用setTransactionState把composerStates作为参数
sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
{} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
hasListenerCallbacks, listenerCallbacks, mId);
//省略
mStatus = NO_ERROR;
return NO_ERROR;
}
到达SurfaceFlinger层面分析
跨进程调用到了SurfaceFlinger中了:
status_t SurfaceFlinger::setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
TransactionState state{frameTimelineInfo, states,
displays, flags,
applyToken, inputWindowCommands,
desiredPresentTime, isAutoTimestamp,
uncacheBuffer, postTime,
permissions, hasListenerCallbacks,
listenerCallbacks, originPid,
originUid, transactionId};
//把TransactionState放入队列,且会启动对应的scheduleCommit
queueTransaction(state);
// Check the pending state to make sure the transaction is synchronous.
if (state.transactionCommittedSignal) {
waitForSynchronousTransaction(*state.transactionCommittedSignal);
}
return NO_ERROR;
}
然后执行SurfaceFlinger对应的commit会调用applyTransactionState再通过
setClientStateLocked把传递过来的layer_state_t进行获取更新到SurfaceFlinger的Layer
依次往下调用updateInputFlinger,会调用buildWindowInfos把当前所有的layer中获取数据转化到WindowInfo
uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo,
ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp,
int64_t postTime, uint32_t permissions) {
//省略
if (what & layer_state_t::eInputInfoChanged) {
layer->setInputInfo(*s.windowInfoHandle->getInfo());
flags |= eTraversalNeeded;
}
//省略
}
这样就更新到了Layer中
接下来再调用updateInputFlinger
void SurfaceFlinger::updateInputFlinger() {
//省略
if (mVisibleRegionsDirty || mInputInfoChanged) {
mInputInfoChanged = false;
updateWindowInfo = true;
//把WindowInfos搞出
buildWindowInfos(windowInfos, displayInfos);
}
BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo,
windowInfos = std::move(windowInfos),
displayInfos = std::move(displayInfos),
inputWindowCommands =
std::move(mInputWindowCommands),
inputFlinger = mInputFlinger, this]() {
if (updateWindowInfo) {
//这里会触发通知
mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
inputWindowCommands.syncInputWindows);
} else if (inputWindowCommands.syncInputWindows) {
// If the caller requested to sync input windows, but there are no
// changes to input windows, notify immediately.
windowInfosReported();
}
for (const auto& focusRequest : inputWindowCommands.focusRequests) {
inputFlinger->setFocusedWindow(focusRequest);
}
}});
mInputWindowCommands.clear();
}
这里看看buildWindowInfos
void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
std::vector<DisplayInfo>& outDisplayInfos) {
//省略
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
// Do not create WindowInfos for windows on displays that cannot receive input.
if (const auto opt = displayInputInfos.get(layer->getLayerStack())) {
const auto& info = opt->get();
outWindowInfos.push_back(layer->fillInputInfo(info.transform, info.isSecure));//根据layer填满outWindowInfos信息
}
});
sNumWindowInfos = outWindowInfos.size();
outDisplayInfos.reserve(displayInputInfos.size());
for (const auto& [_, info] : displayInputInfos) {
outDisplayInfos.push_back(info.info);
}
}
再接下来看看WindowInfo怎么传递通知出去给InputDispatch
void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
const std::vector<DisplayInfo>& displayInfos,
bool shouldSync) {
ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners;
{
std::scoped_lock lock(mListenersMutex);
for (const auto& [_, listener] : mWindowInfosListeners) {
windowInfosListeners.push_back(listener);
}
}
mCallbacksPending = windowInfosListeners.size();
for (const auto& listener : windowInfosListeners) {
//这里listener其实就是InputDispather
listener->onWindowInfosChanged(windowInfos, displayInfos,
shouldSync ? mWindowInfosReportedListener : nullptr);
}
}
而后调用到InputDispatcher中
void InputDispatcher::DispatcherWindowListener::onWindowInfosChanged(
const std::vector<gui::WindowInfo>& windowInfos,
const std::vector<DisplayInfo>& displayInfos) {
mDispatcher.onWindowInfosChanged(windowInfos, displayInfos);
}