简略整顿下activity 显示流程, 次要为acitvity -> WindowManager -> WMS -> SurfaceFlinger建设连贯的过程。
本篇为鸡生蛋系列第四篇文章
- Linux input零碎数据上报流程
- Android InputManager剖析
- AMS startActivity()
- [activity显示过程梳理]()
- [HomeLauncher启动]()
第4篇都曾经拖了快两年了, 几次都想写来着, 可是能源有余, 可是又想实现, 哎…
[代码: Android 11]
http://aosp.opersys.com/xref/…
setContentView()
搞利用的人都相熟,onCreate()里, 通过setContentView()把利用布局设置下,之后就显示进去了界面,
那这个流程是咋个样子的呢?
AppCompat的setContentView()就不看了,
通过在frameworks/base/目录搜寻 setContentView , 其入口次要有Dialog和Activity的,
<code class="java">frameworks/base/core/java/android/app/ Dialog.java Activity.java
持续看Activity的, 其进一歩调用了window的setContentView(),
<code class="java">frameworks/base/core/java/android/app/Activity.java public void setContentView(@LayoutRes int layoutResID) { // 调用mWindow的setContentView() getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } public Window getWindow() { return mWindow; }
那这个mWindow是啥呢?
<code class="java">@UnsupportedAppUsage final void attach(Context context, ActivityThread aThread, ...... Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) { ...... // mWinow为PhoneWindow mWindow = new PhoneWindow(this, window, activityConfigCallback);
它其实是 new PhoneWindow(),
这里顺便回顾下, attach()是在activity启动时会调用, (具体的可看下该系列第二篇文章 AMS startActivity())
其代码如下:
<code class="java">frameworks/base/core/java/android/app/ActivityThread.java private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ...... // 调用activity attach() activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback, r.assistToken);
咱们回到PhoneWindow 持续看 setContentView(),
PhoneWindow有三个setContentView()办法, 最终都是将Decor Layout和ViewGroup关系建设起来,
<code class="java">frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java @Override public void setContentView(int layoutResID) { ...... if (mContentParent == null) { // 装置Decor, // mContentParent会在该函数里赋值 mContentParent = generateLayout(mDecor); installDecor(); } ...... if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { // 将咱们应用程序的布局退出 mLayoutInflater.inflate(layoutResID, mContentParent); } ...... } // 应用程序除了通过指定资源ID形式调用setContentView() // 也可通过传入参数View形式调用, // 最终也是将该view退出 mContentParent @Override public void setContentView(View view) { setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { ...... if (mContentParent == null) { // 和参数为资源ID形式一样,先装置Decor installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { view.setLayoutParams(params); final Scene newScene = new Scene(mContentParent, view); transitionTo(newScene); } else { // 退出view mContentParent.addView(view, params); } mContentParent.requestApplyInsets(); ...... }
对于 setContentView()更具体的代码解读可看
https://www.gaodaima.com/p/2ee…
我感觉这篇文章写得很好, 这里就不再讲了.
show
原本认为利用 onCreate() –> setContentView()之后, 利用就显示进去了, 可是来来回回钻研代码如同都不太对,
这时候再来看看文章后面提到的Dialog咋显示的呢?
咱们晓得对于Dialog用法个别为:
<code class="java">// 伪代码形容 Dialog mDialog = new Dialog(); mDialog 资源参数等设置 // 调用show就显示进去了 mDialog.show();
先new 一个Dialog()对象,而后设置资源参数等, 再调用其show()办法就能够将其显示进去.
那咱们就先看看其show()办法是咋玩的.
<code class="java">frameworks/base/core/java/android/app/Dialog.java public void show() { ......// 获取mDecor mDecor = mWindow.getDecorView(); ......// 属性 WindowManager.LayoutParams l = mWindow.getAttributes(); ...... // 增加view mWindowManager.addView(mDecor, l);
show() 里通过WindowManager的addView()办法, 与WinowManager分割上.
下面的mWindowManager即为WINDOW_SERVICE,
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
须要留神的是 mWindowManager 为 WindowManagerImpl, 此时还处于用户过程中, 非WindowManagerService.
可通过看其 registerService() 注册服务时, 其的确为 new WindowManagerImpl()
<code class="java">frameworks/base/core/java/android/app/SystemServiceRegistry.java registerService(Context.WINDOW_SERVICE, WindowManager.class, new CachedServiceFetcher<WindowManager>() { @Override public WindowManager createService(ContextImpl ctx) { return new WindowManagerImpl(ctx); }});
那么activity的mWindowManager.addView()在哪儿呢
这个时候就要举荐一本书了
<<深刻了解Android内核设计思维>> 林学森 著
这外面surface window view当然还有别的方面内容都讲得不错,
要是我能达到作者的高度这辈子也就值了,哎……
援用书中的话
那么Activity 利用过程在什么时候会调用 addView,进而由WMS来解决addWindow 呢?
Activity从启动到最终在屏幕上显示进去,别离要经验onCreate->onStart->onResume三个状态迁徙。其中 onResume是当界面行将可见时才会调用的,紧接着 ActivityThread 就会通过WindowManagerImpl来把应用程序窗口增加到零碎中。
具体代码如下:
<code class="java">frameworks/base/core/java/android/app/ActivityThread.java public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) { ...... // performResumeActivity()最终会调用activity的onResume() final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason); if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); // 获取decor, DecorView是activity 整棵View树最外围 View decor = r.window.getDecorView(); // 可见性 decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; ...... if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true; // *** 增加到view里 wm.addView(decor, l);
从下面代码剖析可知,其最终也是通过wm.addView(), 最终和WMS分割上, 和后面的Dialog流程大体差不多,
略微有点小区别是其通过 createLocalWindowManager()创立进去的.
<code class="java">frameworks/base/core/java/android/view/Window.java public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { ...... if (wm == null) { wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); } // wm最终为createLocalWindowManager()创立进去的 mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
从下面代码可知Dialog的show()和Activity 显示都最终调用了 WindowManagerImpl 的 addView()办法,
那这之后是咋和SurfaceFlinger分割在一起的呢? 咱们接着addView()看看。
addView() -> WMS
这些代码真是一层套一层, WindowManagerImpl addView() 最终又调用了 WindowManagerGlobal addView()
<code class="java">frameworks/base/core/java/android/view/WindowManagerImpl.java public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); } frameworks/base/core/java/android/view/WindowManagerGlobal.java public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow, int userId) { ...... root = new ViewRootImpl(view.getContext(), display); // do this last because it fires off messages to start doing things try { // ViewRootImpl setView() root.setView(view, wparams, panelParentView, userId);
WindowManagerGlobal setView() 进一通过 ViewRootImpl setView()
<code class="java">frameworks/base/core/java/android/view/ViewRootImpl.java public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) { synchronized (this) { if (mView == null) { mView = view; ......// final IWindowSession mWindowSession; res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mDisplayCutout, inputChannel, mTempInsets, mTempControls);
进一步调用IWindowSession addToDisplayAsUser(), 其最终实现为
<code class="java">frameworks/base/services/core/java/com/android/server/wm/Session.java public int addToDisplayAsUser(IWindow window,......) { return mService.addWindow(...); }
下面的mService为
final WindowManagerService mService;
到这里才终于和WMS扯上点关系,
从上剖析, ViewRootImpl通过IWindowSession为桥梁,建设与WMS分割
ViewRootImpl <-> IWindowSession <-> WindowManagerService
WMS -> SurfaceFlinger
从下面终于看到利用activity通过一系列的调用, 终于和WMS关联上了, 那与SurfaceFlinger咋关联上的呢?
那就持续看addWindow()流程吧
<code class="java">frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java public int addWindow(Session session, IWindow client, int seq, LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, int requestUserId) { // 好多好多的查看 .... // WMS用WindowState治理window final WindowState win = new WindowState(this, session, client, token, parentWindow, appOp[0], seq, attrs, viewVisibility, session.mUid, userId, session.mCanAddInternalSystemWindow); .... if (openInputChannels) { // 与 input建立联系 win.openInputChannel(outInputChannel); } .... // 与SurfaceFlinger建立联系 win.attach();
addWindow()是一个比拟长也比拟重要的函数, 从中咱们能够理解到 WMS用 WindowState 形容窗口, 并通过openInputChannel()与输出关联上,
而其与SurfaceFlinger是通过 WindowState.attach() --> Session.windowAddedLocked() --> SurfaceSession() --> SurfaceComposerClient()
分割上的.
代码如下:
<code class="java">frameworks/base/services/core/java/com/android/server/wm/WindowState.java void attach() { if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken); mSession.windowAddedLocked(mAttrs.packageName); } frameworks/base/services/core/java/com/android/server/wm/Session.java void windowAddedLocked(String packageName) {...... if (mSurfaceSession == null) {...... mSurfaceSession = new SurfaceSession();
SurfaceSession()就会与SF建立联系, 可看下代码正文, 不再具体讲解.
frameworks/base/core/java/android/view/SurfaceSession.java public SurfaceSession() { // 进结构函数调用JNI nativeCreate() mNativeClient = nativeCreate(); } frameworks/base/core/jni/android_view_SurfaceSession.cpp static jlong nativeCreate(JNIEnv* env, jclass clazz) { // JNI里new了个SurfaceComposerClient, 咱们晓得其为SurfaceFlinger的client端, // 用于和SF通信. // 如果不相熟该局部的可持续往后看代码 SurfaceComposerClient* client = new SurfaceComposerClient(); frameworks/native/libs/gui/SurfaceComposerClient.cpp // SurfaceComposerClient的构造函数里并没有做啥, 其继承RefBase, 所以接下来看其onFirstRef() void SurfaceComposerClient::onFirstRef() { // 这里的ComposerService::getComposerService()失去的为 mComposerService, 也即是SurfaceFlinger服务 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); if (sf != nullptr && mStatus == NO_INIT) { sp<ISurfaceComposerClient> conn; // 创立连贯 conn = sf->createConnection(); /*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() { // getInstance()获取实例 ComposerService& instance = ComposerService::getInstance(); ...... // 返回实例的 mComposerService return instance.mComposerService; // 因为ComposerService继承自单例, 调用其getInstance()如果没创建对象的话, 会创立一个, // 所以看下其构造函数 ComposerService::ComposerService() : Singleton<ComposerService>() { Mutex::Autolock _l(mLock); // 构造函数里调用connectLocked() connectLocked(); } void ComposerService::connectLocked() { // 获取SurfaceFlinger服务并赋值给 mComposerService const String16 name("SurfaceFlinger"); while (getService(name, &mComposerService) != NO_ERROR) {
再回头看下
<code class="cpp">void SurfaceComposerClient::onFirstRef() { conn = sf->createConnection();
其在SurfaceFlinger创立了一个client进行治理
<code class="cpp">frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() { const sp<Client> client = new Client(this); return client->initCheck() == NO_ERROR ? client : nullptr; }
NOTE
Window <1–1> WMS的WindowState <1–1> SurfaceSession <1–1> SurfaceComposerClient <1–1> SurfaceFlinger过程里的Client
它们是一一对应的