Acitivty显示战场转移

天王盖地虎,我是二百五,宝塔镇河妖,这还用你教。话不多说,我叫王菜鸟,我的名言是,菜鸟终究会长大,长大了就成菜鸡了。

简介

我们前面说了Activity能和UI有关具体的原因,那既然知道是ViewRoot是核心,那么就要知道怎么一个核心法,最后战场如何转移,转移后干什么了。而且前面,我们要说明performTraversals干什么,这部分其实不是我的重点,所以我这部分直接看别人的文章,把有用的东西复制过来了,我的重点在后面如何显示在第二部分。

image
image
image

第一个问题

 private void performTraversals() {
      ......
      //lp.width和lp.height在创建ViewGroup实例时值为MATCH_PARENT
      int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
      int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
      ......
      performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
      ......
      performLayout(lp, desiredWindowWidth, desiredWindowHeight);
      ......
      performDraw();
      ......
  }
  //执行rootView的测量
  private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
      Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
      try {
        //ViewGroup的measure()方法
          mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
      } finally {
          Trace.traceEnd(Trace.TRACE_TAG_VIEW);
      }
  }
  //执行layout操作
  private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
          int desiredWindowHeight) {
      mLayoutRequested = false;
      mScrollMayChange = true;
      mInLayout = true;
      final View host = mView;
      ......
      try {
        //viewRoot先进行layout
          host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
          mInLayout = false;
          //需要layout的子view的数量
          int numViewsRequestingLayout = mLayoutRequesters.size();
          if (numViewsRequestingLayout > 0) {
            //需要layout的子view
              ArrayList<View> validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters,
                      false);
              if (validLayoutRequesters != null) {
                  //如果view中有调用requestLayout()方法,则说明界面需要刷新
                  mHandlingLayoutInLayoutRequest = true;
                  int numValidRequests = validLayoutRequesters.size();
                  for (int i = 0; i < numValidRequests; ++i) {
                      final View view = validLayoutRequesters.get(i);
                      view.requestLayout();
                  }
                  //整个viewTree重新measure
                  measureHierarchy(host, lp, mView.getContext().getResources(),
                          desiredWindowWidth, desiredWindowHeight);
                  mInLayout = true;
                  //整个viewTree重新layout
                  host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
                  mHandlingLayoutInLayoutRequest = false;
                  // 再次检查是否有view需要刷新
                  validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, true);
                  if (validLayoutRequesters != null) {
                      final ArrayList<View> finalRequesters = validLayoutRequesters;
                      // Post请求,在下一帧的显示的时候去执行刷新
                      getRunQueue().post(new Runnable() {
                          @Override
                          public void run() {
                              int numValidRequests = finalRequesters.size();
                              for (int i = 0; i < numValidRequests; ++i) {
                                  final View view = finalRequesters.get(i);
                                  view.requestLayout();
                              }
                          }
                      });
                  }
              }
          }
      } finally {
          Trace.traceEnd(Trace.TRACE_TAG_VIEW);
      }
      mInLayout = false;
  }
  private void performDraw() {
      ......
      try {
          draw(fullRedrawNeeded);
      } finally {
          mIsDrawing = false;
          Trace.traceEnd(Trace.TRACE_TAG_VIEW);
      }
      ......
  }
  private void draw(boolean fullRedrawNeeded) {
      ......
      if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
    //使用硬件渲染,比如GPU
        mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
      } else {
    //使用软件渲染
          if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
              return;
          }
}
......
  }
   
  /**
   * @return true if drawing was successful, false if an error occurred
   */
  private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
          boolean scalingRequired, Rect dirty) {
      // Draw with software renderer.
      final Canvas canvas;
      ......
      try {
          canvas.translate(-xoff, -yoff);
          if (mTranslator != null) {
          mTranslator.translateCanvas(canvas);
          }
          canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
          attachInfo.mSetIgnoreDirtyState = false;
 
          mView.draw(canvas);
           
          drawAccessibilityFocusedDrawableIfNeeded(canvas);
      } finally {
          if (!attachInfo.mSetIgnoreDirtyState) {
          attachInfo.mIgnoreDirtyState = false;
          }
      }
      ......
      return true;
  }

上面是网上一个友人的拆解

也就是说我们终究会调用到View的三个方法

  • onMeasure
  • onLayout
  • onDraw

我们根据上面个图,我们已经调用到measure,layout,draw方法了。

下来就是分别调用

  • onMeasure
  • onLayout
  • onDraw

