共计 10285 个字符,预计需要花费 26 分钟才能阅读完成。
简略整顿下 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 的,
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 是啥呢?
@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())
其代码如下:
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…
我感觉这篇文章写得很好, 这里就不再讲了.
show
原本认为利用 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() 看看。
addView() -> WMS
这些代码真是一层套一层, 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
WMS -> SurfaceFlinger
从下面终于看到利用 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;}
NOTE
Window <1–1> WMS 的 WindowState <1–1> SurfaceSession <1–1> SurfaceComposerClient <1–1> SurfaceFlinger 过程里的 Client
它们是一一对应的