一、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 计算和添加窗口。