ViewRootImpl简析
- 如何实现视图和wms沟通桥梁的作用
- Session的创建
- 获取画布
- 如何实现事件分发的桥梁作用
The top of a view hierarchy, implementing the needed protocol between View and the WindowManager. This is for the most part an internal implementation detail of WindowManagerGlobal. --google api 31
ViewRootImpl是视图结构的顶层,实现了视图和WM通信的协议。很大程度上是WindowManagerGlobal的内部实现细节。
ViewRootImpl不仅是视图和WM沟通的桥梁,也是事件分发的桥梁。
如何实现视图和wms沟通桥梁的作用
WindowManagerGlobal是单例模式,其中维护ViewRootImpl数组,每一个window对应一个ViewRootImpl,在添加View时会通过requestLayout注册Choreagrapher监听,等待系统下发绘制信号,触发View的绘制流程,也就是measure、layout、draw流程。
Session的创建
我们知道在绘制流程draw之后,应用的视图会显示在屏幕上,这中间需要通过wms拿到可在其上作画的画布。
在setView中会通过mWindowSession对象将window添加到wms,如下(只摘取关键代码):
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
synchronized (this) {
if (mView == null) {
mView = view;
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
mTempControls);
mWindowSession是什么?
This class represents an active client session. There is generally one Session object per process that is interacting with the window manager.
Session表示客户端和WMS交互的会话,每个进程都有一个Session对象与WMS交互。
看几个Session的成员方法:
@Override
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, InsetsState requestedVisibility,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId,
UserHandle.getUserId(mUid), requestedVisibility, outInputChannel, outInsetsState,
outActiveControls);
}
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
}
@Override
public int addToDisplayWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, InsetsState outInsetsState) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId,
UserHandle.getUserId(mUid), mDummyRequestedVisibility, null /* outInputChannel */,
outInsetsState, mDummyControls);
}
@Override
public void remove(IWindow window) {
mService.removeWindow(this, window);
}
@Override
public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
mService.setWillReplaceWindows(appToken, childrenOnly);
}
最终都是在和WMS打交道。
在创建ViewRootImple对象时,默认调用WindowManagerGlobal的静态方法getWindowSession,获取WMS本地代理对象,调用WMS的openSession方法创建Session对象,流程如下:
获取画布
由前文我们知道ViewRootImple在setView时会注册Choreographer的监听,等下次系统下发绘制同步信号时,ViewRootImpl执行performTraversals方法,其中有这样一行代码:
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|| mForceNextWindowRelayout) {
...省略
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...省略
}
其中会调用Session对象的relayout方法:
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
...省略
int relayoutResult = mWindowSession.relayout(mWindow, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
mTempControls, mSurfaceSize);
...省略
Session对象调用WMS的relayout方法:
@Override
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
int res = mService.relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
outActiveControls, outSurfaceSize);
return res;
}
WMS调用自身的createSurfaceControl方法:
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
...省略
// Create surfaceControl before surface placement otherwise layout will be skipped
// (because WS.isGoneForLayout() is true when there is no surface.
if (shouldRelayout) {
try {
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
...省略
}
}
接着调用WindowStateAnimator的createSurfaceLocked方法:
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
WindowState win, WindowStateAnimator winAnimator) {
if (!win.mHasSurface) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
WindowSurfaceController surfaceController;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
在WindowStateAnimator的createSurfaceLocked方法中创建WindowSurfaceController对象并返回WindowSurfaceController对象:
WindowSurfaceController createSurfaceLocked(int windowType) {
...省略
mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width,
height, format, flags, this, windowType);
...省略
WindowSurfaceController在构造函数中创建SurfaceControl对象:
WindowSurfaceController(String name, int w, int h, int format,
int flags, WindowStateAnimator animator, int windowType) {
...省略
final SurfaceControl.Builder b = win.makeSurface()
.setParent(win.getSurfaceControl())
.setName(name)
.setBufferSize(w, h)
.setFormat(format)
.setFlags(flags)
.setMetadata(METADATA_WINDOW_TYPE, windowType)
.setMetadata(METADATA_OWNER_UID, mWindowSession.mUid)
.setMetadata(METADATA_OWNER_PID, mWindowSession.mPid)
.setCallsite("WindowSurfaceController");
...省略
mSurfaceControl = b.build();
}
@NonNull
public SurfaceControl build() {
...省略
return new SurfaceControl(
mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
mLocalOwnerView, mCallsite);
}
在SurfaceControl构造函数中调用了本地方法nativeCreate:
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView,
String callsite)
throws OutOfResourcesException, IllegalArgumentException {
...省略
try {
if (metadata != null && metadata.size() > 0) {
metaParcel.writeInt(metadata.size());
for (int i = 0; i < metadata.size(); ++i) {
metaParcel.writeInt(metadata.keyAt(i));
metaParcel.writeByteArray(
ByteBuffer.allocate(4).order(ByteOrder.nativeOrder())
.putInt(metadata.valueAt(i)).array());
}
metaParcel.setDataPosition(0);
}
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, metaParcel);
} finally {
metaParcel.recycle();
}
...省略
}
到这里由java层转至native层,先总结下java层的流程:
nativeCreate返回的就是画布的底层指针,保存在SurfaceControl中,java层后续的操作都是基于这个指针操作画布。
接着来看native层的创建流程:
frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,401 jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
402 jobject metadataParcel) {
403 ScopedUtfChars name(env, nameStr);
404 sp<SurfaceComposerClient> client;
405 if (sessionObj != NULL) {
406 client = android_view_SurfaceSession_getClient(env, sessionObj);
407 } else {
408 client = SurfaceComposerClient::getDefault();
409 }
410 SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
411 sp<SurfaceControl> surface;
412 LayerMetadata metadata;
413 Parcel* parcel = parcelForJavaObject(env, metadataParcel);
414 if (parcel && !parcel->objectsCount()) {
415 status_t err = metadata.readFromParcel(parcel);
416 if (err != NO_ERROR) {
417 jniThrowException(env, "java/lang/IllegalArgumentException",
418 "Metadata parcel has wrong format");
419 }
420 }
421 422 sp<IBinder> parentHandle;
423 if (parent != nullptr) {
424 parentHandle = parent->getHandle();
425 }
426 427 status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
428 flags, parentHandle, std::move(metadata));
429 if (err == NAME_NOT_FOUND) {
430 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
431 return 0;
432 } else if (err != NO_ERROR) {
433 jniThrowException(env, OutOfResourcesException, statusToString(err).c_str());
434 return 0;
435 }
436 437 surface->incStrong((void *)nativeCreate);
438 return reinterpret_cast<jlong>(surface.get());
439 }
这里会创建SurfaceComposerClient、SurfaceControl和Surface,这三件套。
看下SurfaceComposerClient的createSurfaceChecked方法:
路径:/framework/native/native/libs/gui/SurfaceComposerClient.cpp
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
2376 PixelFormat format,
2377 sp<SurfaceControl>* outSurface, int32_t flags,
2378 const sp<IBinder>& parentHandle,
2379 LayerMetadata metadata,
2380 uint32_t* outTransformHint) {
2381 sp<SurfaceControl> sur;
2382 status_t err = mStatus;
2383 2384 if (mStatus == NO_ERROR) {
2385 gui::CreateSurfaceResult result;
2386 binder::Status status = mClient->createSurface(std::string(name.string()), flags,
2387 parentHandle, std::move(metadata), &result);
2388 err = statusTFromBinderStatus(status);
2389 if (outTransformHint) {
2390 *outTransformHint = result.transformHint;
2391 }
2392 ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
2393 if (err == NO_ERROR) {
2394 *outSurface = new SurfaceControl(this, result.handle, result.layerId,
2395 toString(result.layerName), w, h, format,
2396 result.transformHint, flags);
2397 }
2398 }
2399 return err;
2400 }
这里先调用mClient对象创建Surface,然后将创建结果作为参数创建SurfaceControl对象,并赋值给入参出参的outSurface指针。接下来看下Client的createSurface方法。
路径:/frameworks/native/services/surfaceflinger/Client.cpp
63 binder::Status Client::createSurface(const std::string& name, int32_t flags,
64 const sp<IBinder>& parent, const gui::LayerMetadata& metadata,
65 gui::CreateSurfaceResult* outResult) {
66 // We rely on createLayer to check permissions.67 sp<IBinder> handle;
68 LayerCreationArgs args(mFlinger.get(), sp<Client>::fromExisting(this), name.c_str(),
69 static_cast<uint32_t>(flags), std::move(metadata));
70 args.parentHandle = parent;
71 const status_t status = mFlinger->createLayer(args, *outResult);
72 return binderStatusFromStatusT(status);
73 }
调用mFlinger对象的createlayer方法,这里的mFlinger对象是什么呢?
路径:/frameworks/native/services/surfaceflinger/Client.h
private:
46 // ISurfaceComposerClient interface
47
48 binder::Status createSurface(const std::string& name, int32_t flags, const sp<IBinder>& parent,
49 const gui::LayerMetadata& metadata,
50 gui::CreateSurfaceResult* outResult) override;
51
52 binder::Status clearLayerFrameStats(const sp<IBinder>& handle) override;
53
54 binder::Status getLayerFrameStats(const sp<IBinder>& handle,
55 gui::FrameStats* outStats) override;
56
57 binder::Status mirrorSurface(const sp<IBinder>& mirrorFromHandle,
58 gui::CreateSurfaceResult* outResult) override;
59
60 binder::Status mirrorDisplay(int64_t displayId, gui::CreateSurfaceResult* outResult) override;
61
62 // constant
63 sp<SurfaceFlinger> mFlinger;
mFlinger就是SurfaceFlinger的指针。
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
6215 status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurfaceResult& outResult) {
6216 status_t result = NO_ERROR;
6217
6218 sp<Layer> layer;
6219
6220 switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) {
6221 case ISurfaceComposerClient::eFXSurfaceBufferQueue:
6222 case ISurfaceComposerClient::eFXSurfaceContainer:
6223 case ISurfaceComposerClient::eFXSurfaceBufferState:
6224 args.flags |= ISurfaceComposerClient::eNoColorFill;
6225 FMT_FALLTHROUGH;
6226 case ISurfaceComposerClient::eFXSurfaceEffect: {
6227 result = createBufferStateLayer(args, &outResult.handle, &layer);
6228 std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
6229 if (pendingBufferCounter) {
6230 std::string counterName = layer->getPendingBufferCounterName();
6231 mBufferCountTracker.add(outResult.handle->localBinder(), counterName,
6232 pendingBufferCounter);
6233 #ifdef MTK_SF_DEBUG_SUPPORT
6234 mLayerTracker.track(layer->getName(), android::base::StringPrintf("%s,%d", __func__, __LINE__));
6235 #endif
6236 }
6237 #ifdef MTK_SF_MSYNC
6238 if (mMSyncSfApi && result == NO_ERROR) {
6239 mMSyncSfApi->registerLayer(layer.get());
6240 }
6241 #endif
6242 } break;
6243 default:
6244 result = BAD_VALUE;
6245 break;
6246 }
6247
6248 if (result != NO_ERROR) {
6249 return result;
6250 }
6251
6252 args.addToRoot = args.addToRoot && callingThreadHasUnscopedSurfaceFlingerAccess();
6253 // We can safely promote the parent layer in binder thread because we have a strong reference6254 // to the layer's handle inside this scope.6255 sp<Layer> parent = LayerHandle::getLayer(args.parentHandle.promote());
6256 if (args.parentHandle != nullptr && parent == nullptr) {
6257 ALOGE("Invalid parent handle %p", args.parentHandle.promote().get());
6258 args.addToRoot = false;
6259 }
6260
6261 uint32_t outTransformHint;
6262 result = addClientLayer(args, outResult.handle, layer, parent, &outTransformHint);
6263 if (result != NO_ERROR) {
6264 return result;
6265 }
6266
6267 outResult.transformHint = static_cast<int32_t>(outTransformHint);
6268 outResult.layerId = layer->sequence;
6269 outResult.layerName = String16(layer->getDebugName());
6270 return result;
6271 }
这里就是根据标志创建不同的layer,layer就是Surface合成图层的基本单位了。创建的图层注册添加到SurfaceFlinger,并向上保存到SurfaceContral对象当中,并把指针返回到java层,完成画布的创建。
如何实现事件分发的桥梁作用
setView中会创建WindowInputEventReceiver,在构造方法中会把WindowInputEventReceiver注册到系统层的事件分发流程:
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
路径:/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
529 jobject inputChannelObj, jobject messageQueueObj) {
530 std::shared_ptr<InputChannel> inputChannel =
531 android_view_InputChannel_getInputChannel(env, inputChannelObj);
532 if (inputChannel == nullptr) {
533 jniThrowRuntimeException(env, "InputChannel is not initialized.");
534 return 0;
535 }
536
537 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
538 if (messageQueue == nullptr) {
539 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
540 return 0;
541 }
542
543 sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
544 receiverWeak, inputChannel, messageQueue);
545 status_t status = receiver->initialize();
546 if (status) {
547 std::string message = android::base::
548 StringPrintf("Failed to initialize input event receiver. status=%s(%d)",
549 statusToString(status).c_str(), status);
550 jniThrowRuntimeException(env, message.c_str());
551 return 0;
552 }
553
554 receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object555 return reinterpret_cast<jlong>(receiver.get());
556 }
这里会基于java层传入的参数创建native层的receiver,后续通过reveiver分发事件到java层
326 status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,327 bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
328 ...省略
478 env->CallVoidMethod(receiverObj.get(),
479 gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
480 if (env->ExceptionCheck()) {
481 ALOGE("Exception dispatching input event.");
482 skipCallbacks = true;
483 }
484 env->DeleteLocalRef(inputEventObj);
485 } else {
486 ALOGW("channel '%s' ~ Failed to obtain event object.",
487 getInputChannelName().c_str());
488 skipCallbacks = true;
489 }
490 }
491 }
492 }
这里通过反射调用java层的dispatchInputEvent方法把时间分发到java层,事件进入WindowInputEventReceiver的onInputEvent方法。后续流转顺序:onInputEvent-》enqueueInputEvent-》doProcessInputEvents-》deliverInputEvent-》进入InputStage
InputState采用责任链模式,进行事件的流转,责任链组装过程:
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
触摸事件的分发流程:mSyntheticInputStage --> viewPostImeStage
通过在在view分发事件方法processPointerEvent中添加trace,
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
boolean handled = mHandwritingInitiator.onTouchEvent(event);
mAttachInfo.mUnbufferedDispatchRequested = false;
mAttachInfo.mHandlingPointerEvent = true;
//@ M: control the flag when input move and up
BoostFwkFactory.getInstance().makeBoostFwkManager().perfHint(
mScrollScenario.setAction(BoostFwkManager.Scroll.INPUT_EVENT)
.setBoostStatus(BoostFwkManager.BOOST_BEGIN)
.setMotionEvent(event)
.setContext(mContext)
);
//@ M: End of input control
// If the event was fully handled by the handwriting initiator, then don't dispatch it
// to the view tree.
handled = handled || mView.dispatchPointerEvent(event);
//if (handled && ViewDebugManager.DEBUG_ENG) {
if (handled) {
Log.v(mTag, "App handle pointer event: event = " + event
+ ", mView = " + mView
+ ", this = " + this, new Throwable());
}
可以看到触摸事件在责任链上的流转过程:
到这里事件流转到mView中,mView就是DecorView
/DecorView.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
这里拿到的callback就是activity,事件流转到activity,后边就是大家熟悉的视图层的事件流转过程了。
总结下:
ViewRootImpl作为桥梁注册事件监听,底层事件先分发到ViewRootImpl,再分发到视图层。
系统事件分发到WindowInputEventReceiver,进入onInputEvent方法