안드로이드 그래픽스 프레임워크 학습 2 (tistory.com)
위의 분석에서 SurfaceFlinger의 createLayer를 통해 SurfaceFlinger에 layer가 추가 되는 과정을 알아 봤었습니다
이번에는 그럼, createLayer를 해주는 부분이 어디인지를 한 번 알아보는 것이 핵심입니다
먼저, createLayer 시작점을 보기 전에 WindowManager라는 개념을 먼저 알아야 합니다
native 단의(여기서 native는 c, c++) SurfaceFlinger는 layer 단위로 관리를 하고 있고
java 단의 WindowManager는 window 단위로 관리를 합니다
둘 사이는 SurfaceControl.Transaction 이라는 것을 통해 통신을 하고, 그 Transaction을 가지고 있는 것은 DisplayContent입니다
안드로이드에서는 display별로 DisplayContent를 가지게 되고, 그 displayContent는 RootWindowContainer의 child들로 관리가 됩니다
// 1. WindowManagerService의 RootWindowContainer
// The root of the device window hierarchy.
RootWindowContainer mRoot;
// 2. RootWindowContainer 상속 관계
class RootWindowContainer extends WindowContainer<DisplayContent>
// 3. RootWindowContainer::SetWindowManager
void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
...
final Display[] displays = mDisplayManager.getDisplays();
for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
final Display display = displays[displayNdx];
final DisplayContent displayContent = new DisplayContent(display, this);
addChild(displayContent, POSITION_BOTTOM); // addChild
if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
mDefaultDisplay = displayContent;
}
}
// 4. WindowContainer::addChild
/** Adds the input window container has a child of this container at the input index. */
@CallSuper
void addChild(E child, int index) {
if (!child.mReparenting && child.getParent() != null) {
throw new IllegalArgumentException("addChild: container=" + child.getName()
+ " is already a child of container=" + child.getParent().getName()
+ " can't add to container=" + getName()
+ "\n callers=" + Debug.getCallers(15, "\n"));
}
if ((index < 0 && index != POSITION_BOTTOM)
|| (index > mChildren.size() && index != POSITION_TOP)) {
throw new IllegalArgumentException("addChild: invalid position=" + index
+ ", children number=" + mChildren.size());
}
if (index == POSITION_TOP) {
index = mChildren.size();
} else if (index == POSITION_BOTTOM) {
index = 0;
}
mChildren.add(index, child);
// Set the parent after we've actually added a child in case a subclass depends on this.
child.setParent(this);
}
2번을 보시면 RootWindowContainer는 WindowContainer를 상속받는데 제네릭으로 DisplayContent 형식을 받는 것을 볼 수 있습니다
3번을 보시면 setWindowManager 호출 시에, addChild를 호출 해주는 것을 볼 수있고
4번을 보시면 addChild의 구현부분 입니다
처음 궁금했던, createLayer가 불리기까지의 sequence는 아래와 같습니다
위에서, SurfaceFlinger <-> WindowManager 간의 통신은 Transaction을 통해서 이루어 진다고 얘기를 했는데, 그 부분에 대해서 좀 알아보려고 합니다
// 1. RootWindowContainer::performSurfacePlacementNoTrace
void performSurfacePlacementNoTrace() {
...
mWmService.openSurfaceTransaction();
try {
applySurfaceChangesTransaction();
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
...
}
// 2. WindowManagerService::opensurfaceTranaction, closeSurfaceTransaction
void openSurfaceTransaction() {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
SurfaceControl.openTransaction();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
/**
* Closes a surface transaction.
* @param where debug string indicating where the transaction originated
*/
void closeSurfaceTransaction(String where) {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
SurfaceControl.closeTransaction();
mWindowTracing.logState(where);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
// 3. SurfaceComposerClient::Transaction::merge
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
for (auto const& [handle, composerState] : other.mComposerStates) {
if (mComposerStates.count(handle) == 0) {
mComposerStates[handle] = composerState;
} else {
mComposerStates[handle].state.merge(composerState.state);
}
}
for (auto const& state : other.mDisplayStates) {
ssize_t index = mDisplayStates.indexOf(state);
if (index < 0) {
mDisplayStates.add(state);
} else {
mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
}
}
// 4. SurfaceComposerClient::Transaction::apply
status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
...
Vector<ComposerState> composerStates;
Vector<DisplayState> displayStates;
...
for (auto const& kv : mComposerStates){
composerStates.add(kv.second);
}
...
sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
{} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
hasListenerCallbacks, listenerCallbacks, mId);
1번을 보시면 performSurfacePlacement 함수 내부의 performSurfacePlacementNoTrace 부분에 대한 설명입니다
performSurfacePlacement는 activity 전환 등 많은 경우에 불릴 수 있습니다
2번은 openSurfaceTransaction, closeSurfaceTransaction 부분의 코드 입니다
3번과 4번은 각각 openSurfaceTransaction, closeSurfaceTransaction시의 주요 사항 부분에 대한 코드 입니다
openSurfaceTransaction 일 때, SurfaceComposerClient::Transaction::merge가 불려서 mComposerStates와 mDisplayStates를 업데이트 시켜주고,
closeSurfaceTransaction이 불릴 때 SurfaceComposerClient::Transaction::apply가 불려서 SurfaceFlinger의 setTransactionState가 불리어 TransactionState를 넘겨줍니다
그 이후 SurfaceFlinger에서 queueTransaction를 통해 transaction을 저장했던 것을 flushTransactionQueues 시점에 업데이트 해줍니다 자세한 사항은 지난 번에 썼던 아래 부분과 연계가 되니 궁금하신 분은 확인 부탁드리겠습니다
안드로이드 그래픽스 프레임워크 학습 2 (tistory.com)
이렇게 해서 SurfaceFlinger <-> WindowManger간의 통신은 어떻게 이루어 지는지, SurfaceFlinger의 createLayer는 누가 해주는 지를 분석해보았습니다
다음 번엔 WindowManager에 대해서 좀 더 자세하게 분석 해보도록 하겠습니다
감사합니다
'안드로이드 > 안드로이드 프레임워크' 카테고리의 다른 글
안드로이드 앱 프레임워크 학습(WindowManager) 3 (0) | 2024.03.01 |
---|---|
안드로이드 앱 프레임워크 학습(WindowManager) 2 (0) | 2024.02.29 |
안드로이드 미디어 프레임워크(SurfaceFlinger) 학습 3 (0) | 2024.02.27 |
안드로이드 미디어 프레임워크(SurfaceFlinger) 학습 2 (0) | 2024.02.25 |
안드로이드 미디어 프레임워크(SurfaceFlinger) 학습 1 (0) | 2024.02.24 |