안드로이드/안드로이드 프레임워크

안드로이드 앱 프레임워크 학습(WindowManager) 3

냥냥냥냥냥냥 2024. 3. 1. 01:25

안드로이드 앱 프레임워크 학습(WindowManager) 2 (tistory.com)

 

안드로이드 앱 프레임워크 학습(WindowManager) 2

안드로이드 앱 프레임워크 학습(WindowManager) 1 (tistory.com) 안드로이드 앱 프레임워크 학습(WindowManager) 1 안드로이드 그래픽스 프레임워크 학습 2 (tistory.com) 안드로이드 그래픽스 프레임워크 학습 2

nyaang.tistory.com

지난 번에 이어 이번엔 relayoutWindow 과정에 대해 알아보도록 하겠습니다

 

relayout

사실 WindowSurfacePlacer 이후 부분의 코드는 이미 한 번 봤던 코드라..

 

여기서 중점으로 봐야할 것은 아래 코드 부분입니다

SurfaceControl


// ViewRootImpl::relayoutWindow
int relayoutResult = mWindowSession.relayout(mWindow, params,
        (int) (mView.getMeasuredWidth() * appScale + 0.5f),
        (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
        insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
        mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, // mSurfaceControl
        mTempControls, mSurfaceSize);
        
        
...

        if (mSurfaceControl.isValid()) {
            if (!useBLAST()) {
                mSurface.copyFrom(mSurfaceControl);
            } else {
                final Surface blastSurface = getOrCreateBLASTSurface();
                // If blastSurface == null that means it hasn't changed since the last time we
                // called. In this situation, avoid calling transferFrom as we would then
                // inc the generation ID and cause EGL resources to be recreated.
                if (blastSurface != null) {
                    mSurface.transferFrom(blastSurface);
                }
            }
            if (mAttachInfo.mThreadedRenderer != null) {
                if (HardwareRenderer.isWebViewOverlaysEnabled()) {
                    addPrepareSurfaceControlForWebviewCallback();
                    addASurfaceTransactionCallback();
                }
                mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
            }

mSurfaceControl을 넘겨줘서 결국 WindowSurfaceController의 mSurfaceControl을 복사 받습니다

// WindowSurfaceController
void getSurfaceControl(SurfaceControl outSurfaceControl) {
    outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl");
}

그 이후 valid한지 체크 한 후 useBlast라면 (현재 true로 설정 아래 참고)

HardwareRenderer에 surfaceControl을 set 해줍니다

// ViewRootImpl
boolean useBLAST() {
    return mUseBLASTAdapter && !mForceDisableBLAST;
}

// ViewRootImpl::setView
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
...
                if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) {
                    mUseBLASTAdapter = true;
                }



// WindowManagerService
        mUseBLAST = Settings.Global.getInt(resolver,
            Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) == 1;

// WindowManagerService::addWindow
    public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsVisibilities requestedVisibilities,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
            
        ...
        
            if (mUseBLAST) {
                res |= WindowManagerGlobal.ADD_FLAG_USE_BLAST;
            }

WindowManagerService에서 addWindow 시점에 ADD_FLAG_USE_BLAST set 해주고,

ViewRootImpl 의 setView 시점에 해당 flag 있으면 true

 

정리하자면, 

// WindowManager

1) WindowManager에 addView를 하면 WindowManagerGlobal에서 addView할 때 넘겨준 View와, 그 View의 ViewRootImpl을 생성해서 저장한다

2) relayout 시점에 ViewRootImpl이 가지고 있던 surfaceControl에 WindowSurfaceController가 가지고 있는 surfaceControl의 값을 복사해준다

3) 그 이후 LayoutPolicy 적용 (statusbar, navigationbar 등의 inset 처리 등등)

4) 적용한 사항을 WindowContainer의 getPendingTransaction을 통해서 merge 시킨후 apply(closeSurfaceTransaction)

 

----------------------------------- WindowManager <-> SurfaceFlinger 경계점

 

// SurfaceFlinger

5) 그러면 SurfaceComposerClient::Transaction::apply에서 surfaceFlinger로 setTransactionState

6) SurfaceFlinger의 queueTransaction 호출 후 mTransactionQueue에 저장

7) SurfaceFlinger의 flushTransactionQueues 호출 시점에 applyTransactionState

8) output present 호출 시점에 관련된 transaction 정보들 composer로 전달 하고 compose

 

사실 WindowManager는 window 관점 뿐만 아니라 activity의 state 변환에 따른 처리가 매우 많은데

이 다음부터는 ActivityManager 관련 된 부분을 정리를 진행해보려고 합니다

 

감사합니다!