performLayout

frameworks\base\core\java\android\view\ViewRootImpl.java


?



private          void          performLayout() {        


                  mLayoutRequested =          false         ;        


                  mScrollMayChange =          true         ;        


                  final          View host = mView;        


                  if          (DEBUG_ORIENTATION || DEBUG_LAYOUT) {        


                  Log.v(TAG,          "Laying out "          + host +          " to ("          +        


                  host.getMeasuredWidth() +          ", "          + host.getMeasuredHeight() +          ")"         );        


                  }        


                  Trace.traceBegin(Trace.TRACE_TAG_VIEW,          "layout"         );        


                  try          {        


                  host.layout(         0         ,          0         , host.getMeasuredWidth(), host.getMeasuredHeight());        


                  }          finally          {        


                  Trace.traceEnd(Trace.TRACE_TAG_VIEW);        


                  }        


         }



performDraw

frameworks\base\core\java\android\view\ ViewRootImpl.java


?




private          void          performDraw() {        


                  if          (!mAttachInfo.mScreenOn && !mReportNextDraw) {        


                  return         ;        


                  }        


                  final          boolean          fullRedrawNeeded = mFullRedrawNeeded;        


                  mFullRedrawNeeded =          false         ;        


                  mIsDrawing =          true         ;        


                  Trace.traceBegin(Trace.TRACE_TAG_VIEW,          "draw"         );        


                  try          {        


                  draw(fullRedrawNeeded);        


                  }          finally          {        


                  mIsDrawing =          false         ;        


                  Trace.traceEnd(Trace.TRACE_TAG_VIEW);        


                  }        


                  ...        


         }



?




