簡單整理下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
它們是一一對應的