//final说明该函数不允许被子类override,不需要关注细节
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
       ......
       //widthMeasureSpec,heightMeasureSpec是由parent决定的
    onMeasure(widthMeasureSpec, heightMeasureSpec);
    ......
   }
    
   /**
    *
    * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
    * 
    * @param heightMeasureSpec vertical space requirements as imposed by the parent.
    * 
    * @see #getMeasuredWidth()
    * @see #getMeasuredHeight()
    * @see #setMeasuredDimension(int, int)
    * @see #getSuggestedMinimumHeight()
    * @see #getSuggestedMinimumWidth()
    * @see android.view.View.MeasureSpec#getMode(int)
    * @see android.view.View.MeasureSpec#getSize(int)
    */
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //View类的默认实现,如果自定义view的话,需要我们自己override
    //child的宽高有来自parent的widthMeasureSpec、heightMeasureSpec和子的MeasureSpecMode共同决定
       setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
               getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   }

注意onMeasure(int widthMeasureSpec, int heightMeasureSpec)入参的含义:

  1. widthMeasureSpec和heightMeasureSpec是parent暴露给child的尺寸
  2. widthMeasureSpec和heightMeasureSpec是32位的数值,其中高16位为MeasureSpecMode,低16位为MeasureSpecSize
  3. MeasureSpecMode有三种取值:
  • MeasureSpec.EXACTLY:child为精准尺寸(layout_with=mach_parent、24dp的情况)
  • MeasureSpec.AT_MOST:child为最大尺寸(layout_with=wrap_content的情况)
  • MeasureSpec.UNSPECIFIED:child未指定尺寸
    child的尺寸有parent穿过来的widthMeasureSpec、heightMeasureSpec和子的MeasureSpecMode共同决定
//非final类型,子类可以重载
public void layout(int l, int t, int r, int b) {
        ......
        int oldL = mLeft;
        int oldT = mTop;
        int oldB = mBottom;
        int oldR = mRight;
        boolean changed = isLayoutModeOptical(mParent) ?
                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
            onLayout(changed, l, t, r, b);
            ......
        }
        ......
    }
     
    //View的onlayout函数默认为空(如果自定义view中需要,可重载)
      protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
    }

/**
   * {@inheritDoc}
   */
  @Override
  public final void layout(int l, int t, int r, int b) {
      if (!mSuppressLayout && (mTransition == null || !mTransition.isChangingLayout())) {
          if (mTransition != null) {
              mTransition.layoutChange(this);
          }
          //view的layout方法
          super.layout(l, t, r, b);
      } else {
          mLayoutCalledWhileSuppressed = true;
      }
  }
  /**
   * 抽象方法,子类必须实现(因为内部必然存在多个view控件,需要layout)
   */
  @Override
  protected abstract void onLayout(boolean changed,
          int l, int t, int r, int b);
/**
    * ViewGroup的onLayout()方法都需要子类去实现
    * 所以我们来看一下LinearLayout的实现
    */
    @Override 
        protected void onLayout(boolean changed, int l, int t, int r, int b) {  
        if (mOrientation == VERTICAL) {  
            layoutVertical();  
        } else {  
            layoutHorizontal();  
        }  
    }
    
   //以垂直方向的布局为例
   void layoutVertical() {  
        ......  
        final int count = getVirtualChildCount();  
        ......
        //遍历child
        for (int i = 0; i < count; i++) {  
            final View child = getVirtualChildAt(i);  
            if (child == null) {  
                childTop += measureNullChild(i);  
            } else if (child.getVisibility() != GONE) {  
                final int childWidth = child.getMeasuredWidth();  
                final int childHeight = child.getMeasuredHeight();  
                ......
                //递归child调用layout
                setChildFrame(child, childLeft, childTop + getLocationOffset(child),  
                        childWidth, childHeight);  
                ......  
            }  
        }  
    }
     
    private void setChildFrame(View child, int left, int top, int width, int height) {          
        child.layout(left, top, left + width, top + height);  
}
  • View.layout方法可被重载,ViewGroup.layout为final的不可重载,ViewGroup.onLayout为abstract的,子类必须重载实现自己的位置逻辑。
  • measure操作完成后得到的是对每个View经测量过的measuredWidth和measuredHeight,layout操作 完成之后得到的是对每个View进行位置分配后的mLeft、mTop、mRight、mBottom,这些值都是相对于父View来说的
  • 凡是layout_XXX的布局属性基本都针对的是包含子View的ViewGroup的,当对一个没有父容器的View设置相关layout_XXX属性是没有任何意义的。
  • 使用View的getWidth()和getHeight()方法来获取View测量的宽高,必须保证这两个方法在onLayout流程之后被调用才能返回有效值。
