http://blog.csdn.net/u014486880/article/details/50491406?locationNum=14
其实写分析源码文章总会显得很复杂很乏味,但是梳理自己看源码时的一些总结也是一种提高。这篇博客分析下Activity启动过程源码,我会尽量说得简单点。个人的观点是看源码不能看得太细,否则就会花费很多时间并很难理清整个过程。所以本次分析重在理清activity的一个启动流程。
首先大概总结下activity启动的整个流程,这个过程涉及到Instrumentation,ActivityThread,和ActivityManagerService(AMS)。通过Binder向AMS发请求,AMS内部有一个ActivityStack,它负责栈内的Activity同步,AMS去通过ActivityThread去调用Activity的生命周期方法完成Activity的启动。如果对Binder进程间通信不了解可看下IPC——android进程间通信
先上一张总图,等看完博客可以再回头来看下这图:
一.启动预处理
启动一个activity最常用的方法就是startActivityForResult或者startActivity,而startActivity也是调用startActivityForResult,所以此次分析入口当然是startActivityForResult。
- public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
- if (mParent == null) {
- Instrumentation.ActivityResult ar =
- mInstrumentation .execStartActivity(
- this, mMainThread .getApplicationThread() , mToken, this,
- intent, requestCode, options) ;
- if (ar != null) {
- mMainThread .sendActivityResult(
- mToken, mEmbeddedID, requestCode , ar.getResultCode(),
- ar.getResultData());
- }
- if (requestCode >= 0) {
-
-
-
-
-
-
-
- mStartedActivity = true;
- }
-
- final View decor = mWindow != null ? mWindow .peekDecorView() : null;
- if (decor != null) {
- decor.cancelPendingInputEvents();
- }
-
- } else {
- if (options != null) {
- mParent .startActivityFromChild( this, intent, requestCode, options) ;
- } else {
-
-
- mParent .startActivityFromChild( this, intent, requestCode);
- }
- }
- if (options != null && !isTopOfTask()) {
- mActivityTransitionState .startExitOutTransition( this, options);
- }
- }
Intrumentation它用来监控应用程序和系统的交互。而mMainThread.getApplicationThread()获取ApplicationThread,它是ActivityThread的一个内部类,
是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。上面的代码最终调用了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, options) ;
- checkStartActivityResult(result, intent) ;
- } catch (RemoteException e) {
- }
- return null;
- }
这里的intent.resolveTypeIfNeeded返回这个intent的MIME类型,如果没有在AndroidManifest.xml设置MainActivity的MIME类型那就返回null。
启动的真正实现类由ActivityManagerNative.getDefault()的startActivity方法完成。先分析下ActivityManagerNative.getDefault()。
- public abstract class ActivityManagerNative extends Binder implements IActivityManager{
- …………
- private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
- protected IActivityManager create() {
- IBinder b = ServiceManager.getService("activity") ;
- if ( false) {
- Log.v ("ActivityManager" , "default service binder = " + b);
- }
- IActivityManager am = asInterface (b);
- if ( false) {
- Log.v ("ActivityManager" , "default service = " + am);
- }
- return am;
- }
- };
- }
可以看到
ActivityManagerNative是一个抽象类,它继承Binder,并实现了IActivityManager接口,ActivityManagerService(下称AMS)继承着ActivityManagerNative,所以它是IActivityManager的具体实现类。ActivityManagerNative.getDefault是一个IActivityManager类型的Binder对象,因此它的具体实现是AMS。获取的AMS的Binder对象是一个单例。
ActivityManagerNative就相当于AIDL文件自动生成的那个类。ActivityManagerProxy是ActivityManagerNative中的一个代理方法,看下它的startActivity代码:
- class ActivityManagerProxy implements IActivityManager
- {
- public ActivityManagerProxy(IBinder remote)
- {
- mRemote = remote;
- }
- public IBinder asBinder()
- {
- return mRemote;
- }
- public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
- String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(callingPackage);
- intent.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeStrongBinder(resultTo);
- data.writeString(resultWho);
- data.writeInt(requestCode);
- data.writeInt(startFlags);
- if (profilerInfo != null) {
- data.writeInt(1);
- profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- } else {
- data.writeInt(0);
- }
- if (options != null) {
- data.writeInt(1);
- options.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- int result = reply.readInt();
- reply.recycle();
- data.recycle();
- return result;
- }
-
-
- public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,
- String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options,
- int userId) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(callingPackage);
- intent.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeStrongBinder(resultTo);
- data.writeString(resultWho);
- data.writeInt(requestCode);
- data.writeInt(startFlags);
- if (profilerInfo != null) {
- data.writeInt(1);
- profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- } else {
- data.writeInt(0);
- }
- if (options != null) {
- data.writeInt(1);
- options.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- data.writeInt(userId);
- mRemote.transact(START_ACTIVITY_AS_USER_TRANSACTION, data, reply, 0);
- reply.readException();
- int result = reply.readInt();
- reply.recycle();
- data.recycle();
- return result;
- …………
- }
看到这就会发现,其实就是AIDL来进行进程间通信。它是真正实现类还应该是AMS中的
startActivity。
- public int startActivity(IBinder whoThread, String callingPackage,
- Intent intent, String resolvedType, Bundle options) {
- checkCaller();
-
- int callingUser = UserHandle.getCallingUserId();
- TaskRecord tr;
- IApplicationThread appThread;
- synchronized (ActivityManagerService.this) {
- tr = recentTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- appThread = ApplicationThreadNative.asInterface(whoThread);
- if (appThread == null) {
- throw new IllegalArgumentException("Bad app thread " + appThread);
- }
- }
- return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,
- resolvedType, null, null, null, null, 0, 0, null, null,
- null, options, callingUser, null, tr);
- }
最后调用了
mStackSupervisor.startActivityMayWait,主要看两部分:
1.解析Intent。
下面语句对参数intent的内容进行解析,得到MainActivity的相关信息,保存在aInfo变量中:
- ActivityInfo aInfo;
- try {
- ResolveInfo rInfo =
- AppGlobals.getPackageManager().resolveIntent(
- intent, resolvedType,
- PackageManager.MATCH_DEFAULT_ONLY
- | ActivityManagerService.STOCK_PM_FLAGS);
- aInfo = rInfo != null ? rInfo.activityInfo : null;
- } catch (RemoteException e) {
- ......
- }
2.:调用
startActivityLocked。
- int res = startActivityLocked(caller, intent, resolvedType, aInfo,
- voiceSession, voiceInteractor, resultTo, resultWho,
- requestCode, callingPid, callingUid, callingPackage,
- realCallingPid, realCallingUid, startFlags, options,
- componentSpecified, null, container, inTask);
最的返回了
startActivityLocked,它在
ActivityStackSupervisor
中,再看下它的代码:
- final int startActivityLocked(IApplicationThread caller,
- Intent intent, String resolvedType, ActivityInfo aInfo,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- IBinder resultTo, String resultWho, int requestCode,
- int callingPid, int callingUid, String callingPackage,
- int realCallingPid, int realCallingUid, int startFlags, Bundle options,
- boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
- TaskRecord inTask) {
- int err = ActivityManager.START_SUCCESS;
-
- ProcessRecord callerApp = null;
- if (caller != null) {
- callerApp = mService.getRecordForAppLocked(caller);
- if (callerApp != null) {
- callingPid = callerApp.pid;
- callingUid = callerApp.info.uid;
- } else {
- Slog.w(TAG, "Unable to find app for caller " + caller
- + " (pid=" + callingPid + ") when starting: "
- + intent.toString());
- err = ActivityManager.START_PERMISSION_DENIED;
- }
- }
- …………
- ActivityRecord sourceRecord = null;
- ActivityRecord resultRecord = null;
- if (resultTo != null) {
- sourceRecord = isInAnyStackLocked(resultTo);
- if (DEBUG_RESULTS) Slog.v(
- TAG, "Will send result to " + resultTo + " " + sourceRecord);
- if (sourceRecord != null) {
- if (requestCode >= 0 && !sourceRecord.finishing) {
- resultRecord = sourceRecord;
- }
- }
- }
- final int launchFlags = intent.getFlags();
- if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
-
-
- if (requestCode >= 0) {
- ActivityOptions.abort(options);
- return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
- }
- resultRecord = sourceRecord.resultTo;
- resultWho = sourceRecord.resultWho;
- requestCode = sourceRecord.requestCode;
- sourceRecord.resultTo = null;
-
- …………
- ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
- intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
- requestCode, componentSpecified, this, container, options);
- ^………………
- err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
- startFlags, true, options, inTask);
分三步:
1.
从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了。
前面说过,参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。
2.
创建即将要启动的Activity的相关信息,并保存在r变量中。
3.调用startActivityUncheckedLocked。startActivityUncheckedLocked的核心代码如下:
- final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
- final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
- final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
-
- int launchFlags = intent.getFlags();
- if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
- (launchSingleInstance || launchSingleTask)) {
-
- Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
- "\"singleInstance\" or \"singleTask\"");
- launchFlags &=
- ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- …………
- if (doResume) {
- resumeTopActivitiesLocked();
- }
- ActivityOptions.abort(options);
函数首先获得intent的标志值,保存在launchFlags变量中。
。Activity的启动方式有四种,接下来一系列判断就是决定Activity四种不同启动模式的启动方式。然后判断
当前要启动的Activity是否就是当前堆栈顶端的Activity,如果是的话,在某些情况下,就不用再重新启动了。
最后调用了
resumeTopActivitiesLocked,现在这个过程己经从ActivityStackSupervisor转移到
ActivityStack。
- final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
- if (mStackSupervisor.inResumeTopActivity) {
-
- return false;
- }
-
- boolean result = false;
- try {
-
- mStackSupervisor.inResumeTopActivity = true;
- if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
- mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
- mService.updateSleepIfNeededLocked();
- }
- result = resumeTopActivityInnerLocked(prev, options);
- } finally {
- mStackSupervisor.inResumeTopActivity = false;
- }
- return result;
- }
通过上面的代码可知,
resumeTopActivitiesLocked调用了resumeTopActivityInnerLocked方法。来看下resumeTopActivityInnerLocked源代码,由于这部分代码很长,只贴出它的最主要流程:
- if ((mService.mSleeping || mService.mShuttingDown)
- <span style="white-space:pre"> </span> && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
- <span style="white-space:pre"> </span> ......
- <span style="white-space:pre"> </span> return false;
- <span style="white-space:pre"> </span> }
- .......
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span> if (mResumedActivity != null) {
- <span style="white-space:pre"> </span> if (mResumedActivity != null) {
- if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
- pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
- }
- <span style="white-space:pre"> </span> return true;
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> ......
- <span style="white-space:pre"> </span> if (next.app != null && next.app.thread != null) {
- <span style="white-space:pre"> </span> ......
- <span style="white-space:pre"> </span> } else {
- <span style="white-space:pre"> </span> ......
- <span style="white-space:pre"> </span> startSpecificActivityLocked(next, true, true);
- <span style="white-space:pre"> </span> }
- <span style="white-space:pre"> </span> return true;
- <span style="white-space:pre"> </span> }
由上可以清晰的看到,如果当前activity没暂停,要先把它暂停。
二.暂停当前Activity
上面己经分析到新Activity启动会先把之前的Activity暂停,具体是调用startPausingLocked方法。它的核心代码如下:
- if (prev.app != null && prev.app.thread != null) {
- if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
- try {
- EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
- prev.userId, System.identityHashCode(prev),
- prev.shortComponentName);
- mService.updateUsageStats(prev, false);
- prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
- userLeaving, prev.configChangeFlags, dontWait);
prev.app.thread是一个ApplicationThread对象的远程接口,它的类型是IApplicationThread。
通过调用这个远程接口的schedulePauseActivity来通知Activity进入Paused状态。先看下IApplicationThread接口。
- public interface IApplicationThread extends IInterface {
- void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
- int configChanges, boolean dontReport) throws RemoteException;
- void scheduleStopActivity(IBinder token, boolean showWindow,
- int configChanges) throws RemoteException;
- void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
- void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
- void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)
- throws RemoteException;
- void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
- void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
- String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
- PersistableBundle persistentState, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
- ProfilerInfo profilerInfo) throws RemoteException;
- void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, int configChanges,
- boolean notResumed, Configuration config) throws RemoteException;
- void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;
- void scheduleDestroyActivity(IBinder token, boolean finished,
- int configChanges) throws RemoteException;
- void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
- int resultCode, String data, Bundle extras, boolean sync,
- int sendingUser, int processState) throws RemoteException;
- static final int BACKUP_MODE_INCREMENTAL = 0;
- static final int BACKUP_MODE_FULL = 1;
- static final int BACKUP_MODE_RESTORE = 2;
- static final int BACKUP_MODE_RESTORE_FULL = 3;
- void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,
- int backupMode) throws RemoteException;
- void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)
- throws RemoteException;
- void scheduleCreateService(IBinder token, ServiceInfo info,
- CompatibilityInfo compatInfo, int processState) throws RemoteException;
- void scheduleBindService(IBinder token,
- Intent intent, boolean rebind, int processState) throws RemoteException;
- void scheduleUnbindService(IBinder token,
- Intent intent) throws RemoteException;
- void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
- int flags, Intent args) throws RemoteException;
- void scheduleStopService(IBinder token) throws RemoteException;
- static final int DEBUG_OFF = 0;
- static final int DEBUG_ON = 1;
- static final int DEBUG_WAIT = 2;
- void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
- ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,
- IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
- int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,
- Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
- Bundle coreSettings) throws RemoteException;
- void scheduleExit() throws RemoteException;
- void scheduleSuicide() throws RemoteException;
- void scheduleConfigurationChanged(Configuration config) throws RemoteException;
- void updateTimeZone() throws RemoteException;
- void clearDnsCache() throws RemoteException;
- void setHttpProxy(String proxy, String port, String exclList,
- Uri pacFileUrl) throws RemoteException;
- void processInBackground() throws RemoteException;
- void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
- throws RemoteException;
- void dumpProvider(FileDescriptor fd, IBinder servicetoken, String[] args)
- throws RemoteException;
- void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String data, Bundle extras, boolean ordered,
- boolean sticky, int sendingUser, int processState) throws RemoteException;
- void scheduleLowMemory() throws RemoteException;
- void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
- void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType)
- throws RemoteException;
- void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
- throws RemoteException;
由此猜测它与activity,service的开启有关。IApplicationThread这个IBind实现者完成了大量和Activity以及service有关的功能。
而ApplicationThreadNative就是它的实现类。
- public abstract class ApplicationThreadNative extends Binder
- implements IApplicationThread {
-
-
-
-
- static public IApplicationThread asInterface(IBinder obj) {
- if (obj == null) {
- return null;
- }
- IApplicationThread in =
- (IApplicationThread)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new ApplicationThreadProxy(obj);
- }
-
- public ApplicationThreadNative() {
- attachInterface(this, descriptor);
- }
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- switch (code) {
- case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- boolean finished = data.readInt() != 0;
- boolean userLeaving = data.readInt() != 0;
- int configChanges = data.readInt();
- boolean dontReport = data.readInt() != 0;
- schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport);
- return true;
- }
- <pre name="code" class="java" style="color: rgb(51, 51, 51); line-height: 26px; orphans: 2; widows: 2;">public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(finished ? 1 : 0);
- data.writeInt(userLeaving ? 1 :0);
- data.writeInt(configChanges);
- data.writeInt(dontReport ? 1 : 0);
- mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
………………}
由上可见它就是一个Binder抽象类,
ApplicationThreadProxy是代理类。真正实现类是ApplicationThread。直接看
ApplicationThread的
schedulePauseActivity方法。
- public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges, boolean dontReport) {
- sendMessage(
- finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
- token,
- (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
- configChanges);
- }
看到这,就知道接下来肯定是用Handler来发送消息了,发送消息的代码如下:
- private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
- if (DEBUG_MESSAGES) Slog.v(
- TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
- + ": " + arg1 + " / " + obj);
- Message msg = Message.obtain();
- msg.what = what;
- msg.obj = obj;
- msg.arg1 = arg1;
- msg.arg2 = arg2;
- if (async) {
- msg.setAsynchronous(true);
- }
- mH.sendMessage(msg);
- }
就是在发送一个暂停Activity的消息给Handler处理,这个Handler名字为H。H在它的handlerMessage中处理相应的请求,它的实现如下:
- public void handleMessage(Message msg) {
-
- switch (msg.what) {
- …………
- case PAUSE_ACTIVITY:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
- handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
- (msg.arg1&2) != 0);
- maybeSnapshot();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
- …………
- }
看下handlePauseActivity的代码:
- private void handlePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges, boolean dontReport) {
- ActivityClientRecord r = mActivities.get(token);
- if (r != null) {
-
- if (userLeaving) {
- performUserLeavingActivity(r);
- }
-
- r.activity.mConfigChangeFlags |= configChanges;
- performPauseActivity(token, finished, r.isPreHoneycomb());
-
-
- if (r.isPreHoneycomb()) {
- QueuedWork.waitToFinish();
- }
-
-
- if (!dontReport) {
- try {
- ActivityManagerNative.getDefault().activityPaused(token);
- } catch (RemoteException ex) {
- }
- }
- mSomeActivitiesChanged = true;
- }
函数首先将Binder引用token转换成ActivityRecord的远程接口ActivityClientRecord,然后做了三个事情:1. 如果userLeaving为true,则通过调用performUserLeavingActivity函数来调用Activity.onUserLeaveHint通知Activity,用户要离开它了;2. 调用performPauseActivity函数来调用Activity.onPause函数,我们知道,在Activity的生命周期中,当它要让位于其它的Activity时,系统就会调用它的onPause函数;3. 它通知ActivityManagerService,这个Activity已经进入Paused状态了,ActivityManagerService现在可以完成未竟的事情,即启动MainActivity了。
看下ActivityManagerService.activityPaused的代码:
- public final void activityPaused(IBinder token) {
- final long origId = Binder.clearCallingIdentity();
- synchronized(this) {
- ActivityStack stack = ActivityRecord.getStackLocked(token);
- if (stack != null) {
- stack.activityPausedLocked(token, false);
- }
- }
- Binder.restoreCallingIdentity(origId);
- }
绕了一大圈又回到了ActivityStack中,调用它的activityPauseLocked方法。
- final void activityPausedLocked(IBinder token, boolean timeout) {
- if (DEBUG_PAUSE) Slog.v(
- TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
-
- final ActivityRecord r = isInStackLocked(token);
- if (r != null) {
- mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
- if (mPausingActivity == r) {
- if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
- + (timeout ? " (due to timeout)" : " (pause complete)"));
- completePauseLocked(true);
- } else {
- EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
- r.userId, System.identityHashCode(r), r.shortComponentName,
- mPausingActivity != null
- ? mPausingActivity.shortComponentName : "(none)");
- }
- }
- }
前一个Activity的信息保存在mPausingActivity中,因此,这里mPausingActivity等于r,于是,执行completePauseLocked操作。
- private void completePauseLocked(boolean resumeNext) {
- …………
- if (resumeNext) {
- final ActivityStack topStack = mStackSupervisor.getFocusedStack();
- if (!mService.isSleepingOrShuttingDown()) {
- mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
- } else {
- mStackSupervisor.checkReadyForSleepLocked();
- ActivityRecord top = topStack.topRunningActivityLocked(null);
- if (top == null || (prev != null && top != prev)) {
-
-
-
-
-
- mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
- }
- }
- }
- …………
- }
很显然,又回到了resumeTopActivitiesLocked中,这次activity己经停止,所以它
调用了ActivityStackSupervisor的StartSpecificActivityLocked方法。
三,启动Activity
其实启动Activity与暂停很类似,都是在ApplicationThread中实现的,看代码:
- void startSpecificActivityLocked(ActivityRecord r,
- boolean andResume, boolean checkConfig) {
-
- ProcessRecord app = mService.getProcessRecordLocked(r.processName,
- r.info.applicationInfo.uid, true);
-
- r.task.stack.setLaunchTime(r);
-
- if (app != null && app.thread != null) {
- try {
- if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
- || !"android".equals(r.info.packageName)) {
-
-
-
-
- app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
- mService.mProcessStats);
- }
- realStartActivityLocked(r, app, andResume, checkConfig);
- return;
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception when starting activity "
- + r.intent.getComponent().flattenToShortString(), e);
- }
-
-
-
- }
-
- mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
- "activity", r.intent.getComponent(), false, false, true);
- }
接下来重点看下
realStartActivityLocked,它代码中有以下一段
- app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
- System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
- r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
- r.icicle, r.persistentState, results, newIntents, !andResume,
- mService.isNextTransitionForward(), profilerInfo);
是不是有种似曾相识的感觉。接下来就是跟暂停一样了,调用
ApplicationThread中的scheduleLaunchActivity,最终调用H中的HandlerMessage。
- public void handleMessage(Message msg) {
- if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
- switch (msg.what) {
- case LAUNCH_ACTIVITY: {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
- final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
-
- r.packageInfo = getPackageInfoNoCheck(
- r.activityInfo.applicationInfo, r.compatInfo);
- handleLaunchActivity(r, null);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- } break;
- ………………
再看下handleLaunchActivity()的实现,代码比较长,只看核心的。
- if (localLOGV) Slog.v(
- TAG, "Handling launch of " + r);
-
-
- WindowManagerGlobal.initialize();
-
- Activity a = performLaunchActivity(r, customIntent);
-
- if (a != null) {
- r.createdConfig = new Configuration(mConfiguration);
- Bundle oldState = r.state;
- handleResumeActivity(r.token, false, r.isForward,
- !r.activity.mFinished && !r.startsNotResumed);
performLaunchAcitvity中调用Activity的onCreate(),onStart()方法,handlerResumeActivity调用onResume()方法。重点看下
performLaunchAcitvity,
我们
把它拆分来看,它总共完成以下几个功能。
1.从ActivityClientRecord中获取待启动的Activity的组件信息
- ActivityInfo aInfo = r.activityInfo;
- if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
- Context.CONTEXT_INCLUDE_CODE);
- }
-
- 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);
- }
2.通过Instrumentation 的newActivity方法使用类加载器创建Activity对象
- Activity activity = null;
- try {
- 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);
- }
- }
重点实现在newActivity中
- public Activity newActivity(ClassLoader cl, String className,
- Intent intent)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- return (Activity)cl.loadClass(className).newInstance();
- }
3.通过LoadedApk的makeApplication方法来尝试创建Application
- public Application makeApplication(boolean forceDefaultAppClass,
- Instrumentation instrumentation) {
- if (mApplication != null) {
- return mApplication;
- }
-
- Application app = null;
-
- String appClass = mApplicationInfo.className;
- if (forceDefaultAppClass || (appClass == null)) {
- appClass = "android.app.Application";
- }
-
- try {
- java.lang.ClassLoader cl = getClassLoader();
- if (!mPackageName.equals("android")) {
- initializeJavaContextClassLoader();
- }
- ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
- app = mActivityThread.mInstrumentation.newApplication(
- cl, appClass, appContext);
- appContext.setOuterContext(app);
- } catch (Exception e) {
- if (!mActivityThread.mInstrumentation.onException(app, e)) {
- throw new RuntimeException(
- "Unable to instantiate application " + appClass
- + ": " + e.toString(), e);
- }
- }
- mActivityThread.mAllApplications.add(app);
- mApplication = app;
-
- if (instrumentation != null) {
- try {
- instrumentation.callApplicationOnCreate(app);
- } catch (Exception e) {
- if (!instrumentation.onException(app, e)) {
- throw new RuntimeException(
- "Unable to create application " + app.getClass().getName()
- + ": " + e.toString(), e);
- }
- }
- }
- ………
如果Application被创建了,就不会再重复创建了。这也意味着一个应用只有一个Application,它的创建是通过Instrumentation来完成的。通过类加载载来实现。创建完通过callApplicationOnCreate来调用Application的onCreate()方法。
4,创建ContextImpl对象并通过Activity的attach方法来完成一些重要数据的初始化。
- Context appContext = createBaseContextForActivity(r, activity);
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- Configuration config = new Configuration(mCompatConfiguration);
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
- + r.activityInfo.name + " with config " + config);
- 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);
ContextImpl是通过Activity的attach方法与Acitivity建立关联的。此外attach来完成window的创建并建立自己和window的关联。这样当window接收到外部输入事件后就可以将事件传递给Activity。
到些Activity就启动起来了。
四,总结
在应用程序内部启动新的Activity的过程要执行很多步骤,但是整体来看,主要分为以下四个阶段:
1. 应用程序的MainActivity通过Binder进程间通信机制通知ActivityManagerService,它要启动一个新的Activity;
2. :ActivityManagerService通过Binder进程间通信机制通知MainActivity进入Paused状态;
3. MainActivity通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就准备要在MainActivity所在的进程和任务中启动新的Activity了;
4. ActivityManagerService通过Binder进程间通信机制通知MainActivity所在的ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。
现在再回头去看下那个启动图,应该大部分能看懂了。