Activity是在onResume里显示出来的,下面看下具体的流程。
ActivityThread.java
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
// ...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l); //关键
}
//...
}
关键的函数是wm.addView,这个wm是啥呢?
ViewManager.java中可以看到,就是一接口,那肯定要找到实现他的类,搜索下发现是WindowManager.java,可是这货里也没有具体的,继续找实现Windomanager的家伙。
最后可以找到实际是WindowManagerImpl.java实现了这个方法。
WindowManagerImpl.java
private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
{
//...
root = new ViewRoot(view.getContext());
root.mAddNesting = 1;
view.setLayoutParams(wparams);
if (mViews == null) {
index = 1;
mViews = new View[1];
mRoots = new ViewRoot[1];
mParams = new WindowManager.LayoutParams[1];
} else {
index = mViews.length + 1;
Object[] old = mViews;
mViews = new View[index];
System.arraycopy(old, 0, mViews, 0, index-1);
old = mRoots;
mRoots = new ViewRoot[index];
System.arraycopy(old, 0, mRoots, 0, index-1);
old = mParams;
mParams = new WindowManager.LayoutParams[index];
System.arraycopy(old, 0, mParams, 0, index-1);
}
index--;
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
}
// do this last because it fires off messages to start doing things
root.setView(view, wparams, panelParentView);
}
如果不深究里面每一句话的意思,大体上看来就是new了一个ViewRoot,然后把各种参数传入,调用它的setView方法。
这里我们有必要看一下ViewRoot,这货虽然看上去是个View穷屌丝,其实是个高帅富:
ViewRoot.java
public final class ViewRoot extends Handler implements ViewParent,
View.AttachInfo.Callbacks {
看这声明,原来本体就是个handle,实现了一些方法。
看下里面的成员变量,比较关键的是
static IWindowSession sWindowSession;
private final Surface mSurface = new Surface();
看看他的构造函数:
public ViewRoot(Context context) {
super();
if (MEASURE_LATENCY && lt == null) {
lt = new LatencyTimer(100, 1000);
}
// For debug only
//++sInstanceCount;
// Initialize the statics when this class is first instantiated. This is
// done here instead of in the static block because Zygote does not
// allow the spawning of threads.
getWindowSession(context.getMainLooper());
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();
mWindow = new W(this, context);
mInputMethodCallback = new InputMethodCallback(this);
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
}
通过getWindowSession方法得到了Session的本地代理IWindowSession,并保存在变量sWindowSession中
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
if (!mInitialized) {
try {
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
sWindowSession = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"))
.openSession(imm.getClient(), imm.getInputContext());
mInitialized = true;
} catch (RemoteException e) {
}
}
return sWindowSession;
}
}
这里简单的说下,
IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
就是通过ServiceManager得到windowManagerService的本地代理,并通过这个本地代理来调用远程WMS的方法openSession,返回Session对应的本地代理对象IWindowSession。
而 一开始的 private final Surface mSurface = new Surface();调用了无参的构造函数,实际上没有干啥活,当前的surface是无效的。
public Surface() {
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
mCanvas = new CompatibleCanvas();
}
接着继续看setView();
public void setView(View view, WindowManager.LayoutParams attrs,
View panelParentView) {
//...
requestLayout();
mInputChannel = new InputChannel();
try {
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
} catch (RemoteException e) {
mAdded = false;
mView = null;
mAttachInfo.mRootView = null;
mInputChannel = null;
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
attrs.restore();
}
}
//...
}
requestLayout()和sWindowSession.add方法是最关键的。我们分别来看。
requestLayout只是给ViewRoot的handle发送DO_TRAVERSAL消息,handle收到消息后,会调用performTraversals()
这个方法巨长无比,简直不忍直视,我们主要是看和surface的联系,就挑着看。
private void performTraversals() {
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
draw(fullRedrawNeeded);
}
看看relayoutWindow(),这个方法里对surface有了重新的赋值:
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
float appScale = mAttachInfo.mApplicationScale;
boolean restore = false;
if (params != null && mTranslator != null) {
restore = true;
params.backup();
mTranslator.translateWindowLayout(params);
}
if (params != null) {
if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
}
mPendingConfiguration.seq = 0;
//Log.d(TAG, ">>>>>> CALLING relayout");
int relayoutResult = sWindowSession.relayout(
mWindow, params,
(int) (mView.mMeasuredWidth * appScale + 0.5f),
(int) (mView.mMeasuredHeight * appScale + 0.5f),
viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);
//Log.d(TAG, "<<<<<< BACK FROM relayout");
if (restore) {
params.restore();
}
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
}
return relayoutResult;
}
实际通过Session的本地代理Binder sWindowSession来调用了远程的方法:
WindowManagerService.java
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
boolean insetsPending, Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
//Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
int res = relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, insetsPending,
outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
//Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
return res;
}
这里把传入的surface叫做outSruface是别有深意的。
继续分析
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);
//...
try {
Surface surface = win.createSurfaceLocked();
if (surface != null) {
outSurface.copyFrom(surface);//通过windowState来创建一个新的surface并返回给传入的surface,这样surface和native的surface就联系起来了。
win.mReportDestroySurface = false;
win.mSurfacePendingDestroy = false;
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();
}
} catch (Exception e) {
mInputMonitor.updateInputWindowsLw();
Slog.w(TAG, "Exception thrown when creating surface for client "
+ client + " (" + win.mAttrs.getTitle() + ")",
e);
Binder.restoreCallingIdentity(origId);
return 0;
}
//...
}
relayoutWindow中首先是取出了Clinet对应的windowstate对象,通过他去调用createSurfaceLocked,并返回给传入的surface,到这里,ViewRoot里的mSurface就有了灵魂!
每一个Client都有唯一的一个windowstate对象。ViewRoot-mWindow------WindowState都是一一对应的关系,这个对象是什么时候被创建的? 下面会降到
接下来继续分析createSurfaceLocked
Surface createSurfaceLocked() {
//......
try {
mSurface = new Surface(
mSession.mSurfaceSession, mSession.mPid,
mAttrs.getTitle().toString(),
0, w, h, mAttrs.format, flags);
if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
+ mSurface + " IN SESSION "
+ mSession.mSurfaceSession
+ ": pid=" + mSession.mPid + " format="
+ mAttrs.format + " flags=0x"
+ Integer.toHexString(flags)
+ " / " + this);
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "OutOfResourcesException creating surface");
reclaimSomeSurfaceMemoryLocked(this, "create");
return null;
} catch (Exception e) {
Slog.e(TAG, "Exception creating surface", e);
return null;
}
//......
}
在这里调用了surface的有参的构造函数
surface.java
/**
* create a surface with a name
* {@hide}
*/
public Surface(SurfaceSession s,
int pid, String name, int display, int w, int h, int format, int flags)
throws OutOfResourcesException {
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
mCanvas = new CompatibleCanvas();
init(s,pid,name,display,w,h,format,flags);
mName = name;
}
和无参的不一样,这里调用了native的init
android_view_surface.cpp
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);//获取出session中的SurfaceComposerClient对象,这个对象是怎么来//的?下文会讲到
sp<SurfaceControl> surface;
if (jname == NULL) {
surface = client->createSurface(pid, dpy, w, h, format, flags);//调用SurfaceComposerClient方法,创建一个SurfaceControl对象,该对//象封装了Isurface和SurfaceComposerClient的一些方法,方便Client调用
} 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);//保存surfacecontrol对象
}
surfacecomposerclient和surfaceflinger的关系比较复杂,后面会另写blog来讲。
到这里surface就在native空间有了对应的surfacecontrol,就可以通过surfacecontrol来调用surfacefilnger的方法了。
回到Viewroot,接下来就是draw()方法
private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
if (!dirty.isEmpty() || mIsAnimating) {
Canvas canvas;//画布
try {
int left = dirty.left;
int top = dirty.top;
int right = dirty.right;
int bottom = dirty.bottom;
canvas = surface.lockCanvas(dirty);//surface锁定画布并返回,然后在canvas上画出各种元素
if (left != dirty.left || top != dirty.top || right != dirty.right ||
bottom != dirty.bottom) {
mAttachInfo.mIgnoreDirtyState = true;
}
// TODO: Do this in native
canvas.setDensity(mDensity);
} catch (Surface.OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException locking surface", e);
// TODO: we should ask the window manager to do something!
// for now we just do nothing
return;
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException locking surface", e);
// TODO: we should ask the window manager to do something!
// for now we just do nothing
return;
}
try {
if (!dirty.isEmpty() || mIsAnimating) {
long startTime = 0L;
if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Log.v(TAG, "Surface " + surface + " drawing to bitmap w="
+ canvas.getWidth() + ", h=" + canvas.getHeight());
//canvas.drawARGB(255, 255, 0, 0);
}
if (Config.DEBUG && ViewDebug.profileDrawing) {
startTime = SystemClock.elapsedRealtime();
}
// If this bitmap's format includes an alpha channel, we
// need to clear it before drawing so that the child will
// properly re-composite its drawing on a transparent
// background. This automatically respects the clip/dirty region
// or
// If we are applying an offset, we need to clear the area
// where the offset doesn't appear to avoid having garbage
// left in the blank areas.
if (!canvas.isOpaque() || yoff != 0) {
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
}
dirty.setEmpty();
mIsAnimating = false;
mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
mView.mPrivateFlags |= View.DRAWN;
if (DEBUG_DRAW) {
Context cxt = mView.getContext();
Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
", metrics=" + cxt.getResources().getDisplayMetrics() +
", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());
}
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
if (mTranslator != null) {
mTranslator.translateCanvas(canvas);
}
canvas.setScreenDensity(scalingRequired
? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);//调用传入decorView的draw方法
} finally {
mAttachInfo.mIgnoreDirtyState = false;
canvas.restoreToCount(saveCount);
}
if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
}
if (SHOW_FPS || Config.DEBUG && ViewDebug.showFps) {
int now = (int)SystemClock.elapsedRealtime();
if (sDrawTime != 0) {
nativeShowFPS(canvas, now - sDrawTime);
}
sDrawTime = now;
}
if (Config.DEBUG && ViewDebug.profileDrawing) {
EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
}
}
} finally {
surface.unlockCanvasAndPost(canvas);//保存并解锁
}
}
//..
}
这里就会调用View的draw,将数据画到canvas上。
我们回头看setView里的第二个方法:sWindowSession.add。
不知道大家看上面的时候有没有觉得奇怪,viewroot对应的windowstate是什么时候创建的?
就在add里。
IWindowSession的add方法就是Session的本地proxy方法,通过Binder机制后实际会调用到Session的add方法:
public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets,
outInputChannel);
}
直接调用WindowManagerService的addWindow方法:
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility,
Rect outContentInsets, InputChannel outInputChannel) {
//...
win = new WindowState(this, session, client, token,
//...
win.attach();
mWindowMap.put(client.asBinder(), win);}
其中和windowstate的创建相关的主要是这三句话,首先new了一个windowstate对象,其次调用它的attach方法,再其次将他放入全局的表中(和client一一对应)。
我们看下他的attach方法:
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
mSession就是上文传入的session:
void windowAddedLocked() {
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
mSurfaceSession = new SurfaceSession();//初始化surfacesession
if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
WindowManagerService.TAG, " NEW SURFACE SESSION " + mSurfaceSession);
mService.mSessions.add(this);//将session加入WMS的全局表中
}
mNumWindow++;
}
这里又看到了一个另外的对象--surfaceSession:
public SurfaceSession() {
init();
}
init是native的方法,本尊是在android_view_surface.cpp中的
static void SurfaceSession_init(JNIEnv* env, jobject clazz)
{
sp<SurfaceComposerClient> client = new SurfaceComposerClient;
client->incStrong(clazz);
env->SetIntField(clazz, sso.client, (int)client.get());
}
到这里我们就应该明白了上文中创建surfacecontrol的SurfaceComposerClient是哪里来的吧!