public void draw(Canvas canvas) {
        ......
        /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *
         *      1. Draw the background
         *      2. If necessary, save the canvas' layers to prepare for fading
         *      3. Draw view's content
         *      4. Draw children
         *      5. If necessary, draw the fading edges and restore layers
         *      6. Draw decorations (scrollbars for instance)
         */
 
        // Step 1, draw the background, if needed
        ......
        if (!dirtyOpaque) {
            drawBackground(canvas);
        }
 
        // skip step 2 & 5 if possible (common case)
        ......
 
        // Step 2, save the canvas' layers
        ......
            if (drawTop) {
                canvas.saveLayer(left, top, right, top + length, null, flags);
            }
        ......
 
        // Step 3, draw the content
        if (!dirtyOpaque) onDraw(canvas);
 
        // Step 4, draw the children
        dispatchDraw(canvas);
 
        // Step 5, draw the fade effect and restore layers
        ......
        if (drawTop) {
            matrix.setScale(1, fadeHeight * topFadeStrength);
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(left, top, right, top + length, p);
        }
        ......
 
        // Step 6, draw decorations (scrollbars)
        onDrawScrollBars(canvas);
        ......
    }
  • View的onDraw()方法为空,需要用户自己实现
  • 关于draw,官方的注释已经很清楚,我们需要注意的是第四步:递归调用完成viewTree的绘制
  • dispatchdraw()为空,需要在子类去实现
/**
    * 遍历各种类型的情况的child,并draw
    */
   @Override
   protected void dispatchDraw(Canvas canvas) {
       boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);
       final int childrenCount = mChildrenCount;
       final View[] children = mChildren;
       
       ......
       for (int i = 0; i < childrenCount; i++) {
           ......
           if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
               more |= drawChild(canvas, child, drawingTime);
           }
       }
       while (transientIndex >= 0) {
           ......
           if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                   transientChild.getAnimation() != null) {
               more |= drawChild(canvas, transientChild, drawingTime);
           }
           ......
       }
        
       if (mDisappearingChildren != null) {
           ......
           for (int i = disappearingCount; i >= 0; i--) {
               final View child = disappearingChildren.get(i);
               more |= drawChild(canvas, child, drawingTime);
           }
       }
      ......
   }
    
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
       return child.draw(canvas, this, drawingTime);
   }

第二杀Surface

我们在ViewRoot的成员变量中发现了Surface的创建

// These can be accessed by any thread, must be protected with a lock.
// Surface can never be reassigned or cleared (use Surface.clear()).
final Surface mSurface = new Surface();

既然和绘制有关,那我们就去draw中找痕迹

CalledByGraph-ViewRootImpl-draw.png
ClusterCallbyGraph-ViewRootImpl-draw.png
private void draw(boolean fullRedrawNeeded) {
     Surface surface = mSurface;
      if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
            return;
      }
}
  private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty) {
            final Canvas canvas;
            final int left = dirty.left;
            final int top = dirty.top;
            final int right = dirty.right;
            final int bottom = dirty.bottom;
            canvas = mSurface.lockCanvas(dirty);
            mView.draw(canvas);
            surface.unlockCanvasAndPost(canvas);
...

我们看到Surface会调用lockCanvas,然后DroceView会调用draw在canvas上面绘画,最后surface会调用unlockCanvasAndPost提交绘画。释放内存

其实我以为到这里就分析的差不多了,但实际上才开始下来我们继续看,因为调用顺序:
performTraversals过程中调用了

relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
CalledByGraph-ViewRootImpl-relayoutWindow.png
   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");
        if (params != null && mOrigWindowType != params.type) {
            // For compatibility with old apps, don't crash here.
            if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                Slog.w(TAG, "Window type can not be changed after "
                        + "the window is added; ignoring change of " + mView);
                params.type = mOrigWindowType;
            }
        }
        int relayoutResult = mWindowSession.relayout(
                mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface);
        //Log.d(TAG, "<<<<<< BACK FROM relayout");
        if (restore) {
            params.restore();
        }

        if (mTranslator != null) {
            mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
            mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
        }
        return relayoutResult;
    }

这个方法的流程图:


ControlFlow(beta)Graph-ViewRootImpl-relayoutWindow.png

看到中间那个节点:

        int relayoutResult = mWindowSession.relayout(
                mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface);

我们还记得mWindowSession的地方吗?

    public ViewRootImpl(Context context, Display display) {
        mContext = context;
        mWindowSession = WindowManagerGlobal.getWindowSession();
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to open window session", e);
                }
            }
            return sWindowSession;
        }
    }

