performTraversals函数相当复杂,其主要实现以下几个重要步骤:
1.执行窗口测量;
2.执行窗口注册;
3.执行窗口布局;
4.执行窗口绘图;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
private
void
performTraversals() {
// cache mView since it is used so much below...
final
View host = mView;
if
(host ==
null
|| !mAdded)
return
;
mWillDrawSoon =
true
;
boolean
windowSizeMayChange =
false
;
boolean
newSurface =
false
;
boolean
surfaceChanged =
false
;
WindowManager.LayoutParams lp = mWindowAttributes;
int
desiredWindowWidth;
int
desiredWindowHeight;
final
View.AttachInfo attachInfo = mAttachInfo;
final
int
viewVisibility = getHostVisibility();
boolean
viewVisibilityChanged = mViewVisibility != viewVisibility
|| mNewSurfaceNeeded;
WindowManager.LayoutParams params =
null
;
if
(mWindowAttributesChanged) {
mWindowAttributesChanged =
false
;
surfaceChanged =
true
;
params = lp;
}
...
/****************执行窗口测量******************/
boolean
layoutRequested = mLayoutRequested && !mStopped;
if
(layoutRequested) {
...
// Ask host how big it wants to be
windowSizeMayChange |= measureHierarchy(host, lp, res,
desiredWindowWidth, desiredWindowHeight);
}
...
/****************向WMS服务添加窗口******************/
if
(mFirst || windowShouldResize || insetsChanged ||
viewVisibilityChanged || params !=
null
) {
...
try
{
final
int
surfaceGenerationId = mSurface.getGenerationId();
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
}
catch
(RemoteException e) {
}
...
if
(!mStopped) {
boolean
focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) !=
0
);
if
(focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
...
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
}
}
}
/****************执行窗口布局******************/
final
boolean
didLayout = layoutRequested && !mStopped;
boolean
triggerGlobalLayoutListener = didLayout
|| attachInfo.mRecomputeGlobalAttributes;
if
(didLayout) {
performLayout();
...
}
...
/****************查找窗口焦点******************/
boolean
skipDraw =
false
;
if
(mFirst) {
// handle first focus request
if
(DEBUG_INPUT_RESIZE) Log.v(TAG,
"First: mView.hasFocus()="
+ mView.hasFocus());
if
(mView !=
null
) {
if
(!mView.hasFocus()) {
mView.requestFocus(View.FOCUS_FORWARD);
mFocusedView = mRealFocusedView = mView.findFocus();
if
(DEBUG_INPUT_RESIZE) Log.v(TAG,
"First: requested focused view="
+ mFocusedView);
}
else
{
mRealFocusedView = mView.findFocus();
if
(DEBUG_INPUT_RESIZE) Log.v(TAG,
"First: existing focused view="
+ mRealFocusedView);
}
}
if
((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) !=
0
) {
// The first time we relayout the window, if the system is
// doing window animations, we want to hold of on any future
// draws until the animation is done.
mWindowsAnimating =
true
;
}
}
else
if
(mWindowsAnimating) {
skipDraw =
true
;
}
/****************执行窗口绘制******************/
mFirst =
false
;
mWillDrawSoon =
false
;
mNewSurfaceNeeded =
false
;
mViewVisibility = viewVisibility;
...
boolean
cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw() ||
viewVisibility != View.VISIBLE;
if
(!cancelDraw && !newSurface) {
if
(!skipDraw || mReportNextDraw) {
if
(mPendingTransitions !=
null
&& mPendingTransitions.size() >
0
) {
for
(
int
i =
0
; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).startChangingAnimations();
}
mPendingTransitions.clear();
}
performDraw();
}
}
else
{
if
(viewVisibility == View.VISIBLE) {
// Try again
scheduleTraversals();
}
else
if
(mPendingTransitions !=
null
&& mPendingTransitions.size() >
0
) {
for
(
int
i =
0
; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).endChangingAnimations();
}
mPendingTransitions.clear();
}
}
}
|
performMeasure
frameworks\base\core\java\android\view\ViewRootImpl.java
1
2
3
4
5
6
7
8
|
private
void
performMeasure(
int
childWidthMeasureSpec,
int
childHeightMeasureSpec) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"measure"
);
try
{
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
finally
{
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
|
relayoutWindow
frameworks\base\core\java\android\view\ViewRootImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
private
int
relayoutWindow(WindowManager.LayoutParams params,
int
viewVisibility,
boolean
insetsPending)
throws
RemoteException {
...
int
relayoutResult = sWindowSession.relayout(
mWindow, mSeq, params,
(
int
) (mView.getMeasuredWidth() * appScale +
0
.5f),
(
int
) (mView.getMeasuredHeight() * appScale +
0
.5f),
viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING :
0
,
mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);
...
return
relayoutResult;
}
|
这里通过前面获取的IWindowSession代理对象请求WMS服务执行窗口布局,mSurface是ViewRootImpl的成员变量
1
|
private
final
Surface mSurface =
new
Surface();
|
frameworks\base\core\java\android\view\ Surface.java
1
2
3
4
5
6
7
|
public
Surface() {
checkHeadless();
if
(DEBUG_RELEASE) {
mCreationStack =
new
Exception();
}
mCanvas =
new
CompatibleCanvas();
}
|
该Surface构造函数仅仅创建了一个CompatibleCanvas对象,并没有对该Surface进程native层的初始化,到此我们知道应用程序进程为每个窗口对象都创建了一个Surface对象。并且将该Surface通过跨进程方式传输给WMS服务进程,我们知道,在Android系统中,如果一个对象需要在不同进程间传输,必须实现Parcelable接口,Surface类正好实现了Parcelable接口。ViewRootImpl通过IWindowSession接口请求WMS的完整过程如下:
frameworks\base\core\java\android\view\IWindowSession.java$ Proxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
public
int
relayout(android.view.IWindow window,
int
seq,
android.view.WindowManager.LayoutParams attrs,
int
requestedWidth,
int
requestedHeight,
int
viewVisibility,
int
flags,
android.graphics.Rect outFrame,
android.graphics.Rect outOverscanInsets,
android.graphics.Rect outContentInsets,
android.graphics.Rect outVisibleInsets,
android.content.res.Configuration outConfig,
android.view.Surface outSurface)
throws
android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int
_result;
try
{
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((window !=
null
)) ? (window.asBinder()): (
null
)));
_data.writeInt(seq);
if
((attrs !=
null
)) {
_data.writeInt(
1
);
attrs.writeToParcel(_data,
0
);
}
else
{
_data.writeInt(
0
);
}
_data.writeInt(requestedWidth);
_data.writeInt(requestedHeight);
_data.writeInt(viewVisibility);
_data.writeInt(flags);
mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply,
0
);
_reply.readException();
_result = _reply.readInt();
if
((
0
!= _reply.readInt())) {
outFrame.readFromParcel(_reply);
}
if
((
0
!= _reply.readInt())) {
outOverscanInsets.readFromParcel(_reply);
}
if
((
0
!= _reply.readInt())) {
outContentInsets.readFromParcel(_reply);
}
if
((
0
!= _reply.readInt())) {
outVisibleInsets.readFromParcel(_reply);
}
if
((
0
!= _reply.readInt())) {
outConfig.readFromParcel(_reply);
}
if
((
0
!= _reply.readInt())) {
outSurface.readFromParcel(_reply);
}
}
finally
{
_reply.recycle();
_data.recycle();
}
return
_result;
}
|
从该函数的实现可以看出,应用程序进程中创建的Surface对象并没有传递到WMS服务进程,只是读取WMS服务进程返回来的Surface。那么WMS服务进程是如何响应应用程序进程布局请求的呢?
frameworks\base\core\java\android\view\IWindowSession.java$ Stub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
public
boolean
onTransact(
int
code, android.os.Parcel data,
android.os.Parcel reply,
int
flags)
throws
android.os.RemoteException {
switch
(code) {
case
TRANSACTION_relayout: {
data.enforceInterface(DESCRIPTOR);
android.view.IWindow _arg0;
_arg0 = android.view.IWindow.Stub.asInterface(data.readStrongBinder());
int
_arg1;
_arg1 = data.readInt();
android.view.WindowManager.LayoutParams _arg2;
if
((
0
!= data.readInt())) {
_arg2 = android.view.WindowManager.LayoutParams.CREATOR
.createFromParcel(data);
}
else
{
_arg2 =
null
;
}
int
_arg3;
_arg3 = data.readInt();
int
_arg4;
_arg4 = data.readInt();
int
_arg5;
_arg5 = data.readInt();
int
_arg6;
_arg6 = data.readInt();
android.graphics.Rect _arg7;
_arg7 =
new
android.graphics.Rect();
android.graphics.Rect _arg8;
_arg8 =
new
android.graphics.Rect();
android.graphics.Rect _arg9;
_arg9 =
new
android.graphics.Rect();
android.graphics.Rect _arg10;
_arg10 =
new
android.graphics.Rect();
android.content.res.Configuration _arg11;
_arg11 =
new
android.content.res.Configuration();
android.view.Surface _arg12;
_arg12 =
new
android.view.Surface();
int
_result =
this
.relayout(_arg0, _arg1, _arg2, _arg3, _arg4,
_arg5, _arg6, _arg7, _arg8, _arg9, _arg10, _arg11, _arg12);
reply.writeNoException();
reply.writeInt(_result);
if
((_arg7 !=
null
)) {
reply.writeInt(
1
);
_arg7.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else
{
reply.writeInt(
0
);
}
if
((_arg8 !=
null
)) {
reply.writeInt(
1
);
_arg8.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else
{
reply.writeInt(
0
);
}
if
((_arg9 !=
null
)) {
reply.writeInt(
1
);
_arg9.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else
{
reply.writeInt(
0
);
}
if
((_arg10 !=
null
)) {
reply.writeInt(
1
);
_arg10.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else
{
reply.writeInt(
0
);
}
if
((_arg11 !=
null
)) {
reply.writeInt(
1
);
_arg11.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else
{
reply.writeInt(
0
);
}
if
((_arg12 !=
null
)) {
reply.writeInt(
1
);
_arg12.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else
{
reply.writeInt(
0
);
}
return
true
;
}
}
}
|
该函数可以看出,WMS服务在响应应用程序进程请求添加窗口时,首先在当前进程空间创建一个Surface对象,然后调用Session的relayout()函数进一步完成窗口添加过程,最后将WMS服务中创建的Surface返回给应用程序进程。
到目前为止,在应用程序进程和WMS服务进程分别创建了一个Surface对象,但是他们调用的都是Surface的无参构造函数,在该构造函数中并未真正初始化native层的Surface,那native层的Surface是在那里创建的呢?
frameworks\base\services\java\com\android\server\wm\ Session.java
1
2
3
4
5
6
7
8
9
10
|
public
int
relayout(IWindow window,
int
seq, WindowManager.LayoutParams attrs,
int
requestedWidth,
int
requestedHeight,
int
viewFlags,
int
flags, Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
int
res = mService.relayoutWindow(
this
, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outContentInsets, outVisibleInsets,
outConfig, outSurface);
return
res;
}
|
frameworks\base\services\java\com\android\server\wm\ WindowManagerService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public
int
relayoutWindow(Session session, IWindow client,
int
seq,
WindowManager.LayoutParams attrs,
int
requestedWidth,
int
requestedHeight,
int
viewVisibility,
int
flags,
Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
...
synchronized
(mWindowMap) {
// TODO(cmautner): synchronize on mAnimator or win.mWinAnimator.
WindowState win = windowForClientLocked(session, client,
false
);
if
(win ==
null
) {
return
0
;
}
...
if
(viewVisibility == View.VISIBLE &&
(win.mAppToken ==
null
|| !win.mAppToken.clientHidden)) {
...
try
{
if
(!win.mHasSurface) {
surfaceChanged =
true
;
}
//创建Surface
Surface surface = winAnimator.createSurfaceLocked();
if
(surface !=
null
) {
outSurface.copyFrom(surface);
}
else
{
outSurface.release();
}
}
catch
(Exception e) {
...
}
...
}
...
}
...
}
|
frameworks\base\services\java\com\android\server\wm\WindowStateAnimator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
Surface createSurfaceLocked() {
if
(mSurface ==
null
) {
...
try
{
...
if
(DEBUG_SURFACE_TRACE) {
mSurface =
new
SurfaceTrace(
mSession.mSurfaceSession, mSession.mPid,
attrs.getTitle().toString(),
0
, w, h, format, flags);
}
else
{
mSurface =
new
Surface(
mSession.mSurfaceSession, mSession.mPid,
attrs.getTitle().toString(),
0
, w, h, format, flags);
}
mWin.mHasSurface =
true
;
}
catch
(Surface.OutOfResourcesException e) {
...
}
Surface.openTransaction();
...
}
return
mSurface;
}
|
Surface创建过程
frameworks\base\core\java\android\view\Surface.java
1
2
3
4
5
6
7
8
9
10
|
public
Surface(SurfaceSession s,
int
pid, String name,
int
display,
int
w,
int
h,
int
format,
int
flags)
throws
OutOfResourcesException {
checkHeadless();
if
(DEBUG_RELEASE) {
mCreationStack =
new
Exception();
}
mCanvas =
new
CompatibleCanvas();
init(s,pid,name,display,w,h,format,flags);
mName = name;
}
|
frameworks\base\core\jni\ android_view_Surface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
static
void
Surface_init(
JNIEnv* env, jobject clazz,
jobject session,
jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
{
if
(session == NULL) {
doThrowNPE(env);
return
;
}
SurfaceComposerClient* client =
(SurfaceComposerClient*)env->GetIntField(session, sso.client);
sp<surfacecontrol> surface;
if
(jname == NULL) {
surface = client->createSurface(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(name, dpy, w, h, format, flags);
}
if
(surface ==
0
) {
jniThrowException(env, OutOfResourcesException, NULL);
return
;
}
setSurfaceControl(env, clazz, surface);
}</surfacecontrol>
|
到此才算真正创建了一个可用于绘图的Surface,从上面的分析我们可以看出,在WMS服务进程端,其实创建了两个Java层的Surface对象,第一个Surface使用了无参构造函数,仅仅构造一个Surface对象而已,而第二个Surface却使用了有参构造函数,参数指定了图象宽高等信息,这个Java层Surface对象还会在native层请求SurfaceFlinger创建一个真正能用于绘制图象的native层Surface。最后通过浅拷贝的方式将第二个Surface复制到第一个Surface中,最后通过writeToParcel方式写回到应用程序进程。
到目前为止,应用程序和WMS一共创建了3个Java层Surface对象,如上图所示,而真正能用于绘图的Surface只有3号,那么3号Surface与2号Surface之间是什么关系呢?outSurface.copyFrom(surface)
frameworks\base\core\jni\ android_view_Surface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
static
void
Surface_copyFrom(JNIEnv* env, jobject clazz, jobject other)
{
if
(clazz == other)
return
;
if
(other == NULL) {
doThrowNPE(env);
return
;
}
//得到当前Surface所引用的SurfaceControl对象
const
sp<surfacecontrol>& surface = getSurfaceControl(env, clazz);
//得到源Surface所引用的SurfaceControl对象
const
sp<surfacecontrol>& rhs = getSurfaceControl(env, other);
//如果它们引用的不是同一个SurfaceControl对象
if
(!SurfaceControl::isSameSurface(surface, rhs)) {
setSurfaceControl(env, clazz, rhs);
}
}
</surfacecontrol></surfacecontrol>
|
2号Surface引用到了3号Surface的SurfaceControl对象后,通过writeToParcel()函数写会到应用程序进程。
frameworks\base\core\jni\ android_view_Surface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
static
void
Surface_writeToParcel(
JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
{
Parcel* parcel = (Parcel*)env->GetIntField(
argParcel, no.native_parcel);
if
(parcel == NULL) {
doThrowNPE(env);
return
;
}
const
sp<surfacecontrol>& control(getSurfaceControl(env, clazz));
if
(control != NULL) {
SurfaceControl::writeSurfaceToParcel(control, parcel);
}
else
{
sp<surface> surface(Surface_getSurface(env, clazz));
if
(surface != NULL) {
Surface::writeToParcel(surface, parcel);
}
else
{
SurfaceControl::writeSurfaceToParcel(NULL, parcel);
}
}
if
(flags & PARCELABLE_WRITE_RETURN_VALUE) {
setSurfaceControl(env, clazz, NULL);
setSurface(env, clazz, NULL);
}
}
</surface></surfacecontrol>
|
由于2号Surface引用的SurfaceControl对象不为空,因此这里就将SurfaceControl对象写会给应用程序进程
frameworks\native\libs\gui\ Surface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
status_t SurfaceControl::writeSurfaceToParcel(
const
sp<surfacecontrol>& control, Parcel* parcel)
{
sp<isurface> sur;
uint32_t identity =
0
;
if
(SurfaceControl::isValid(control)) {
sur = control->mSurface;
identity = control->mIdentity;
}
parcel->writeStrongBinder(sur!=
0
? sur->asBinder() : NULL);
parcel->writeStrongBinder(NULL);
// NULL ISurfaceTexture in this case.
parcel->writeInt32(identity);
return
NO_ERROR;
}
</isurface></surfacecontrol>
|
写入Parcel包裹的对象顺序如下:
应用程序进程中的1号Surface通过readFromParcel()函数读取从WMS服务进程写回的Binder对象。
frameworks\base\core\jni\ android_view_Surface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
|
static
void
Surface_readFromParcel(
JNIEnv* env, jobject clazz, jobject argParcel)
{
Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
if
(parcel == NULL) {
doThrowNPE(env);
return
;
}
sp<surface> sur(Surface::readFromParcel(*parcel));
setSurface(env, clazz, sur);
}
</surface>
|
frameworks\native\libs\gui\ Surface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
sp<surface> Surface::readFromParcel(
const
Parcel& data) {
Mutex::Autolock _l(sCachedSurfacesLock);
sp<ibinder> binder(data.readStrongBinder());
sp<surface> surface = sCachedSurfaces.valueFor(binder).promote();
if
(surface ==
0
) {
surface =
new
Surface(data, binder);
sCachedSurfaces.add(binder, surface);
}
else
{
// The Surface was found in the cache, but we still should clear any
// remaining data from the parcel.
data.readStrongBinder();
// ISurfaceTexture
data.readInt32();
// identity
}
if
(surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) {
surface =
0
;
}
cleanCachedSurfacesLocked();
return
surface;
}
</surface></ibinder></surface>
|
应用程序进程中的1号Surface按相反顺序读取WMS服务端返回过来的Binder对象等数据,并构造一个native层的Surface对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Surface::Surface(
const
Parcel& parcel,
const
sp<ibinder>& ref)
: SurfaceTextureClient()
{
mSurface = interface_cast<isurface>(ref);
sp<ibinder> st_binder(parcel.readStrongBinder());
sp<isurfacetexture> st;
if
(st_binder != NULL) {
st = interface_cast<isurfacetexture>(st_binder);
}
else
if
(mSurface != NULL) {
st = mSurface->getSurfaceTexture();
}
mIdentity = parcel.readInt32();
init(st);
}
</isurfacetexture></isurfacetexture></ibinder></isurface></ibinder>
|
每个Activity可以有一个或多个Surface,默认情况下一个Activity只有一个Surface,当Activity中使用SurfaceView时,就存在多个Surface。Activity默认surface是在relayoutWindow过程中由WMS服务创建的,然后回传给应用程序进程,我们知道一个Surface其实就是应用程序端的本地窗口,关于Surface的初始化过程这里就不在介绍。