简单整理下activity 显示流程, 主要为acitvity -> WindowManager -> WMS -> SurfaceFlinger创建链接的过程。java
本篇为鸡生蛋系列第四篇文章android
第4篇都已经拖了快两年了, 几回都想写来着, 但是动力不足, 但是又想完成, 哎...segmentfault
[代码: Android 11]session
http://aosp.opersys.com/xref/...app
搞应用的人都熟悉,onCreate()里, 经过setContentView()把应用布局设置下,以后就显示出来了界面,
那这个流程是咋个样子的呢?ide
AppCompat的setContentView()就不看了,
经过在frameworks/base/目录搜索 setContentView , 其入口主要有Dialog和Activity的,函数
frameworks/base/core/java/android/app/ Dialog.java Activity.java
继续看Activity的, 其进一歩调用了window的setContentView(),布局
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是啥呢?ui
@UnsupportedAppUsage final void attach(Context context, ActivityThread aThread, ...... Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) { ...... // mWinow为PhoneWindow mWindow = new PhoneWindow(this, window, activityConfigCallback);
它实际上是 new PhoneWindow(),this
这里顺便回顾下, attach()是在activity启动时会调用, (详细的可看下该系列第二篇文章 AMS startActivity())
其代码以下:
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关系创建起来,
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.jianshu.com/p/2ee...
我以为这篇文章写得很好, 这里就再也不讲了.
原本觉得应用 onCreate() --> setContentView()以后, 应用就显示出来了, 但是来来回回研究代码好像都不太对,
这时候再来看看文章前面提到的Dialog咋显示的呢?
咱们知道对于Dialog用法通常为:
// 伪代码描述 Dialog mDialog = new Dialog(); mDialog 资源参数等设置 // 调用show就显示出来了 mDialog.show();
先new 一个Dialog()对象,而后设置资源参数等, 再调用其show()方法就能够将其显示出来.
那咱们就先看看其show()方法是咋玩的.
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()
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来把应用程序窗口添加到系统中。
具体代码以下:
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()建立出来的.
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()看看。
这些代码真是一层套一层, WindowManagerImpl addView() 最终又调用了 WindowManagerGlobal addView()
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()
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(), 其最终实现为
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
从上面终于看到应用activity经过一系列的调用, 终于和WMS关联上了, 那与SurfaceFlinger咋关联上的呢?
那就继续看addWindow()流程吧
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()
联系上的.
代码以下:
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) {
再回头看下
void SurfaceComposerClient::onFirstRef() { conn = sf->createConnection();
其在SurfaceFlinger建立了一个client进行管理
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() { const sp<Client> client = new Client(this); return client->initCheck() == NO_ERROR ? client : nullptr; }
Window <1--1> WMS的WindowState <1--1> SurfaceSession <1--1> SurfaceComposerClient <1--1> SurfaceFlinger进程里的Client
它们是一一对应的