private          void          draw(         boolean          fullRedrawNeeded) {        


                  Surface surface = mSurface;        


                  if          (surface ==          null          || !surface.isValid()) {        


                  return         ;        


                  }        


                  ...        


                  if          (!dirty.isEmpty() || mIsAnimating) {        


                  //使用硬件渲染        


                  if          (attachInfo.mHardwareRenderer !=          null          && attachInfo.mHardwareRenderer.isEnabled()) {        


                  // Draw with hardware renderer.        


                  mIsAnimating =          false         ;        


                  mHardwareYOffset = yoff;        


                  mResizeAlpha = resizeAlpha;        


                  mCurrentDirty.set(dirty);        


                  mCurrentDirty.union(mPreviousDirty);        


                  mPreviousDirty.set(dirty);        


                  dirty.setEmpty();        


                  if          (attachInfo.mHardwareRenderer.draw(mView, attachInfo,          this         ,        


                  animating ?          null          : mCurrentDirty)) {        


                  mPreviousDirty.set(         0         ,          0         , mWidth, mHeight);        


                  }        


                  //使用软件渲染        


                  }          else          if          (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {        


                  return         ;        


                  }        


                  }        


                  ...        


         }
private          void          draw(         boolean          fullRedrawNeeded) {        


                  Surface surface = mSurface;        


                  if          (surface ==          null          || !surface.isValid()) {        


                  return         ;        


                  }        


                  ...        


                  if          (!dirty.isEmpty() || mIsAnimating) {        


                  //使用硬件渲染        


                  if          (attachInfo.mHardwareRenderer !=          null          && attachInfo.mHardwareRenderer.isEnabled()) {        


                  // Draw with hardware renderer.        


                  mIsAnimating =          false         ;        


                  mHardwareYOffset = yoff;        


                  mResizeAlpha = resizeAlpha;        


                  mCurrentDirty.set(dirty);        


                  mCurrentDirty.union(mPreviousDirty);        


                  mPreviousDirty.set(dirty);        


                  dirty.setEmpty();        


                  if          (attachInfo.mHardwareRenderer.draw(mView, attachInfo,          this         ,        


                  animating ?          null          : mCurrentDirty)) {        


                  mPreviousDirty.set(         0         ,          0         , mWidth, mHeight);        


                  }        


                  //使用软件渲染        


                  }          else          if          (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {        


                  return         ;        


                  }        


                  }        


                  ...        


         }
private          void          draw(         boolean          fullRedrawNeeded) {        


                  Surface surface = mSurface;        


                  if          (surface ==          null          || !surface.isValid()) {        


                  return         ;        


                  }        


                  ...        


                  if          (!dirty.isEmpty() || mIsAnimating) {        


                  //使用硬件渲染        


                  if          (attachInfo.mHardwareRenderer !=          null          && attachInfo.mHardwareRenderer.isEnabled()) {        


                  // Draw with hardware renderer.        


                  mIsAnimating =          false         ;        


                  mHardwareYOffset = yoff;        


                  mResizeAlpha = resizeAlpha;        


                  mCurrentDirty.set(dirty);        


                  mCurrentDirty.union(mPreviousDirty);        


                  mPreviousDirty.set(dirty);        


                  dirty.setEmpty();        


                  if          (attachInfo.mHardwareRenderer.draw(mView, attachInfo,          this         ,        


                  animating ?          null          : mCurrentDirty)) {        


                  mPreviousDirty.set(         0         ,          0         , mWidth, mHeight);        


                  }        


                  //使用软件渲染        


                  }          else          if          (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {        


                  return         ;        


                  }        


                  }        


                  ...        


         }



窗口添加过程

frameworks\base\services\java\com\android\server\wm\Session.java


?



1



2



3



4



5


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);



}



frameworks\base\services\java\com\android\server\wm\WindowManagerService.java


?




public          int          addWindow(Session session, IWindow client,          int          seq,        


                  WindowManager.LayoutParams attrs,          int          viewVisibility,        


                  Rect outContentInsets, InputChannel outInputChannel) {        


                  //client为IWindow的代理对象,是Activity在WMS服务中的唯一标示        


                  int          res = mPolicy.checkAddPermission(attrs);        


                  if          (res != WindowManagerImpl.ADD_OKAY) {        


                  return          res;        


                  }        


                  boolean          reportNewConfig =          false         ;        


                  WindowState attachedWindow =          null         ;        


                  WindowState win =          null         ;        


                  long          origId;        


                  synchronized         (mWindowMap) {        


                  if          (mDisplay ==          null         ) {        


                  throw          new          IllegalStateException(         "Display has not been initialialized"         );        


                  }        


                  //判断窗口是否已经存在        


                  if          (mWindowMap.containsKey(client.asBinder())) {        


                  Slog.w(TAG,          "Window "          + client +          " is already added"         );        


                  return          WindowManagerImpl.ADD_DUPLICATE_ADD;        


                  }        


                  //如果添加的是应用程序窗口        


                  if          (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {        


                  //根据attrs.token从mWindowMap中取出应用程序窗口在WMS服务中的描述符WindowState        


                  attachedWindow = windowForClientLocked(         null         , attrs.token,          false         );        


                  if          (attachedWindow ==          null         ) {        


                  Slog.w(TAG,          "Attempted to add window with token that is not a window: "        


                  + attrs.token +          ".  Aborting."         );        


                  return          WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;        


                  }        


                  if          (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW        


                  && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {        


                  Slog.w(TAG,          "Attempted to add window with token that is a sub-window: "        


                  + attrs.token +          ".  Aborting."         );        


                  return          WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;        


                  }        


                  }        


                  boolean          addToken =          false         ;        


                  //根据attrs.token从mWindowMap中取出应用程序窗口在WMS服务中的描述符WindowState        


                  WindowToken token = mTokenMap.get(attrs.token);        


                  if          (token ==          null         ) {        


                  ...        


                  ①token =          new          WindowToken(         this         , attrs.token, -         1         ,          false         );        


                  addToken =          true         ;        


                  }         


                  //应用程序窗口        


                  else          if          (attrs.type >= FIRST_APPLICATION_WINDOW        


                  && attrs.type <= LAST_APPLICATION_WINDOW) {        


                  AppWindowToken atoken = token.appWindowToken;        


                  ...        


                  }         


                  //输入法窗口        


                  else          if          (attrs.type == TYPE_INPUT_METHOD) {        


                  ...        


                  }        


                  //墙纸窗口        


                  else          if          (attrs.type == TYPE_WALLPAPER) {        


                  ...        


                  }        


                  //Dream窗口        


                  else          if          (attrs.type == TYPE_DREAM) {        


                  ...        


                  }        


                  //为Activity窗口创建WindowState对象        


                  ②win =          new          WindowState(         this         , session, client, token,        


                  attachedWindow, seq, attrs, viewVisibility);        


                  ...        


                  if          (outInputChannel !=          null          && (attrs.inputFeatures& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) ==          0         ) {        


                  String name = win.makeInputChannelName();        


                  InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);        


                  win.setInputChannel(inputChannels[         0         ]);        


                  inputChannels[         1         ].transferTo(outInputChannel);        


                  mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);        


                  }        


                  ...        


                  //以键值对<iwindow.proxy token,windowtoken="">形式保存到mTokenMap表中        


                  if          (addToken) {        


                  ③mTokenMap.put(attrs.token, token);        


                  }        


                  ④win.attach();        


                  //以键值对<iwindow的代理对象,windowstate>形式保存到mWindowMap表中        


                  ⑤mWindowMap.put(client.asBinder(), win);        


                  ...        


                  }        


                  ...        


                  return          res;        


         }        


         </iwindow的代理对象,windowstate></iwindow.proxy>


我们知道当应用程序进程添加一个DecorView到窗口管理器时,会为当前添加的窗口创建ViewRootImpl对象,同时构造了一个W本地Binder对象,无论是窗口视图对象DecorView还是ViewRootImpl对象,都只是存在于应用程序进程中,在添加窗口过程中仅仅将该窗口的W对象传递给WMS服务,经过Binder传输后,到达WMS服务端进程后变为IWindow.Proxy代理对象,因此该函数的参数client的类型为IWindow.Proxy。参数attrs的类型为WindowManager.LayoutParams,在应用程序进程启动Activity时,handleResumeActivity()函数通过WindowManager.LayoutParams l = r.window.getAttributes();来得到应用程序窗口布局参数,由于WindowManager.LayoutParams实现了Parcelable接口,因此WindowManager.LayoutParams对象可以跨进程传输,WMS服务的addWindow函数中的attrs参数就是应用程序进程发送过来的窗口布局参数。在LocalWindowManager的addView函数中为窗口布局参数设置了相应的token,如果是应用程序窗口,则布局参数的token设为W本地Binder对象。如果不是应用程序窗口,同时当前窗口没有父窗口,则设置token为当前窗口的IApplicationToken.Proxy代理对象,否则设置为父窗口的IApplicationToken.Proxy代理对象,由于应用程序和WMS分属于两个不同的进程空间,因此经过Binder传输后,布局参数的令牌attrs.token就转变为IWindow.Proxy或者Token。以上函数首先根据布局参数的token等信息构造一个WindowToken对象,然后在构造一个WindowState对象,并将添加的窗口信息记录到mTokenMap和mWindowMap哈希表中。



在WMS服务端创建了所需对象后,接着调用了WindowState的attach()来进一步完成窗口添加。
frameworks\base\services\java\com\android\server\wm\WindowState.java


?



void          attach() {        


                  if          (WindowManagerService.localLOGV) Slog.v(        


                  TAG,          "Attaching "          +          this          +          " token="          + mToken        


                  +          ", list="          + mToken.windows);        


                  mSession.windowAddedLocked();        


         }


frameworks\base\services\java\com\android\server\wm\Session.java


?




void          windowAddedLocked() {        


                  if          (mSurfaceSession ==          null         ) {        


                  mSurfaceSession =          new          SurfaceSession();        


                  if          (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(        


                  WindowManagerService.TAG,          "  NEW SURFACE SESSION "          + mSurfaceSession);        


                  mService.mSessions.add(         this         );        


                  }        


                  mNumWindow++;         //记录对应的某个应用程序添加的窗口数量        


         }


到此一个新的应用程序窗口就添加完成了。总结一下:

应用程序通过IWindowSession接口请求WMS服务添加一个应用程序窗口,WMS服务首先在自己服务进程为应用程序创建创建一个对应的WindowState描述符,然后保存到成员变量mWindowMap中。如果还没有为应用程序进程创建连接SurfaceFlinger的会话,就接着创建该会话通道SurfaceSession,我们知道,Activity中的视图所使用的画布Surface是在WMS服务进程中创建的,但是该画布所使用的图形buffer确实在SurfaceFlinger进程中分配管理的,而图形的绘制确是在应用程序进程中完成的,所以Activity的显示过程需要三个进程的配合才能完成。应用程序进程只与WMS服务进程交互,并不直接和SurfaceFlinger进程交互,而是由WMS服务进程同SurfaceFlinger进程配合。前面我们介绍了应用程序进程是通过IWindowSession接口与WMS服务进程通信的,那WMS服务是如何与SurfaceFlinger进程通信的呢,这就是windowAddedLocked函数要完成的工作。


在windowAddedLocked函数中使用单例模式创建一个SurfaceSession对象,在构造该对象时,通过JNI在native层创建一个与SurfaceFlinger进程的连接。

frameworks\base\core\java\android\view\SurfaceSession.java


?



public          SurfaceSession() {        


                  init();        


         }


该init()函数是一个native函数,其JNI实现如下:

f

rameworks\base\core\jni\ 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());        


         }        


         </surfacecomposerclient>


该函数构造了一个SurfaceComposerClient对象,在第一次强引用该对象时,会请求SurfaceFlinger创建一个专门处理当前应用程序进程请求的Client会话。


系统中创建的所有IWindowSession都被记录到WMS服务的mSessions成员变量中,这样WMS就可以知道自己正在处理那些应用程序的请求。到此我们来梳理一下在WMS服务端都创建了那些对象:

1) WindowState对象,是应用程序窗口在WMS服务端的描述符;

2) Session对象,应用程序进程与WMS服务会话通道;

3) SurfaceSession对象,应用程序进程与SurfaceFlinger的会话通道;