This blog mainly analyzes how ViewRoot, the manager of ViewTree, works.
1, Two way communication between ViewRootImpl and WMS
ViewRootImpl > WMS: IwindowSession
WMS > ViewRootImpl: Iwindow
Iwindonsession and Iwindow are anonymous bindservers.
1. The process of viewrootimpl getting the handle of IWindowSession service.
ViewRootImpl.java public ViewRootImpl(Context context, Display display) { mContext = context; mWindowSession = WindowManagerGlobal.getWindowSession(); ... } WindowManagerGlobal.java @UnsupportedAppUsage public static IWindowSession getWindowSession() { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { // Emulate the legacy behavior. The global instance of InputMethodManager // was instantiated here. // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { @Override public void onAnimatorScaleChanged(float scale) { ValueAnimator.setDurationScale(scale); } }); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowSession; } }
Here, IWindowManager is the agent of WindowManagerService on the local process side, and the requests of windowManager are implemented by WMS on the remote side;
In ActivityThread, when handling handleResumeActivity, there is also a WindowManager, that is, ViewManager wm =a.getWindowManager(); here wm is ViewManager, which is the base class of WindowManager class, and the final implementation is WindowManagerImpl, which belongs to the local end completely, and stores the related transactions used for window management within the application process.
2.
In handleResumeActivity, through wm.addView(decor,l) Finally, the setView of ViewRootImpl will be called. On the one hand, this function sets the decirview, that is, the root of viewtree, to ViewRootImpl and saves it with mView; on the other hand, it will apply to WMS to register a window, and at the same time, it will pass the mWindow object (W type, which is also the inner class of ViewRootImpl and the implementation of Iwindow server) to WMS to realize the communication between WMS and Viewroot.
ViewRootImpl.java public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { if (mView == null) { mView = view; ... try { mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets); setFrame(mTmpFrame); } catch (RemoteException e) { mAdded = false; mView = null; mAttachInfo.mRootView = null; mInputChannel = null; mFallbackEventHandler.setView(null); unscheduleTraversals(); setAccessibilityFocus(null, null); throw new RuntimeException("Adding window failed", e); } finally { if (restore) { attrs.restore(); } } ... } } }
Two concepts related to windows, phoneWindow inherits from the window class, which is the description of the application process to the window and expresses a constraint to the window; window in WMS is an abstract concept, which describes its state with WindowState, which can be considered as the description of the window in WMS.
2, How ViewRootImpl works
Each ViewTree corresponds to only one ViewRoot, which will communicate with WMS in a series of ways, including window registration, resizing, etc. Under what circumstances will these operations be performed?
1. The internal requests of ViewTree, such as the view object to update the UI, will be initiated through invalidate or other ways, and then these requests will be transmitted along the ViewTree layer by layer, and finally arrive at ViewRoot. As the manager of ViewTree, it will perform corresponding operations according to a series of actual situations (such as initiating a traverse, notifying WMS, etc.).
2. External status updates, such as WMS callback to viewroot to notify the size of interface changes, touch events, key events, etc.
Whether it is an internal request or an external request, viewroot will usually stack these messages, and then the ViewRootHandler class in ViewRootImpl will handle them uniformly. ViewRootImpl is created during addView of WindowManagerImpl. The starting point of addView call is handleResumeActivity of ActivityThread, so ViewRootImpl is actually running in the main thread, and ViewRootHandler is actually linked with the message queue of the main thread.
Internal and external requests are queued to the message queue of the main thread, and then processed by Viewroot.
ViewRootImpl.java final class ViewRootHandler extends Handler { ... @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_INVALIDATE: ((View) msg.obj).invalidate(); break; ... } } ... }