一、WMS服務初始化過程
- SystemServer中創建WMS
frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
... ...
WindowManagerService wm = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
... ...
wm.displayReady();
... ...
wm.systemReady();
}
- WindowManagerService.main
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
//WMS 運行在"android.display"線程
//DisplayThread 從Android 5.0開始,所有跟系統前景相關的操作都集中到這個線程類中。這個線程只能由WindowManager,DisplayManager和InputManager用來實時顯示相關的快速操作。
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy), 0);
return sInstance;
}
frameworks/base/core/java/android/os/Handler.java
/**
* One example of where you might want to use this method is when you just
* set up a Handler thread and need to perform some initialization steps on
* it before continuing execution.
*/
public final boolean runWithScissors(final Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
//如果當前線程和handler所在線程是同一線程,直接執行run
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
//否者把這個runnable 放在handler 所在線程執行,當前線程等待直到這個runnable 執行完后被喚醒
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
private static final class BlockingRunnable implements Runnable {
@Override
public void run() {
try {
mTask.run();
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
if (!handler.post(this)) {
return false;
}
synchronized (this) {
if (timeout > 0) {
... ...
} else {
while (!mDone) {
try {
wait();
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
- WindowManagerService 構造函數
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
... ...
初始化PhoneWindowManager
initPolicy();
}
private void initPolicy() {
//運行在android.ui 線程
UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
//mPolicy為PhoneWindowManager
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
}
}, 0);
}
這里跟前面一樣使用Handler.runWithScissors, 由于WindowManagerService是在"android.display"線程中運行, 而mPolicy.init
在"android.ui"線程中運行,"android.display"線程等待mPolicy.init執行完再被喚醒。
- wm.displayReady
public void displayReady() {
for (Display display : mDisplays) {
displayReady(display.getDisplayId());
}
synchronized(mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
if (mMaxUiWidth > 0) {
displayContent.setMaxUiWidth(mMaxUiWidth);
}
readForcedDisplayPropertiesLocked(displayContent);
mDisplayReady = true;
}
try {
mActivityManager.updateConfiguration(null);
} catch (RemoteException e) {
}
synchronized(mWindowMap) {
mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TOUCHSCREEN);
configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
}
try {
mActivityManager.updateConfiguration(null);
} catch (RemoteException e) {
}
updateCircularDisplayMaskIfNeeded();
}
- wm.systemReady
public void systemReady() {
mPolicy.systemReady();
//TaskSnapshotController android O 新增, 當app token不可見時對當前task截圖并放在緩存中,系統應用可以得到代表當前task狀態的截圖,并在他們自己的進程中繪制
//當這個task可見后,顯示starting window 時用這個截圖的內容,可以使應用轉換更加敏捷
mTaskSnapshotController.systemReady();
}
WMS初始化過程涉及進程關系如下:
(圖片來源^^: http://gityuan.com/2017/01/08/windowmanger/)
二、關于Token
AMS中的Token是Binder對象,用于跨進程標識同一個Activity對象。WMS中的WindowToken用來標識與一個Activity對應的所有窗口。
1. Token 定義和創建
/frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
static class Token extends IApplicationToken.Stub {
private final WeakReference<ActivityRecord> weakActivity;
Token(ActivityRecord activity) {
weakActivity = new WeakReference<>(activity);
}
//獲取ActivityRecord 對象
private static ActivityRecord tokenToActivityRecordLocked(Token token) {
if (token == null) {
return null;
}
ActivityRecord r = token.weakActivity.get();
if (r == null || r.getStack() == null) {
return null;
}
return r;
}
}
... ...
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,...{
... ...
appToken = new Token(this, service);
}
2. Token對象傳遞
- (1)在啟動一個Activity時會調用 ActivityStack 的startActivityLocked,在這里面調用 addAppToken 將AMS的Token 對象傳遞給WMS,然后WMS 根據這個Token對象創建 AppWindowToken。
- (2)接下來ASS調用scheduleLaunchActivity將token傳給應用端的ActivityThread,此時應用端得到token的代理對象。
- (3)Activity Resume過程中,添加視圖時ViewRootImpl.setView會調用WMS.addWindow將應用端的token代理對象傳給WMS,此時WMS得到token的Binder對象。
/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
ActivityOptions options) {
... ...
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) {
task.addActivityToTop(r);
r.putInHistory();
addConfigOverride(r, task);
... ...
}
}
}
void addConfigOverride(ActivityRecord r, TaskRecord task) {
final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
// TODO: VI deal with activity
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
task.voiceSession != null, r.mLaunchTaskBehind, bounds, task.mOverrideConfig,
task.mResizeMode, r.isAlwaysFocusable(), task.isHomeTask(),
r.appInfo.targetSdkVersion, r.mRotationAnimationHint);
r.taskConfigOverride = task.mOverrideConfig;
}
- AMS跨Binder調用應用進程的scheduleLaunchActivity()將Token傳遞給上層應用進程,這時候應用端得到的是Token 代理對象。
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
... ...
//app.thread 是 IApplicationThread 對象,服務端為應用進程中的ApplicationThread
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
... ...
}
- 應用端添加窗口調用的ViewRootImpl的setView,跨進程將token對象再傳給WMS服務,這時候應用端傳的是Token 代理對象,
WMS服務端得到的卻是Token對象,這樣就跟之前AMS addAppToken時傳過來的Token是同一個對象了。
/frameworks/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
... ...
//mWindowSession IWindowSession對象,服務端是WMS中的 Session,在addToDisplay調用WMS的addWindow
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
... ...
}
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
... ...
WindowToken token = mTokenMap.get(attrs.token);
... ...
}
三、StartingWindow
- 點擊應用圖標時,啟動應用Activity之前,WMS會先啟動一個窗口StartingWindow用于過度。
- StartingWindow啟動流程
- StartingWindow關閉流程
四、Activity窗口創建流程
- 啟動一個Activity時調用startActivityLocked
/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
ActivityOptions 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)) {
insertTaskAtTop(rTask, r);
//(1)將要打開Activity所在的task移到頂部
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) {
... ...
if (task == r.task) {
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
task.addActivityToTop(r);
r.putInHistory();
//(2)在這里調用addAppToken 創建AppWindowToken對象
addConfigOverride(r, task);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
... ...
if (!isHomeStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
boolean showStartingIcon = newTask;
ProcessRecord proc = r.app;
if (proc == null) {
proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
}
if (proc == null || proc.thread == null) {
showStartingIcon = true;
}
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: starting " + r);
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
//(3)設置Activity切換動畫類型,發送一個APP_TRANSITION_TIMEOUT的5s超時消息。
mWindowManager.prepareAppTransition(newTask
? r.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
: TRANSIT_TASK_OPEN
: TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
addConfigOverride(r, task);
... ...
if (r.mLaunchTaskBehind) {
//(4)設置Activity可見性,什么情況下mLaunchTaskBehind???
mWindowManager.setAppVisibility(r.appToken, true);
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
} else if (SHOW_APP_STARTING_PREVIEW && doShow) {
ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
... ...
//(5)顯示StartingWindow
r.showStartingWindow(prev, showStartingIcon);
}
}
... ...
}
- 下面依次介紹WMS 中的(1)~(5)
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
(1) moveTaskToTop
public void moveTaskToTop(int taskId) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized(mWindowMap) {
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
// Normal behavior, addAppToken will be called next and task will be created.
return;
}
final TaskStack stack = task.mStack;
final DisplayContent displayContent = task.getDisplayContent();
//將該task所屬的棧 移至display的頂部
displayContent.moveStack(stack, true);
if (displayContent.isDefaultDisplay) {
final TaskStack homeStack = displayContent.getHomeStack();
if (homeStack != stack) {
// 將home移到display的底部
displayContent.moveStack(homeStack, false);
}
}
//將task移到棧頂
stack.moveTaskToTop(task);
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(false);
}
//更新窗口布局
moveStackWindowsLocked(displayContent);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
(2) addAppToken
@Override
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,
Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable,
boolean homeTask, int targetSdkVersion, int rotationAnimationHint) {
... ...
synchronized(mWindowMap) {
AppWindowToken atoken = findAppWindowToken(token.asBinder());
if (atoken != null) {
Slog.w(TAG_WM, "Attempted to add existing app token: " + token);
return;
}
//創建AppWindowToken
atoken = new AppWindowToken(this, token, voiceInteraction);
atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
atoken.appFullscreen = fullscreen;
atoken.showForAllUsers = showForAllUsers;
atoken.targetSdk = targetSdkVersion;
atoken.requestedOrientation = requestedOrientation;
atoken.layoutConfigChanges = (configChanges &
(ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
atoken.mLaunchTaskBehind = launchTaskBehind;
atoken.mAlwaysFocusable = alwaysFocusable;
if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
+ " to stack=" + stackId + " task=" + taskId + " at " + addPos);
atoken.mRotationAnimationHint = rotationAnimationHint;
//找到或者創建所在task
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config);
}
task.addAppToken(addPos, atoken, taskResizeMode, homeTask);
//將AppWindowToken對象添加到mTokenMap中
mTokenMap.put(token.asBinder(), atoken);
// Application tokens start out hidden.
atoken.hidden = true;
atoken.hiddenRequested = true;
}
}
(3) prepareAppTransition 設置Activity動畫的類型和超時處理,真正執行動畫要在Activity Resumed狀態時,WMS 的executeAppTransition中。
boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent) {
if (!isTransitionSet() || mNextAppTransition == TRANSIT_NONE) {
// Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0 時設為TRANSIT_NONE
setAppTransition(transit);
} else if (!alwaysKeepCurrent) {
if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) {
// newTask時將mNextAppTransition設為TRANSIT_TASK_OPEN
setAppTransition(transit);
} else if (transit == TRANSIT_ACTIVITY_OPEN
&& isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) {
// 將mNextAppTransition設為TRANSIT_ACTIVITY_OPEN
setAppTransition(transit);
}
}
boolean prepared = prepare();
if (isTransitionSet()) {
//5秒后被執行,是用來強制前面所設置的Activity組件切換動畫要在5秒之內執行完成的,否則的話,WindowManagerService服務就會認為該切換動畫執行超時了。
mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
mService.mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, APP_TRANSITION_TIMEOUT_MS);
}
return prepared;
}
(4)后面再說 ,(5)StartingWindow流程圖見第三部分
startActivityLocked 主要完成了以下工作:
(1).將activity所在task移到頂部
(2).創建WindowToken并加到 WindowToken列表中
(3).設置activity切換動畫的相關參數
(4).開啟startingWindow
- Activity 進入onCreate和onResume階段會調用到 ActivityStack.resumeTopActivityInnerLocked
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
... ...
//如果目標進程已存在onResume,否則onCreate
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
+ " stopped=" + next.stopped + " visible=" + next.visible);
// If the previous activity is translucent, force a visibility update of
// the next activity, so that it's added to WM's opening app list, and
// transition animation can be set up properly.
// For example, pressing Home button with a translucent activity in focus.
// Launcher is already visible in this case. If we don't add it to opening
// apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
// TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
final boolean lastActivityTranslucent = lastStack != null
&& (!lastStack.mFullscreen
|| (lastStack.mLastPausedActivity != null
&& !lastStack.mLastPausedActivity.fullscreen));
//如果目標activity不可見之前的activity是半透明的, 那么使窗口可見
if (!next.visible || next.stopped || lastActivityTranslucent) {
mWindowManager.setAppVisibility(next.appToken, true);
}
... ...
try {
... ...
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
mWindowManager.notifyAppResumed(next.appToken, next.stopped, allowSavedSurface);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.task.taskId, next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
//activity進入onResume
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
mStackSupervisor.checkReadyForSleepLocked();
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
}
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null, true);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
//activity 進入attach 和onCreate流程
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
第一次啟動進入onCreate流程,跨進程調用應用端ActivityThread.handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
... ...
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
... ...
}
}
WindowManagerGlobal 用于應用端和WMS通信,服務端是Session,WindowManagerGlobal.initialize() 直接調用getWindowManagerService
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
try {
sWindowManagerService = getWindowManagerService();
ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowManagerService;
}
}
得到WMS 服務代理對象
再回到ActivityThread.handleLaunchActivity 函數,調用performLaunchActivity
/android/frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//創建LoadedApk對象
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//創建ComponentName 對象
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {
//反射創建Activity對象
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
//創建Application 對象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
//調用activity.attach
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//這里回調Activity.onCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
... ...
if (!r.activity.mFinished) {
activity.mCalled = false;
//回調Activity.onPostCreate,onPostCreate Activity view 初始化完畢后調用,可以用來得到Activity中view的高寬等
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
}
}
return activity;
}
performLaunchActivity 函數中主要創建了LoadedApk、ComponentName、Activity對象,
并回調onCreate 和 onResume.
- Activity.attach
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//創建PhoneWindow 對象,繼承Window ,成員變量W,作為服務端 和WMS 通信
mWindow = new PhoneWindow(this, window);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();//得到ui 主線程
mMainThread = aThread; //獲取ActivityThread 對象
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
//獲得WindowManagerImpl對象
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();
mCurrentConfig = config;
}
attach 函數中主要初始化各種變量:
- PhoneWindow
- ActivityThread
- mUiThread
- mToken
- Window的WindowManagerImpl
再回到ActivityThread.handleLaunchActivity 函數,調用ActivityThread.handleResumeActivity
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
... ...
//回調onResume
r = performResumeActivity(token, clearHide, reason);
... ...
if (r.window == null && !a.mFinished && willBeVisible) {
... ...
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
//添加DecorView
wm.addView(decor, l);
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r, false /* force */);
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
... ...
//添加視圖
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
... ...
// Tell the activity manager we have resumed.
if (reallyResume) {
try {
ActivityManagerNative.getDefault().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
... ...
}
- performResumeActivity回調onResume
- 添加DecorView
- r.activity.makeVisible()添加視圖
- ActivityManagerNative.getDefault().activityResumed 通知AMS activty已經resumed
- Activity.makeVisible
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
調用WindowManagerImpl 的 addView方法,然后再調用WindowManagerGlobal.addView
- WindowManagerGlobal.addView
/frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
... ...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
.. ...
root = new ViewRootImpl(view.getContext(), display);
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);
} catch (RuntimeException e) {
... ...
}
/frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();// WMS 的Session對象的代理端
mDisplay = display;
mBasePackageName = context.getBasePackageName();
mThread = Thread.currentThread();
... ...
mWindow = new W(this);//W是服務端用于跟WMS 的WindowState 通信
... ...
mChoreographer = Choreographer.getInstance();
}
初始化mWindowSession 和 mWindow,建立應用和WMS之間的通信。
- WindowManagerGlobal.getWindowSession
/frameworks/base/core/java/android/view/WindowManagerGlobal.java
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
//sWindowSession 靜態變量,一個應用進程中所有ViewRootImpl 對象中mWindowSession 都引用相同對象,用于和WMS通信
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
跨進程調用WMS的openSession
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, callback, client, inputContext);
return session;
}
應用端得到Session的代理對象
- 回到WindowManagerGlobal.addView中的ViewRootImpl.setView
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
... ...
try {
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
}
... ...
}
- Session.addToDisplay直接調用WMS的addWindow
/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
... ...
//創建WindowState 對象
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
... ...
//調整窗口屬性,例如截圖窗口不能獲得焦點
mPolicy.adjustWindowParamsLw(win.mAttrs);
... ...
win.attach();
//以IWindow 代理對象作為key值
mWindowMap.put(client.asBinder(), win);
... ...
boolean focusChanged = false;
if (win.canReceiveKeys()) {
//如果能接受key事件,更新窗口焦點
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
if (focusChanged) {
imMayMove = false;
}
}
}
/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
mService = service;
mSession = s;//Session Binder 對象的服務端
mClient = c;//W Binder 對象的客戶端
mAppOp = appOp;
mToken = token;
mOwnerUid = s.mUid;
... ...
mContext = mService.mContext;
//應用死掉后回調DeathRecipient
DeathRecipient deathRecipient = new DeathRecipient();
mSeq = seq;
mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
try {
//c在應用進程
c.asBinder().linkToDeath(deathRecipient, 0);
}
}
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
void windowAddedLocked() {
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
TAG_WM, "First window added to " + this + ", creating SurfaceSession");
mSurfaceSession = new SurfaceSession();
if (SHOW_TRANSACTIONS) Slog.i(
TAG_WM, " NEW SURFACE SESSION " + mSurfaceSession);
//將當前Session對象添加到WMS Sessions 列表中
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
- WMS.updateFocusedWindowLocked
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
//計算當前獲得focus的窗口
WindowState newFocus = computeFocusedWindowLocked();
... ...
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
if (imWindowChanged && oldFocus != mInputMethodWindow) {
// Focus of the input method window changed. Perform layout if needed.
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
updateInputWindows);
focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
} else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
// Client will do the layout, but we need to assign layers
// for handleNewWindowLocked() below.
mLayersController.assignLayersLocked(displayContent.getWindowList());
}
}
if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
// The change in focus caused us to need to do a layout. Okay.
displayContent.layoutNeeded = true;
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
//焦點改變重新計算窗口大小
mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
updateInputWindows);
}
}
}
/android/frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
final void performLayoutLockedInner(final DisplayContent displayContent,
boolean initial, boolean updateInputWindows) {
... ...
//設置屏幕大小
mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
mService.mCurConfiguration.uiMode);
... ...
for (i = topAttached; i >= 0; i--) {
final WindowState win = windows.get(i);
if (win.mLayoutAttached) {
... ...
win.mLayoutNeeded = false;
win.prelayout();
//計算各層窗口大小
mService.mPolicy.layoutWindowLw(win, win.mAttachedWindow);
win.mLayoutSeq = seq;
}
} else if (win.mAttrs.type == TYPE_DREAM) {
attachedBehindDream = behindDream;
}
}
... ...
//執行清理工作
mService.mPolicy.finishLayoutLw();
mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
}
- 總結
Activity窗口啟動流程
- 調用startActivity進入Activity生命周期之前主要完成了以下工作:
(1).將activity所在task移到頂部
(2).創建WindowToken并加到 WindowToken列表中
(3).設置activity切換動畫的相關參數
(4).開啟startingWindow
- 進入Activity的attach、onCreate、onResume
(1) 創建LoadedApk、ComponentName、Activity對象
(2) 在attach 函數中初始化變量:PhoneWindow, ActivityThread, mUiThread, mToken, Window的WindowManagerImpl
(3) 執行performResumeActivity,回調onResume,添加DecorView, r.activity.makeVisible()添加視圖
(4)創建 ViewRootImpl對象,ViewRootImpl中創建IWindow的服務端對象和IWindowSession的代理對象,用于應用和WMS之前通信,一個應用進程中所有ViewRootImpl 對象中的IWindowSession代理對象都引用相同對象。
(5)最后調用WMS.addWindow 計算和添加窗口。