Android 6.0 WMS (1) WMS 와 응용 프로 세 스 의 관계
1. apptoken 이 WMS 에서 만 듭 니 다.
블 로그http://blog.csdn.net/kc58236582/article/details/52413871에서 APPWindowToken 을 만 드 는 과정 에서 AMS 에서 startActivity Locked 를 호출 할 때 WMS 의 addAppToken 을 호출 하여 APPWindowToken 을 만 드 는 것 을 분 석 했 습 니 다.
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
insertTaskAtTop(rTask, r);
mWindowManager.moveTaskToTop(taskId);
}
TaskRecord task = null;
if (!newTask) {
// If starting in an existing task, find where that is...
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
// All activities in task are finishing.
continue;
}
if (task == r.task) {
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
task.addActivityToTop(r);
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
WMS 의 addAppToken 함 수 를 살 펴 보고 WMS 에서 APPWindowToken 을 만 들 고 mTokenMap 에 저장 합 니 다. public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
......
synchronized(mWindowMap) {
AppWindowToken atoken = findAppWindowToken(token.asBinder());//
if (atoken != null) {
Slog.w(TAG, "Attempted to add existing app token: " + token);
return;
}
atoken = new AppWindowToken(this, token, voiceInteraction);// APPWindowToken
atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
atoken.appFullscreen = fullscreen;
atoken.showForAllUsers = showForAllUsers;
atoken.requestedOrientation = requestedOrientation;
atoken.layoutConfigChanges = (configChanges &
(ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
atoken.mLaunchTaskBehind = launchTaskBehind;
if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
+ " to stack=" + stackId + " task=" + taskId + " at " + addPos);
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
task = createTaskLocked(taskId, stackId, userId, atoken);
}
task.addAppToken(addPos, atoken);
mTokenMap.put(token.asBinder(), atoken);// mTokenMap token key(Activity binder )
// Application tokens start out hidden.
atoken.hidden = true;
atoken.hiddenRequested = true;
}
}
다시 한 번 AppWindowToken 의 구조 함 수 를 살 펴 보 겠 습 니 다. WindowToken 의 하위 클래스 이 고 부모 류 구조 함 수 를 호출 할 때 자신 이 TYPE 라 는 것 을 설명 합 니 다.어 플 리 케 이 션 타 입.매개 변수token 은 Activity Record 대상 의 IBinder 인 터 페 이 스 를 가리 키 기 때문에 AppWindowToken 류 의 구성원 변수 인 appToken 은 Activity Record 대상 을 묘사 합 니 다.
AppWindowToken(WindowManagerService _service, IApplicationToken _token,
boolean _voiceInteraction) {
super(_service, _token.asBinder(),
WindowManager.LayoutParams.TYPE_APPLICATION, true);
appWindowToken = this;
appToken = _token;
voiceInteraction = _voiceInteraction;
mInputApplicationHandle = new InputApplicationHandle(this);
mAnimator = service.mAnimator;
mAppAnimator = new AppWindowAnimator(this);
}
2. Activity 의 attach 함수
일단 블 로그 에서.http://blog.csdn.net/kc58236582/article/details/52397657Activity 생 성 초기 화 를 분석 하 였 습 니 다.
handleLaunchActivity 함 수 는 performLaunchActivity 함 수 를 먼저 호출 한 다음 handleResumeActivity 함 수 를 호출 합 니 다.
permlaunchActivity 함수 에서 Activity 를 새로 만 든 다음 attach 함 수 를 호출 하고 마지막 으로 Activity 의 onCreate 함 수 를 호출 합 니 다.
Activity 의 attach 함수 에서 주요 코드 는 다음 과 같 습 니 다.
......
mWindow = new PhoneWindow(this);// PhoneWindow
mWindow.setCallback(this);// window , 。 , Activity dispatchKeyEvent
mWindow.setOnWindowDismissedCallback(this);
......
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
3. ViewRootImpl, DecorView 만 들 기
우 리 는 계속 분석 하고 있다.http://blog.csdn.net/kc58236582/article/details/52411791블 로그, 우 리 는 ViewRootImpl 과 DecorView 의 창설 을 분석 했다.
보통 Activity 의 onCreate 함수 에서 setContentView 를 호출 합 니 다.set ContentView 에 서 는 DecorView 대상 을 만 듭 니 다.
다음은 Activity Thread 의 handle ResumeActivity 함 수 를 살 펴 보 겠 습 니 다. 먼저 permResumeActivity 함 수 를 호출 하여 이 Activity 를 찾 았 습 니 다. 그 다음 에는 주로 WindowManager 의 addView 함 수 를 호출 했 습 니 다.
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
if (localLOGV) Slog.v(
TAG, "Resume " + r + " started activity: " +
a.mStartedActivity + ", hideForNow: " + r.hideForNow
+ ", finished: " + a.mFinished);
final int forwardBit = isForward ?
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
Window Manager Impl 의 addView 함 수 를 살 펴 보 겠 습 니 다. 사실은 Window Manager Global 의 addView 함 수 를 호출 한 것 입 니 다.
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
이전에 도 Window Manager Global 을 분석 한 적 이 있 는데 세 가지 중요 한 구성원 변수 가 있 습 니 다.
private final ArrayList mViews = new ArrayList();// DecorView
private final ArrayList mRoots = new ArrayList();// ViewRootImpl
private final ArrayList mParams =// View layout
new ArrayList();
Window Manager Global 의 addView 함 수 를 살 펴 보 겠 습 니 다. 이 함 수 는 먼저 Window Manager Global 에 이미 이 view 가 있 는 지 찾 습 니 다. 있 으 면 ViewRootImpl 의 doDie 함수 에서 Window Manager Global 함 수 를 호출 하여 이 ViewRootImpl 대상 을 제거 합 니 다. 이 함 수 는 주로 ViewRootImpl 을 만 들 고 DecorView, RootView RootImpl 을 만 듭 니 다.layot 인자 가 모두 저장 되 었 습 니 다.그리고 ViewRootImpl 의 setView 함 수 를 호출 했 습 니 다.
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
......
int index = findViewLocked(view, false);// view, index
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();// ViewRootImpl doDie
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
......
root = new ViewRootImpl(view.getContext(), display);// ViewRootImpl
view.setLayoutParams(wparams);
mViews.add(view);//
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);// ViewRootImpl setView
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
4. ViewRootImpl 의 setView 함수
위 에 ViewRootImpl 을 만 든 후에 setView 함 수 를 호출 합 니 다. setView 함 수 는 주로 두 부분 으로 나 눌 수 있 습 니 다.
4.1 requestLayout 함수
setView 에서 먼저 requestLayout 함 수 를 호출 합 니 다. 이 함 수 는...http://blog.csdn.net/kc58236582/article/details/52421683블 로그 에 상세 한 분석 이 있 는데 주로 WMS 의 relayoutWindow 함 수 를 호출 한 다음 에 Surface Flinger 를 통 해 Surface 를 만 듭 니 다.
4.2 addToDisplay
다른 부분 은 다음 코드 입 니 다. 최종 적 으로 WMS 의 addWindow 함 수 를 호출 하여 창 을 추가 합 니 다.... 에 있다http://blog.csdn.net/kc58236582/article/details/52413871블 로그 에서 Window State 의 생 성 과정 에 대해 상세 하 게 분석 되 었 습 니 다.
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.