Android应用程序窗口(Activity)的绘图表面(Surface)的创建过程分析
ndroid应用程序窗口(Activity)的绘图表面(Surface)的创建过程分析
在WindowManagerService服务这一侧,每一个应用程序窗口,即每一个Activity组件,都有一个对应的WindowState对象,这个WindowState对象的成员变量mSurface同样是指向了一个Surface对象
,如图3所示:
一个应用程序窗口分别位于应用程序进程和WindowManagerService服务中的两个Surface对象有什么区别呢?虽然它们都是用来操作位于SurfaceFlinger服务中的同一个Layer对象的,不过,它们的操作方式却不一样。具体来说,就是位于应用程序进程这一侧的Surface对象负责绘制应用程序窗口的UI,即往应用程序窗口的图形缓冲区填充UI数据,而位于WindowManagerService服务这一侧的Surface对象负责设置应用程序窗口的属性,例如位置、大小等属性。这两种不同的操作方式分别是通过C++层的Surface对象和SurfaceControl对象来完成的,因此,位于应用程序进程和WindowManagerService服务中的两个Surface对象的用法是有区别的。之所以会有这样的区别,是因为绘制应用程序窗口是独立的,由应用程序进程来完即可,而设置应用程序窗口的属性却需要全局考虑,即需要由WindowManagerService服务来统筹安排,例如,一个应用程序窗口的Z轴坐标大小要考虑它到的窗口类型以及它与系统中的其它窗口的关系。
Surface Surface
Surface SurfaceControl
应用程序窗口在第一次显示的时候,就会请求WindowManagerService服务为其创建绘制表面。
当一个应用程序窗口被激活并且它的视图对象创建完成之后,应用程序进程就会调用与其所关联的一个ViewRoot对象的成员函数requestLayout来请求对其UI进行布局以及显示。
WindowManagerService
ViewRoot request
public final class ViewRoot extends Handler implements ViewParent,
public void requestLayout() {
ViewRoot类是从Handler类继承下来的,用来处理应用程序窗口的UI布局和渲染等消息。
public void scheduleTraversals() {
private void performTraversals() {
final View host = mView;
boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw();
attachInfo.mTreeObserver.dispatchOnPreDraw
ViewRoot类的成员函数performTraversals的实现是相当复杂的,这里我们分析它的实现框架,在以后的文章中,我们再详细分析它的实现细节。
在分析ViewRoot类的成员函数performTraversals的实现框架之前,我们首先了解ViewRoot类的以下五个成员变量:
--mView:它的类型为View,但它实际上指向的是一个DecorView对象,用来描述应用程序窗口的顶级视图,这一点可以参考前面Android应用程序窗口(Activity)的视图对象(View)的创建过程分析一文。
--mLayoutRequested:这是一个布尔变量,用来描述应用程序进程的UI线程是否需要正在被请求执行一个UI布局操作。
--mFirst:这是一个布尔变量,用来描述应用程序进程的UI线程是否第一次处理一个应用程序窗口的UI。
--mFullRedrawNeeded:这是一个布尔变量,用来描述应用程序进程的UI线程是否需要将一个应用程序窗口的全部区域都重新绘制。
--mSurface:它指向一个Java层的Surface对象,用来描述一个应用程序窗口的绘图表面。
scheduleTraversals performTraversals
mView DecorView
那么应用程序进程的UI线程就会调用另外一个成员函数relayoutWindow来请求WindowManagerService服务重新布局系统中的所有窗口。
ViewRoot
performTraversals
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
int relayoutResult = mWindowSession.relayout(
过在重绘之前,会先询问一下那些注册到当前正在处理的应用程序窗口中的Tree Observer,即调用它们的成员函数dispatchOnPreDraw,看看它们是否需要取消接下来的重绘操作,这个询问结果保存在本地变量cancelDraw中。
private final Surface mSurface = new Surface();
实现了IWindowSession接口的Binder代理对象是由IWindowSession.Stub.Proxy类来描述的,
接下来我们就继续分析它的成员函数relayout的实现。
IWindowSession IWindowSession.Stub.Proxy类
interface IWindowSession {
......
int relayout(IWindow window, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
boolean insetsPending, out Rect outFrame, out Rect outContentInsets,
out Rect outVisibleInsets, out Configuration outConfig,
out Surface outSurface);
......
}
这个接口定义在frameworks/base/core/java/android/view/IWindowSession.aidl文件
使用AIDL语言来描述的IWindowSession接口被编译后,就会生成一个使用Java语言来描述的IWindowSession.Stub.Proxy类,
它的成员函数relayout的实现如下所示:
AIDL
IWindowSession.aidl文件中。
Stub IWindowSession
Proxy IBinder mReadyToShow
relayout
Parcel.obtain
编译生成的文件
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IWindowSession.java中。
IWindowSession.Stub.Proxy类的成员函数relayout首先将从前面传进来的各个参数写入到Parcel对象_data中,接着再通过其成员变量mRemote所描述的一个Binder代理对象向运行在WindowManagerService服务内部的一个Session对象发送一个类型为TRANSACTION_relayout的进程间通信请求,其中,这个Session对象是用来描述从当前应用程序进程到WindowManagerService服务的一个连接的。
当运行在WindowManagerService服务内部的Session对象处理完成当前应用程序进程发送过来的类型为TRANSACTION_relayout的进程间通信请求之后,就会将处理结果写入到Parcel对象_reply中,并且将这个Parcel对象_reply返回给当前应用程序进程处理。返回结果包含了一系列与参数window所描述的应用程序窗口相关的参数,如下所示:
1. 窗口的大小:最终保存在输出参数outFrame中。
2. 窗口的内容区域边衬大小:最终保存在输出参数outContentInsets中。
3. 窗口的可见区域边衬大小:最终保存在输出参数outVisibleInsets中。
4. 窗口的配置信息:最终保存在输出参数outConfig中。
5. 窗口的绘图表面:最终保存在输出参数outSurface中。
outSurface
public int relayoutWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending,
Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Configuration outConfig, Surface outSurface) {
WindowState win = windowForClientLocked(session, client, false);
WindowState mAppToken Activity
如果这个绘图表面能创建成功,那么WindowManagerService类的成员函数relayoutWindow就会将它的内容拷贝到输出参数outSource所描述的一个Surface对象去,以便可以将它返回给应用程序进程处理。
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
if (surfaceControl != null) {
outSurface.copyFrom(surfaceControl);
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
outSurface.release();
}
mSurface = new Surface(
mSession.mSurfaceSession, mSession.mPid,
mAttrs.getTitle().toString(),
0, w, h, mAttrs.format, flags);
......
SurfaceSession
Surface
--mReportDestroySurface的值被设置为false。当一个应用程序窗口的绘图表面被销毁时,WindowManagerService服务就会将相应的WindowState对象的成员变量mReportDestroySurface的值设置为true,表示要向该应用程序窗口所运行在应用程序进程发送一个绘图表面销毁通知。
--mSurfacePendingDestroy的值被设置为false。当一个应用程序窗口的绘图表面正在等待销毁时,WindowManagerService服务就会将相应的WindowState对象的成员变量mReportDestroySurface的值设置为true。
绘图表面
--如果成员变量mAppToken的值不等于null,那么就需要将它所描述的一个AppWindowToken对象的成员变量allDrawn的值设置为false。从前面Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析一文可以知道,一个AppWindowToken对象用来描述一个Activity组件的,当该AppWindowToken对象的成员变量allDrawn的值等于true时,就表示属于该Activity组件的所有窗口都已经绘制完成了。
public class Surface implements Parcelable {
......
private int mSurfaceControl;
......
private Canvas mCanvas;
......
private String mName;
......
public Surface(SurfaceSession s,
int pid, String name, int display, int w, int h, int format, int flags)
throws OutOfResourcesException {
......
mCanvas = new CompatibleCanvas();
init(s,pid,name,display,w,h,format,flags);
mName = name;
}
......
private native void init(SurfaceSession s,
int pid, String name, int display, int w, int h, int format, int flags)
throws OutOfResourcesException;
......
}
mSurfaceControl
static void Surface_init(
JNIEnv* env, jobject clazz,
jobject session,
jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
{
if (session == NULL) {
doThrow(env, "java/lang/NullPointerException");
return;
}
SurfaceComposerClient* client =
(SurfaceComposerClient*)env->GetIntField(session, sso.client);
sp<SurfaceControl> surface;
if (jname == NULL) {
surface = client->createSurface(pid, dpy, w, h, format, flags);
} else {
const jchar* str = env->GetStringCritical(jname, 0);
const String8 name(str, env->GetStringLength(jname));
env->ReleaseStringCritical(jname, str);
surface = client->createSurface(pid, name, dpy, w, h, format, flags);
}
if (surface == 0) {
doThrow(env, OutOfResourcesException);
return;
}
setSurfaceControl(env, clazz, surface);
}
SurfaceComposerClient*
WindowManagerService
DecorView
Android应用程序窗口(Activity)的绘图表面(Surface)的创建过程分析相关推荐
- Android应用程序资源管理器(Asset Manager)的创建过程分析
在前面一篇文章中,我们分析了Android应用程序资源的编译和打包过程,最终得到的应用程序资源就与应用程序代码一起打包在一个APK文件中.Android应用程序在运行的过程中,是通过一个称为Asset ...
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析(上)...
在前面一篇文章中,我们分析了Android应用程序窗口的绘图表面的创建过程.Android应用程序窗口的绘图表面在创建完成之后,我们就可以从上到下地绘制它里面的各个视图了,即各个UI元素了.不过在绘制 ...
- Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析
在前两文中,我们分析了Activity组件的窗口对象和视图对象的创建过程.Activity组件在其窗口对象和视图对象创建完成之后,就会请求与WindowManagerService建立一个连接,即请求 ...
- Android应用程序窗口(Activity)的视图对象(View)的创建过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8245546 从前文可知道,每一个Activit ...
- Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析
在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...
- Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析
出自:http://blog.csdn.net/luoshengyang/article/details/8201936 在前文中,我们简要介绍了Android应用程序窗口的框架.Android应用程 ...
- Android基本程序单元Activity总结
1.什么是Activity? 在Android当中,Activity提供可视化的用户界面,一个Android应用通常由多个Activity组成.多个Activity组成了Activity栈(Stack ...
- 解开Android应用程序组件Activity的singleTask之谜(3)
回到前面的startActivityUncheckedLocked函数中,这里的变量top就为null了,于是执行下面的else语句: if (top != null) { ...... } else ...
- Android应用程序注冊广播接收器(registerReceiver)的过程分析
前面我们介绍了Android系统的广播机制,从本质来说,它是一种消息订阅/公布机制,因此,使用这样的消息驱动模型的第一步便是订阅消息:而对Android应用程序来说,订阅消息事实上就是注冊广播接收器, ...
最新文章
- python简单装饰器_python装饰器的简单示例
- oracle if=,oracle中if/else的三种实现方式详解
- 深入学习Redis高可用架构:哨兵原理及实践
- pandas DataFrame isin
- Linux每次开机都要source /etc/profile的解决方法
- VS编译提示错误“....Consider using strcat_s instead.To disable deprecation, use _CRT_SECURE_NO_WARNINGS.”
- Gym - 102460A Rush Hour Puzzle(dfs迭代加深)
- 本地项目antd 修改.less文件导致内存溢出
- Python一亿以内的素数个数_Python 计数质数
- 【SpringCloud】Spring cloud Alibaba Sentinel 规则持久化
- BZOJ.1178.[APIO2009]会议中心(贪心 倍增)
- centos php7.0 mysql,如何在centos7.3系统下安装php7.0
- 黑客都使用什么编程语言?
- 域名不要www如何解析
- css3中自适应边框图片运用
- Java程序员都是青春饭吗?
- 阿里云服务器采用AMD CPU处理器ECS实例规格详解
- 华为2019春招留学生笔试第三题python
- 618终极剁手攻略,收割全套数据分析师课程!
- Java返回报文有单双引号_Spring MVC 响应结果有反斜杠转义字符+双引号
热门文章
- Javascript面向对象深入-两小时实现坦克大战(含源码+工具+具体流程)
- 链式调用和解决回调地狱的终极解决方法async,await
- 【电脑一点通】美图秀秀创建动态照片
- 沁恒微CH32V307开发板试用-RT-Thread+UART+LWIP+LED
- abb机器人指令手册_ABB机器人独立轴非同步联动
- 折腾amd加持的tensorflow和keras
- 在线进行复杂数学计算的网站——云算子
- Halcon算子总结
- SonarQube 7.7 中文插件安装
- 胡玮炜卸任后美团将优化裁员;爆料称罗永浩卸任锤子科技CEO;华为麒麟985首次曝光 | 雷锋早报...