이전에 StartActivity 호출 순서를 블로그로 써본적이 있었는데 (자세한 건 아래 참조 부탁드립니다)
Android framework StartActivity 호출 순서 (tistory.com)
안드로이드에서 Activity는 4대 컴포넌트 중 하나입니다
화면에 띄우는 방식이 반드시 Activity를 사용해야만 화면에 띄울 수 있는 것은 아니지만
Activity를 사용하면 Framework 단에서 LifeCycle (Resume, Pause, Stop 등과 같은) 관리가 용이하다는 점이 있습니다
이번에는 그 Activity의 LifeCycle등을 관리 해주는 ActivityManager에 대해서 한 번 알아보려고 합니다
// SystemServer::startBootstrapServices
// Activity manager runs the show.
t.traceBegin("StartActivityManager");
// TODO: Might need to move after migration to WM.
ActivityTaskManagerService atm = mSystemServiceManager.startService(
ActivityTaskManagerService.Lifecycle.class).getService();
mActivityManagerService = ActivityManagerService.Lifecycle.startService(
mSystemServiceManager, atm);
WindowManagerService 처럼 ActivityManagerService도 SystemServer에서 시작이 됩니다
이전 글들에서 WindowManager는 WindowState단위로 관리를 한다고 말씀을 드렸는데 ActivityManager는 ActivityRecord 기준으로 관리를 하게 됩니다 그리고 그 ActivityRecord는 WindowState안에 멤버변수로가지고 있습니다
WindowManager 분석에서는 SurfaceFlinger 부분과의 연결되는 관점 위주로 봤기에 ActivityManager 관련 된 얘기를 안했지만, 사실 Activity가 전환 시 wm 측의 transition 과정이 필요하기 때문에 AM과 WM은 어울려서 동작합니다
예를 들어, 새 activity가 실행 될 때도, multiwindow 상황이 아니라면 하나의 activity 화면을 보여주기 위해, 보이던 앱의 state를 pause -> stop 으로 내려야할 것이고 실행되는 액티비티는 create -> start -> resume으로 바뀌어야할 것입니다
LifeCycle의 변환을 알기 전에 근본적으로 Activity의 전환(transition) 간에 일어나는 상황을 보면
아래와 같습니다
(RootWindowContainer의 openSurfaceTransaction 부분은 WindowManager 분석 때 SurfaceFlinger 관련 연결 부분과 한 번 본적있으니 이전 블로그 글 참고 부탁드립니다)
여기서 좀 봐야할 부분은 AppTransitionController 부분입니다
여기선 RemoteAnimation과 Leash라는 개념이 있는데 Leash는 사전적 의미를 보니 속박 이란 의미로 사용되는 것 같고
RemoteAnimation은 원격 애니메이션이라는 개념일듯 한데, 그걸 생각해보면
SurfaceControl의 layer 전환에 따른 animation => RemoteAnimation
그리고 그 SurfaceControl에 속박된 effectLayer로 사용되는 layer => Leash 로 추정이 됩니다
// SurfaceAnimator::startAnimation
if (mLeash == null) {
mLeash = createAnimationLeash(mAnimatable, surface, t, type,
mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
0 /* y */, hidden, mService.mTransactionFactory);
mAnimatable.onAnimationLeashCreated(t, mLeash);
}
mAnimatable.onLeashAnimationStarting(t, mLeash);
...
mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
여기서 받는 mAnimation은 animationAdapter로 WindowContainer에서의 adapter (RemoteAnimationConroller.RemoteAnimationRecord) 입니다
// SurfaceAnimator::startAnimator
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback,
@Nullable Runnable animationCancelledCallback,
@Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) {
mAnimation = anim;
// WindowContainer::applyanimationUnchecked
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
transit, enter, isVoiceInteraction);
AnimationAdapter adapter = adapters.first;
...
animationRunnerBuilder.build()
.startAnimation(getPendingTransaction(), adapter, !isVisible(),
ANIMATION_TYPE_APP_TRANSITION, thumbnailAdapter);
그 이후 AppTransitionController에서
// AppTransitionController::handleAppTransitionReady
try {
applyAnimations(mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps, transit,
animLp, voiceInteraction);
handleClosingApps();
handleOpeningApps();
handleChangingApps(transit);
appTransition.setLastAppTransition(transit, topOpeningApp,
topClosingApp, topChangingApp);
final int flags = appTransition.getTransitFlags();
layoutRedo = appTransition.goodToGo(transit, topOpeningApp);
handleNonAppWindowsInTransition(transit, flags);
appTransition.postAnimationCallback();
appTransition.clear();
} finally {
mService.mSurfaceAnimationRunner.continueStartingAnimations();
}
mService.mTaskSnapshotController.onTransitionStarting(mDisplayContent);
handleClosingApps 에서는 일단 떠 있는 앱의 Visibility를 내리고
handleOpeningApps에서는 실행시킬 앱의 Visibility를 올리고, 실제로 보여줘야할 Window에 style, animationAttr이 설정되어 있는 경우 WindowStateAnimator를 실행시킵니다
// AppTransitionController::handleOpeningApps
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION handleAppTransitionReady()");
mService.openSurfaceTransaction();
try {
app.showAllWindowsLocked();
} finally {
mService.closeSurfaceTransaction("handleAppTransitionReady");
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
"<<< CLOSE TRANSACTION handleAppTransitionReady()");
}
그 이후 appTransition.goodToGo를 실행시키고, 마무리로 displayContent에 pendingLayoutChanges를 업데이트 시킵니다
사실 봐야하는 내용이 Leash 말고도 InsetsController를 통해 (앱 마다 상,하단바 설정에 따라 보여주고 말고를 결정할 수 있어서) 그 부분의 animation도 봐야하는데 내용이 너무 길어져서 일단 여기서 한 번 자르도록 하겠습니다
감사합니다!
'안드로이드 > 안드로이드 프레임워크' 카테고리의 다른 글
안드로이드 앱 프레임워크 학습(ActivityManager) 3 (0) | 2024.03.10 |
---|---|
안드로이드 앱 프레임워크 학습(ActivityManager) 2 (0) | 2024.03.03 |
안드로이드 앱 프레임워크 학습(WindowManager) 3 (0) | 2024.03.01 |
안드로이드 앱 프레임워크 학습(WindowManager) 2 (0) | 2024.02.29 |
안드로이드 앱 프레임워크 학습(WindowManager) 1 (0) | 2024.02.28 |