WMS:Surface的管理

Surface的管理

Surface和Window的区别
Surface的管理
Surface的内部实现

1.Surface的申请流程

WMS原则上只负责窗口的层级和属性,而SurfaceFlinger才是真正将窗口数据合成并最终显示到屏幕上的系统服务,由此可见,WMS在对窗口做出调整的同时,也必须通知SurfaceFlinger,这样才能把正确结果及时的呈现。
而UI界面的绘制需要画板也就是BufferQueue的支持,所以无论系统窗口还是应用窗口,都必须向SurfaceFlinger申请Layer,进而得到图形缓冲区的使用权。这个操作的起点在ViewRoot中;当ViewRoot执行performTraversals的时候,会向WMS申请一个Surface。

1.1 performTraversals

private void performTraversals() {
   //...
   int relayoutResult = 0;
   relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
   //...
}

1.2 relayoutWindow

private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, 
        boolean insetsPending) throws RemoteException {

   
    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,
            mPendingConfiguration, mSurface);//注意这里的mSurface
  
   return relayoutResult;
}

大致的流程是当ViewRoot执行performTraversals的时候,如果发现时第一次执行这个函数,那么它会调用relayoutWidow,该函数会通过IWindowSession.relayout来让WMS向SurfaceFlinger申请画板,然后通过mSurface变量将结果返回。(ViewRoot中new Surface只是一个空壳,内部没有承载UI数据的画板,所以直接用它来绘图时无效的只有经过relayout重新赋值只会,它才有意义)

1.3 IWindowSession.aidl的relayout声明:Binder调用过程

    int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility,
            int flags, out Rect outFrame, out Rect outOverscanInsets,
            out Rect outContentInsets, out Rect outVisibleInsets,
            out Configuration outConfig, out Surface outSurface);

Surface之前有out,说明在生成代码的时候会考虑应用端的proxy和服务端的Stub的parceable

Stub###

android.view.Surface _arg11;
_arg11 =  new android.view.Surface();//创建一个Surface对象
//调用wms进行relayout处理
int _result = this.relayout(arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
...
if(_arg11!=null){
    reply.writeInt(1);//写一个状态值
}
_arg11.writeToParcel(reply,android.os.Parcelable.PARCEABLE_WRITE_RETURN_VALUE);

Proxy###

public int relayout(...,android.view.Surface outSurface){
    android.os.Parcel reply = android.os.Parcel.obtain();
    mRemote.transact(Stub.TRASACTION_relayout,_data,_reply,0);
    if(0!=_reply.readInt()){
        outSurface.readFromParcel(_reply);
    }
}
 

1.4 Session的relayout方法

    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, Configuration outConfig, Surface outSurface) {
       
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags,
                outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                outConfig, outSurface);
      
        return res;
    } 

1.5 relayoutWindow

