以下分析基于Android4.3.
1. 从Activity到ActivityManagerService
通过Activity1的startActivity启动Activity2,调用流程如下
(Activity).startActivity(Intent, Bundle)
--》(Activity).startActivityForResult(Intent, int)
--》(Activity).startActivityForResult(Intent, int, Bundle)
--》Instrumentation.execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)
Instrumentation.execStartActivity的实现如下:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
ActivityManagerNative.getDefault().startActivity通过AIDL进程间通信机制调用ActivityManagerService的startActivity方法。
2. 从ActivityMnageService到Activity
调用流程如下:
ActivityManagerService.startActivity(IApplicationThread, String, Intent, String, IBinder, String, int, int, String, ParcelFileDescriptor, Bundle)
--》ActivityManagerService.startActivityAsUser(IApplicationThread, String, Intent, String, IBinder, String, int, int, String, ParcelFileDescriptor, Bundle, int)
--》ActivityStack.startActivityMayWait(IApplicationThread, int, String, Intent, String, IBinder, String, int, int, String, ParcelFileDescriptor, IActivityManager$WaitResult, Configuration, Bundle, int)
--》ActivityStack.startActivityLocked(IApplicationThread, Intent, String, ActivityInfo, IBinder, String, int, int, int, String, int, Bundle, boolean, ActivityRecord[])
ActivityStack.startActivityLocked,这个过程会创建ActivityRecord,ActivityRecord构造的时候会创建成员变量appToken = new Token(this),这个appToken用来与WindowManager通信。接着调用以下过程
--》ActivityStack.startActivityUncheckedLocked(ActivityRecord, ActivityRecord, int, boolean, Bundle)
--》ActivityStack.startActivityLocked(ActivityRecord, boolean, boolean, boolean, Bundle)
--》ActivityStack.startActivityUncheckedLocked(ActivityRecord, ActivityRecord, int, boolean, Bundle)
--》ActivityStack.startActivityLocked(ActivityRecord, boolean, boolean, boolean, Bundle)
这次的startActivityLocked的参数不再是Intent而是ActivityRecord,
主要的过程分3步:
1. 将Activity2的ActivityRecord添加到mHistory中
2. 通过mWindowManager.addAppToken建立activity与WindowManagerService之间的联系。
mService.mWindowManager.addAppToken(
addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
在WindowManagerService的addAppToken的处理中,会创建atoken = new AppWindowToken(this, token);
接着 mAppTokens.add(addPos, atoken); //将atoken加入到WindowManagerService的成员mAppTokens中
addAppTokenToAnimating(addPos, atoken);
mTokenMap.put(token.asBinder(), atoken); //建立appToken与AppWindowToken的映射关系
3. 继续进行启动Activity2的流程
-->resumeTopActivityLocked(null);
这个过程分两步:
1)ActivityStack.startPausingLocked(boolean, boolean) ,使前一个Activity进行pause动作
调用
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags);
进而进入到应用程序侧的handlePauseActivity流程,这个流程中先进行activity的onPause回调,再通过AIDL调用ActivityManagerService的activityPaused方法。
2)启动下一个Activity
ActivityManagerService.activityPaused(IBinder)
--》ActivityStack.activityPaused(IBinder, boolean)
先进行前一个Activity的Pause流程,之后是completePauseLocked
--》ActivityStack.completePauseLocked() line:
--》ActivityStack.resumeTopActivityLocked(ActivityRecord)
--》ActivityStack.resumeTopActivityLocked(ActivityRecord, Bundle)
--》ActivityStack.startSpecificActivityLocked(ActivityRecord, boolean, boolean)
startSpecificActivityLocked的处理中会判断Activity2和Activity1是否是同一个进程。
如果不是,调用mService.startProcessLocked,启动一个新的进程。
如果是,调用startSpecificActivityLocked,这个函数中会调用app.thread.scheduleLaunchActivity进入Activity侧的处理流程。
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler, int panelIndex) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
r.mPanelIndex = panelIndex;
updatePendingConfiguration(curConfig);
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
注:这个过程会把
r.appToken传递给Activity侧的
ActivityClientRecord
3. Activity侧的处理流程
通过message会进入以下过程
ActivityThread.handleLaunchActivity(ActivityThread$ActivityClientRecord, Intent)
--》ActivityThread.performLaunchActivity(ActivityThread$ActivityClientRecord, Intent)
--》(Activity).attach(Context, ActivityThread, Instrumentation, IBinder, int, Application, Intent, ActivityInfo, CharSequence, Activity, String, Activity$NonConfigurationInstances, Configuration, int)
-->(Activity).attach(Context, ActivityThread, Instrumentation, IBinder, int, Application, Intent, ActivityInfo, CharSequence, Activity, String,
Activity$NonConfigurationInstances, Configuration)
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) {
attachBaseContext(context);
mFragments.attachActivity(this, mContainer, null);
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setWindowPanelIndex(mPanelIndex);
String deviveName = (String)intent.getExtra("devicename");
if(deviveName!=null){
mWindow.setWindowTitle(deviveName);
}
mWindow.setCallback(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();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
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处理:把token赋值给Activity的成员变量mToken,mWindow是一个PhoneWindow.(继承自Window),是Activity的成员。通过调用mWindow.setWindowManager将mToken赋值给Window的mAppToken成员变量。
attach之后,performLaunchActivity会间接调用Activity的onCreate,进而调用setContentView,生成decorView。
接着
ActivityThread.handleLaunchActivity(ActivityThread$ActivityClientRecord, Intent)
如下是部分代码:
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();//取得Activity的window
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);
}
// 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;
}
4. addView的处理流程
WindowManagerImpl.addView(View, ViewGroup$LayoutParams)
--》WindowManagerGlobal.addView(View, ViewGroup$LayoutParams, Display, Window)
addView传入的第二个参数是LayoutParams,是Activity对应的window的mWindowAttributes属性。
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (ViewRootImpl viewRoot : mRoots) {
viewRoot.loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false);
if (index >= 0) {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews != null ? mViews.length : 0;
for (int i=0; i<count; i++) {
if (mRoots[i].mWindow.asBinder() == wparams.token) {
panelParentView = mViews[i];
}
}
}
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
if (mViews == null) {
index = 1;
mViews = new View[1];
mRoots = new ViewRootImpl[1];
mParams = new WindowManager.LayoutParams[1];
} else {
index = mViews.length + 1;
Object[] old = mViews;
mViews = new View[index];
System.arraycopy(old, 0, mViews, 0, index-1);
old = mRoots;
mRoots = new ViewRootImpl[index];
System.arraycopy(old, 0, mRoots, 0, index-1);
old = mParams;
mParams = new WindowManager.LayoutParams[index];
System.arraycopy(old, 0, mParams, 0, index-1);
}
index--;
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
1)通过调用adjustLayoutParamsForSubWindow将LayoutParams的token成员变量。
2)ViewRootImpl的构造
public ViewRootImpl(Context context, Display display) {
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
CompatibilityInfoHolder cih = display.getCompatibilityInfo();
mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();
mWindow = new W(this);
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
mAccessibilityManager = AccessibilityManager.getInstance(context);
mAccessibilityInteractionConnectionManager =
new AccessibilityInteractionConnectionManager();
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mAttachInfo.mScreenOn = powerManager.isScreenOn();
loadSystemProperties();
}
3)设定decorView的LayoutParams
4)ViewRootImpl.setView部分处理
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
}
说明: 1.requestLayout将遍历布局的处理放入UI主线程的工作队列中。
2. mWindowSession.addToDisplay,最后会调用WindwoMangerService的addWindow处理。
3. addWindow之后会执行requestLayout放入工作队列中的处理过程,会调用WindwoMangerService的relayoutWindow。
5. 各组件间关系