详解AndroidSurface系统.docx
- 文档编号:30292504
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:40
- 大小:29.43KB
详解AndroidSurface系统.docx
《详解AndroidSurface系统.docx》由会员分享,可在线阅读,更多相关《详解AndroidSurface系统.docx(40页珍藏版)》请在冰豆网上搜索。
详解AndroidSurface系统
深入浅出详解AndroidSurface系统
2011-05-0514:
44InnostCSDN 字号:
T | T
本文详细介绍了Android中的Surface系统,采用情景分析的办法,详解了何为SurfaceFlinger,以及SurfaceFlinger的工作流程,以Activity函数调用为切入点来研究SurfaceFlinger。
AD:
2014WOT全球软件技术峰会北京站课程视频发布
一目的
本篇文章的目的就是为了讲清楚Android中的Surface系统,大家耳熟能详的SurfaceFlinger到底是个什么东西,它的工作流程又是怎样的。
当然,鉴于SurfaceFlinger的复杂性,我们依然将采用情景分析的办法,找到合适的切入点。
一个Activity是怎么在屏幕上显示出来的呢?
我将首先把这个说清楚。
接着我们把其中的关键调用抽象在Native层,以这些函数调用为切入点来研究SurfaceFlinger。
好了,开始我们的征途吧。
二Activity是如何显示的
最初的想法就是,Activity获得一块显存,然后在上面绘图,最后交给设备去显示。
这个道理是没错,但是Android的SurfaceFlinger是在SystemServer进程中创建的,Activity一般另有线程,这之间是如何...如何挂上关系的呢?
我可以先提前告诉大家,这个过程还比较复杂。
好吧,我们从Activity最初的启动开始。
代码在framework/base/core/java/android/app/ActivityThread.java中,这里有个函数叫handleLaunchActivity。
[---->ActivityThread:
:
handleLaunchActivity()]
1.private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
2.
3. Activity a = performLaunchActivity(r, customIntent);
4.
5.
6.
7. if (a !
= null) {
8.
9. r.createdConfig = new Configuration(mConfiguration);
10.
11. Bundle oldState = r.state;
12.
13. handleResumeActivity(r.token, false, r.isForward);
14.
15.---->调用handleResumeActivity
16.
17.}
handleLaunchActivity中会调用handleResumeActivity。
[--->ActivityThread:
:
handleResumeActivity]
1.final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2.
3. boolean willBeVisible = !
a.mStartedActivity;
4.
5.
6.
7.if (r.window == null && !
a.mFinished && willBeVisible) {
8.
9. r.window = r.activity.getWindow();
10.
11. View decor = r.window.getDecorView();
12.
13. decor.setVisibility(View.INVISIBLE);
14.
15. ViewManager wm = a.getWindowManager();
16.
17. WindowManager.LayoutParams l = r.window.getAttributes();
18.
19. a.mDecor = decor;
20.
21. l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
22.
23. if (a.mVisibleFromClient) {
24.
25. a.mWindowAdded = true;
26.
27. wm.addView(decor, l); //这个很关键。
28.
29. }
上面addView那几行非常关键,它关系到咱们在Activity中setContentView后,整个Window到底都包含了些什么。
我先告诉大家。
所有你创建的View之上,还有一个DecorView,这是一个FrameLayout,另外还有一个PhoneWindow。
上面这些东西的代码在framework/Policies/Base/Phone/com/android/Internal/policy/impl。
这些隐藏的View的创建都是由你在Acitivty的onCreate中调用setContentView导致的。
[---->PhoneWindow:
:
addContentView]
1.public void addContentView(View view, ViewGroup.LayoutParams params) {
2.
3.if (mContentParent == null) { //刚创建的时候mContentParent为空
4.
5.installDecor();
6.
7.}
8.
9.mContentParent.addView(view, params);
10.
11.final Callback cb = getCallback();
12.
13.if (cb !
= null) {
14.
15.cb.onContentChanged();
16.
17.}
18.
19.}
installDecor将创建mDecor和mContentParent。
mDecor是DecorView类型,ContentParent是ViewGroup类型
1.private void installDecor() {
2.
3.if (mDecor == null) {
4.
5.mDecor = generateDecor();
6.
7.mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
8.
9.mDecor.setIsRootNamespace(true);
10.
11.}
12.
13.if (mContentParent == null) {
14.
15.mContentParent = generateLayout(mDecor);
那么,ViewManagerwm=a.getWindowManager()又返回什么呢?
PhoneWindow从Window中派生,Acitivity创建的时候会调用它的setWindowManager。
而这个函数由Window类实现。
代码在framework/base/core/java/android/view/Window.java中:
1.public void setWindowManager(WindowManager wm,IBinder appToken, String appName) {
2.
3.mAppToken = appToken;
4.
5.mAppName = appName;
6.
7.if (wm == null) {
8.
9.wm = WindowManagerImpl.getDefault();
10.
11.}
12.
13.mWindowManager = new LocalWindowManager(wm);
14.
15.}
你看见没,分析JAVA代码这个东西真的很复杂。
mWindowManager的实现是LocalWindowManager,但由通过Bridge模式把功能交给WindowManagerImpl去实现了。
真的很复杂!
好了,我们回到wm.addView(decor,l)。
最终会由WindowManagerImpl来完成addView操作,我们直接看它的实现好了。
代码在framework/base/core/java/android/view/WindowManagerImpl.java:
[---->addView]
1.private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
2.
3.{
4.
5.ViewRoot root; //ViewRoot,我们的主人公终于登场!
6.
7.synchronized (this) {
8.
9.root = new ViewRoot(view.getContext());
10.
11.root.mAddNesting = 1;
12.
13.view.setLayoutParams(wparams);
14.
15.if (mViews == null) {
16.
17.index = 1;
18.
19.mViews = new View[1];
20.
21.mRoots = new ViewRoot[1];
22.
23.mParams = new WindowManager.LayoutParams[1];
24.
25.} else {
26.
27.}
28.
29.index--;
30.
31.mViews[index] = view;
32.
33.mRoots[index] = root;
34.
35.mParams[index] = wparams;
36.
37.}
38.
39.root.setView(view, wparams, panelParentView);
40.
41.}
ViewRoot是整个显示系统中最为关键的东西,看起来这个东西好像和View有那么点关系,其实它根本和View等UI关系不大,它不过是一个Handler罢了,唯一有关系的就是它其中有一个变量为Surface类型。
我们看看它的定义。
ViewRoot代码在framework/base/core/java/android/view/ViewRoot.java中:
1.public final class ViewRoot extends Handler implements ViewParent,
2.
3.View.AttachInfo.Callbacks
4.
5.{
6.
7.private final Surface mSurface = new Surface();
8.
9.}
它竟然从handler派生,而ViewParent不过定义了一些接口函数罢了。
看到Surface直觉上感到它和SurfaceFlinger有点关系。
要不先去看看?
Surface代码在framework/base/core/java/android/view/Surface.java中,我们调用的是无参构造函数。
1.public Surface() {
2.
3.mCanvas = new CompatibleCanvas(); //就是创建一个Canvas!
4.
5.}
如果你有兴趣的话,看看Surface其他构造函数,最终都会调用native的实现,而这些native的实现将和SurfaceFlinger建立关系,但我们这里ViewRoot中的mSurface显然还没有到这一步。
那它到底是怎么和SurfaceFlinger搞上的呢?
这一切待会就会水落石出的。
另外,为什么ViewRoot是主人公呢?
因为ViewRoot建立了客户端和SystemServer的关系。
我们看看它的构造函数。
1.public ViewRoot(Context context) {
2.
3.super();
4.
5.....
6.
7.getWindowSession(context.getMainLooper());
8.
9.}
getWindowsession将建立和WindowManagerService的关系。
1.public static IWindowSession getWindowSession(Looper mainLooper) {
2.
3. synchronized (mStaticInit) {
4.
5. if (!
mInitialized) {
6.
7. try {
8.
9. //sWindowSession是通过Binder机制创建的。
终于让我们看到点希望了
10.
11. InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
12.
13. sWindowSession = IWindowManager.Stub.asInterface(
14.
15. ServiceManager.getService("window"))
16.
17. .openSession(imm.getClient(), imm.getInputContext());
18.
19. mInitialized = true;
20.
21. } catch (RemoteException e) {
22.
23. }
24.
25. }
26.
27. return sWindowSession;
28.
29. }
30.
31. }
上面跨Binder的进程调用另一端是WindowManagerService,代码在framework/base/services/java/com/android/server/WindowManagerService.java中。
我们先不说这个。
回过头来看看ViewRoot接下来的调用。
[-->ViewRoot:
:
setView()],这个函数很复杂,我们看其中关键几句。
1.public void setView(View view, WindowManager.LayoutParams attrs,
2.
3. View panelParentView) {
4.
5. synchronized (this) {
6.
7. requestLayout();
8.
9. try {
10.
11. res = sWindowSession.add(mWindow, mWindowAttributes,
12.
13. getHostVisibility(), mAttachInfo.mContentInsets);
14.
15. }
16.
17.}
requestLayout实现很简单,就是往handler中发送了一个消息。
1.public void requestLayout() {
2.
3. checkThread();
4.
5. mLayoutRequested = true;
6.
7. scheduleTraversals(); //发送DO_TRAVERSAL消息
8.
9.}
10.
11.public void scheduleTraversals() {
12.
13. if (!
mTraversalScheduled) {
14.
15. mTraversalScheduled = true;
16.
17. sendEmptyMessage(DO_TRAVERSAL);
18.
19. }
20.
21.}
我们看看跨进程的那个调用。
sWindowSession.add。
它的最终实现在WindowManagerService中。
[--->WindowSession:
:
add()]
1.public int add(IWindow window, WindowManager.LayoutParams attrs,
2.
3. int viewVisibility, Rect outContentInsets) {
4.
5. return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6.
7. }
WindowSession是个内部类,会调用外部类的addWindow。
这个函数巨复杂无比,但是我们的核心目标是找到创建显示相关的部分。
所以,最后精简的话就简单了。
[--->WindowManagerService:
:
addWindow]
1.public int addWindow(Session session, IWindow client,
2.
3. WindowManager.LayoutParams attrs, int viewVisibility,
4.
5. Rect outContentInsets) {
6.
7. //创建一个WindowState,这个又是什么玩意儿呢?
8.
9. win = new WindowState(session, client, token,
10.
11. attachedWindow, attrs, viewVisibility);
12.
13. win.attach();
14.
15. return res;
16.
17.}
WindowState类中有一个和Surface相关的成员变量,叫SurfaceSession。
它会在attach函数中被创建。
SurfaceSession嘛,就和SurfaceFlinger有关系了。
我们待会看。
好,我们知道ViewRoot创建及调用add后,我们客户端的View系统就和WindowManagerService建立了牢不可破的关系。
另外,我们知道ViewRoot是一个handler,而且刚才我们调用了requestLayout,所以接下来消息循环下一个将调用的就是ViewRoot的handleMessage。
1.public void handleMessage(Message msg) {
2.
3. switch (msg.what) {
4.
5. case DO_TRAVERSAL:
6.
7. performTraversals();
performTraversals更加复杂无比,经过我仔细挑选,目标锁定为下面几个函数。
当然,后面我们还会回到performTraversals,不过我们现在更感兴趣的是Surface是如何创建的。
1.private void performTraversals() {
2.
3. // cache mView since it is used so much below...
4.
5. final View host = mView;
6.
7.
8.
9. boolean initialized = false;
10.
11. boolean contentInsetsChanged = false;
12.
13. boolean visibleInsetsChanged;
14.
15. try {
16.
17.//ViewRoot也有一个Surface成员变量,叫mSurface,这个就是代表SurfaceFlin
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详解 AndroidSurface 系统
![提示](https://static.bdocx.com/images/bang_tan.gif)