ViewRootImpl简析

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沟通桥梁的作用

ViewRootImpl简析_第1张图片
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对象,流程如下:
ViewRootImpl简析_第2张图片

获取画布

由前文我们知道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层的流程:
ViewRootImpl简析_第3张图片
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 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 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(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());
            }

可以看到触摸事件在责任链上的流转过程:
ViewRootImpl简析_第4张图片
到这里事件流转到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方法

你可能感兴趣的:(android进阶,ViewRootImpl)