然后在WMS中:


    @Override
    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
            IInputContext inputContext) {
        if (client == null) throw new IllegalArgumentException("null client");
        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
        Session session = new Session(this, callback, client, inputContext);
        return session;
    }

所以上面的mWindowSession是个代理类代理的是WMS创建出来的Session

    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags,
            int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
            Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Configuration
                    outConfig,
            Surface outSurface) {
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags,
                outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                outStableInsets, outsets, outConfig, outSurface);
        return res;
    }

    public int relayoutWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int requestedWidth,
            int requestedHeight, int viewVisibility, int flags,
            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
            Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig,
            Surface outSurface) {
            WindowState win = windowForClientLocked(session, client, false);

                    SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
                    if (surfaceControl != null) {
                        outSurface.copyFrom(surfaceControl);
                    } else {
                        outSurface.release();

}

我们看到了SurfaceControl这个对象,最后的结果是我们传递进来的Surface outSurface有创建出来的SurfaceControl对象。

也就是说,我们当初在ViewRoot中创建的outSurface传入WMS,现在在这个方法中,我想到这里,就要验证一下,是不是Surface能通过Binder传递

public class Surface implements Parcelable {

哎呦握操可以啊小伙子。

我们ViewRootImpl中的Surface现在持有WMS中创建的SurfaceControl,这是干什么,要想知道干什么就必须要知道SurfaceControl干什么。

public class SurfaceControl {
    private static native long nativeCreate(SurfaceSession session, String name,
            int w, int h, int format, int flags)
            throws OutOfResourcesException;
    private static native void nativeRelease(long nativeObject);
    private static native void nativeDestroy(long nativeObject);
    long mNativeObject; // package visibility only for Surface.java access

上面几个方法这是要创建什么啊,销毁什么啊这是,销毁一个nativeObject根据名称,我们知道销毁的时mNativeObject,这个根据注释时Surface。

哎呦握操,创建Surface的工作跑到native去了,SurfaceControl持有Surface,哎呦握操。

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    sp<SurfaceControl> surface = client->createSurface(
            String8(name.c_str()), w, h, format, flags);
    if (surface == NULL) {
        jniThrowException(env, OutOfResourcesException, NULL);
        return 0;
    }
    surface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(surface.get());
}

这个不就是我前段时间写的那些东东吗,我当时是在C++层创建Surface看看他们之间的关系,现在好了,全跑到C++层了。

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags)
{
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}

到了这里,我们知道,原来ViewRoot中使用的就是我们通过WMS

WindowState win = windowForClientLocked(session, client, false);
WindowStateAnimator winAnimator = win.mWinAnimator;
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();

我们看到了吗?

    final WindowState windowForClientLocked(Session session, IBinder client,
            boolean throwOnError) {
        WindowState win = mWindowMap.get(client);
       
        if (win == null) {
            RuntimeException ex = new IllegalArgumentException(
                    "Requested window " + client + " does not exist");
            if (throwOnError) {
                throw ex;
            }
            Slog.w(TAG, "Failed looking up window", ex);
            return null;
        }
        return win;
    }
    final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();

那我们在哪里put呢?

    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
            WindowState win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
              win.attach();
              mWindowMap.put(client.asBinder(), win);
}

我们在WindowManagerService.addWindow中,构造中mWinAnimator=null
那到底这个在哪里赋值呢?
我们只能寄希望与attach()方法

void attach() {  
    if (WindowManagerService.localLOGV) Slog.v(  
        TAG, "Attaching " + this + " token=" + mToken  
        + ", list=" + mToken.windows);  
    mSession.windowAddedLocked();  
}  

在Session的windowAddedLocked函数中创建了SurfaceSession对象。

    void windowAddedLocked() {
        if (mSurfaceSession == null) {
            if (WindowManagerService.localLOGV) Slog.v(
                WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
            mSurfaceSession = new SurfaceSession();
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                    WindowManagerService.TAG, "  NEW SURFACE SESSION " + mSurfaceSession);
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }

SurfaceSession对象的构造函数就调用了nativeCreate函数,返回值保存在mNativeClient中了。

public SurfaceSession() {  
    mNativeClient = nativeCreate();  
} 
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}

然后

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

这里都是之前讲过的

我们成功将战场转移到了native层,也就是说,ViewRoot已经和native的Surface沟通好了。哈哈,这些从Activity到WMS,到native Surface有了一个大概印象了。
我们明天继续细化这个过程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容