//viewVisibility窗口可见性请求
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, Configuration outConfig, Surface outSurface) {
    boolean toBeDisplayed = false;//次窗口是否需要显示,是由多个因素决定
    boolean inTouchMode;
    boolean configChanged;//配置是否发生变化
    boolean surfaceChanged = false;//Surface是否发生变化
    

    synchronized(mWindowMap) {
        //查找窗口对应的WindowState(窗口添加过程中被加进来的,这个时候是查询)
        WindowState win = windowForClientLocked(session, client, false);
        //winAnimator
        WindowStateAnimator winAnimator = win.mWinAnimator;
        if (win.mRequestedWidth != requestedWidth
                || win.mRequestedHeight != requestedHeight) {
            //尺寸发生变化,需要relayout
            win.mLayoutNeeded = true;
            win.mRequestedWidth = requestedWidth;
            win.mRequestedHeight = requestedHeight;
        } 
        
        if (viewVisibility == View.VISIBLE &&
                (win.mAppToken == null || !win.mAppToken.clientHidden)) {

            toBeDisplayed = !win.isVisibleLw();//加入已经是可见状态,不要再显示
     
            if (toBeDisplayed) {//需要显示的情况
                if (win.isDrawnLw() && okToDisplay()) {
                    winAnimator.applyEnterAnimationLocked();
                }
                //......
            }
           
            try {
                if (!win.mHasSurface) {
                    surfaceChanged = true;
                }
                //SurfaceControl
                SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
                if (surfaceControl != null) {//生成Surface
                    outSurface.copyFrom(surfaceControl); 
                } else {
                    //生成Surface失败
                    outSurface.release();
                }
            } catch (Exception e) {
                
            }
            
        } else {
             //viewVisibility不是VISIBLE的情况
        }

        //....
        performLayoutAndPlaceSurfacesLocked();
        //...
}

1.判断这个窗口是否需要显示,最终的判断结果由toBeDisplayed表示
2.如果是要显示的窗口就需要有合法的Surface,所以如果这个窗口之前没有Surface或者Surface的配置发生了变化,就需要重新申请。最终的判断结果由surfaceChanged表示
3.还要判断配置是否变更configChanged
4.如果当前正在进行动画,情况会稍有不同
5.requestWidth和requestHeight表示用户请求的宽高,这会影响到申请的Surface的属性,

1.6 createSurfaceLocked

SurfaceControl createSurfaceLocked() {
    if (mSurfaceControl == null) { 
        mDrawState = DRAW_PENDING; 
        mService.makeWindowFreezingScreenIfNeededLocked(mWin);

        int flags = SurfaceControl.HIDDEN;
        final WindowManager.LayoutParams attrs = mWin.mAttrs;

        int w = mWin.mCompatFrame.width();
        int h = mWin.mCompatFrame.height();
 
        try {
             
            if (DEBUG_SURFACE_TRACE) {
                
            } else {
                mSurfaceControl = new SurfaceControl(
                    mSession.mSurfaceSession,
                    attrs.getTitle().toString(),
                    w, h, format, flags);
            }
            mWin.mHasSurface = true;//更改状态 
        } catch (OutOfResourcesException e) {
            //如发生异常改变状态,NO_SURFACE以及mWin.mHasSurface = false
            mWin.mHasSurface = false; 
            mDrawState = NO_SURFACE;
            return null;
        } catch (Exception e) {
            mWin.mHasSurface = false; 
            mDrawState = NO_SURFACE;
            return null;
        }

        
        SurfaceControl.openTransaction();
        try {
            try {
                //openTransaction和endTransaction之间是对Surface的操作
                 
                mSurfaceX = mWin.mFrame.left + mWin.mXOffset;
                mSurfaceY = mWin.mFrame.top + mWin.mYOffset;
                //设置位置
                mSurfaceControl.setPosition(mSurfaceX, mSurfaceY);
                mSurfaceLayer = mAnimLayer;
                mSurfaceControl.setLayerStack(mLayerStack);
                mSurfaceControl.setLayer(mAnimLayer);
                mSurfaceControl.setAlpha(0);
                mSurfaceShown = false;
            } catch (RuntimeException e) { 
                mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
            }
            mLastHidden = true;
        } finally {
            SurfaceControl.closeTransaction();
             
        }
         
    }
    return mSurfaceControl;
} 

到此为止,通过一系列调用,生成了SurfaceControl对象

openTransaction和closeTransaction之间的操作如setSize,setLayer,setPosition等都不是及时生效的,而是要等到业务关闭之后才统一通知SurfaceFlinger,对于频繁变更属性的地方,这样做一方面可以提高效率,另一方面可以避免属性过快带来的画面不稳定###

1.7 performLayoutAndPlaceSurfacesLocked

private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
    SurfaceControl.openTransaction();
    try {

        if (mWatermark != null) {
            mWatermark.positionSurface(defaultDw, defaultDh);
        }
        if (mStrictModeFlash != null) {
            mStrictModeFlash.positionSurface(defaultDw, defaultDh);
        }

        boolean focusDisplayed = false;

        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 
            int repeats = 0;
            do {
                repeats++;
                if (repeats > 6) { 
                    displayContent.layoutNeeded = false;
                    break;
                }

                // FIRST LOOP: Perform a layout, if needed.
                if (repeats < 4) {//如果需要的话,计算窗口大小
                    performLayoutLockedInner(displayContent, repeats == 1,
                            false /*updateInputWindows*/);
                } else { 

                }


                if (isDefaultDisplay) {
                    mPolicy.beginPostLayoutPolicyLw(dw, dh);
                    for (i = windows.size() - 1; i >= 0; i--) {
                        WindowState w = windows.get(i);
                        if (w.mHasSurface) {//把Policy运用到各个窗口
                            mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
                        }
                    }
                    displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 
                }
            } while (displayContent.pendingLayoutChanges != 0);

            //动画相关
            //执行应用间切换
            //销毁所有不再可见的窗口
            //是否需要移除已经退出的token
            //是否需要移除退出的应用程序 

}
 

2.Surface的跨进程传递

Surface(java)会在两个地方被创建,一个是ViewRootImpl,一个是WindowStateAnimator

  • ViewRootImpl中:对应的是它的成员变量mSurface,而且在一开始就分配了一个空的Surface对象
  • WindowStateAnimator中,当WMS调用WindowStateAnimator的createSurfaceLocked方法时,将生成一个真正有效的Surface对象,且由其成员变量mSurfaceControl管理。

2.1 Surface的三个构造函数

public Surface();//ViewRootImpl中mSurface的初始化采用的是这种
public Surface(SurfaceTexture surfaceTexture);
public Surface(int nativeObject); //Surface与SurfaceFlinger建立联系的入口,

WindowStateAnimator通过SurfaceControl来间接生成Surface

 mSurfaceControl = new SurfaceControl(
                     mSession.mSurfaceSession,
                     attrs.getTitle().toString(),
                        w, h, format, flags);

2.2 SurfaceControl的构造方法

public SurfaceControl(SurfaceSession session,
        String name, int w, int h, int format, int flags)
                throws OutOfResourcesException { 
    mName = name;
    //nativeCreate方法
    mNativeObject = nativeCreate(session, name, w, h, format, flags);
    mCloseGuard.open("release");
} 

nativeCreate###

 private static native int nativeCreate(SurfaceSession session, String name,
            int w, int h, int format, int flags) 

android_view_SurfaceControl.cpp 的nativeCreate###

static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    
    sp client(android_view_SurfaceSession_getClient(env, sessionObj));
    sp 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 int(surface.get());
}

通过SurfaceComposerClient的createSurface方法创建SurfaceControl,SurfaceComposerClient是SurfaceFlinger派出的代表

android_view_SurfaceSession_getClient(env, sessionObj)###

用android_view_SurfaceSession_getClient可以获取SurfaceComposerClient对象,说明在其他地方创建了这个对象,并通过jni将其保存到了java层,具体过程是addWindow被调用时,WMS会为窗口创建一个WindowState,并将Session保存到它的成员变量mSession中,紧接着WindowState.attach被调用,此时mSession通过windowAddedLocked进一步生成mSurfaceSession;当WindowState构造时,它同时内部生成mWindowAnimator,mWindowAnimator构造的时候也将Session对象保存在mSession成员变量中,这个变量将在createSurfaceLocked中传递给Surface的构造函数。

2.2 Surface.jva copyFrom

public void copyFrom(SurfaceControl other) { 
    int surfaceControlPtr = other.mNativeObject; 
    int newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr); 
    synchronized (mLock) {
        if (mNativeObject != 0) {
            nativeRelease(mNativeObject);
        }
        setNativeObjectLocked(newNativeObject);
    }
}



static jint nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
        jint surfaceControlNativeObj) {
  
    sp ctrl(reinterpret_cast(surfaceControlNativeObj));
    sp surface(ctrl->getSurface());
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast(surface.get());
}

2.3 nativeReadFromParcel

static jint nativeReadFromParcel(JNIEnv* env, jclass clazz,
        jint nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    
    sp self(reinterpret_cast(nativeObject));
    sp binder(parcel->readStrongBinder());
 

    sp sur;
    sp gbp(interface_cast(binder));
    if (gbp != NULL) { 
        sur = new Surface(gbp, true); 
        sur->incStrong(&sRefBaseOwner);
    }

    if (self != NULL) { 
        self->decStrong(&sRefBaseOwner);
    } 
    return int(sur.get());
}  

这样客户端的Surface 和 IGraphicBufferProducer就成功建立了联系,而后者就是Buffer的管理者,所以后续在此Surface基础上的UI操作最终可以通过SurfaceFlinger显示到屏幕上

你可能感兴趣的:(WMS:Surface的管理)