天天看點

Activity啟動過程源碼分析一.啟動預處理二.暫停目前Activity三,啟動Activity四,總結 一.啟動預處理二.暫停目前Activity三,啟動Activity四,總結 

目錄(?)[+]

其實寫分析源碼文章總會顯得很複雜很乏味,但是梳理自己看源碼時的一些總結也是一種提高。這篇部落格分析下Activity啟動過程源碼,我會盡量說得簡單點。個人的觀點是看源碼不能看得太細,否則就會花費很多時間并很難理清整個過程。是以本次分析重在理清activity的一個啟動流程。

首先大概總結下activity啟動的整個流程,這個過程涉及到Instrumentation,ActivityThread,和ActivityManagerService(AMS)。通過Binder向AMS發請求,AMS内部有一個ActivityStack,它負責棧内的Activity同步,AMS去通過ActivityThread去調用Activity的生命周期方法完成Activity的啟動。如果對Binder程序間通信不了解可看下IPC——android程序間通信

先上一張總圖,等看完部落格可以再回頭來看下這圖:

Activity啟動過程源碼分析一.啟動預處理二.暫停目前Activity三,啟動Activity四,總結 一.啟動預處理二.暫停目前Activity三,啟動Activity四,總結 

一.啟動預處理

啟動一個activity最常用的方法就是startActivityForResult或者startActivity,而startActivity也是調用startActivityForResult,是以此次分析入口當然是startActivityForResult。

[java]  view plain  copy

  1. public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {  
  2.     if (mParent == null) {  
  3.         Instrumentation.ActivityResult ar =  
  4.             mInstrumentation .execStartActivity(  
  5.                 this, mMainThread .getApplicationThread() , mToken, this,  
  6.                 intent, requestCode, options) ;  
  7.         if (ar != null) {  
  8.             mMainThread .sendActivityResult(  
  9.                 mToken, mEmbeddedID, requestCode , ar.getResultCode(),  
  10.                 ar.getResultData());  
  11.         }  
  12.         if (requestCode >= 0) {  
  13.             // If this start is requesting a result, we can avoid making  
  14.             // the activity visible until the result is received.  Setting  
  15.             // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the  
  16.             // activity hidden during this time, to avoid flickering.  
  17.             // This can only be done when a result is requested because  
  18.             // that guarantees we will get information back when the  
  19.             // activity is finished, no matter what happens to it.  
  20.             mStartedActivity = true;  
  21.         }  
  22.         final View decor = mWindow != null ? mWindow .peekDecorView() : null;  
  23.         if (decor != null) {  
  24.             decor.cancelPendingInputEvents();  
  25.         }  
  26.         // TODO Consider clearing/flushing other event sources and events for child windows.  
  27.     } else {  
  28.         if (options != null) {  
  29.             mParent .startActivityFromChild( this, intent, requestCode, options) ;  
  30.         } else {  
  31.             // Note we want to go through this method for compatibility with  
  32.             // existing applications that may have overridden it.  
  33.             mParent .startActivityFromChild( this, intent, requestCode);  
  34.         }  
  35.     }  
  36.     if (options != null && !isTopOfTask()) {  
  37.         mActivityTransitionState .startExitOutTransition( this, options);  
  38.     }  
  39. }  

Intrumentation它用來監控應用程式和系統的互動。而mMainThread.getApplicationThread()擷取ApplicationThread,它是ActivityThread的一個内部類, 是一個Binder對象,後面我們會看到,ActivityManagerService會使用它來和ActivityThread來進行程序間通信。上面的代碼最終調用了 execStartActivity方法。 [java]  view plain  copy

  1. public ActivityResult execStartActivity(  
  2.         Context who, IBinder contextThread, IBinder token , Activity target,  
  3.         Intent intent , int requestCode, Bundle options) {  
  4.     IApplicationThread whoThread = (IApplicationThread) contextThread;  
  5.     if ( mActivityMonitors != null ) {  
  6.         synchronized (mSync) {  
  7.             final int N = mActivityMonitors.size() ;  
  8.             for ( int i=0 ; i<N; i++) {  
  9.                 final ActivityMonitor am = mActivityMonitors.get(i);  
  10.                 if (am.match(who, null, intent)) {  
  11.                     am. mHits++;  
  12.                     if (am.isBlocking()) {  
  13.                         return requestCode >= 0 ? am.getResult() : null;  
  14.                     }  
  15.                     break;  
  16.                 }  
  17.             }  
  18.         }  
  19.     }  
  20.     try {  
  21.         intent.migrateExtraStreamToClipData();  
  22.         intent.prepareToLeaveProcess() ;  
  23.         int result = ActivityManagerNative. getDefault()  
  24.             .startActivity(whoThread, who.getBasePackageName() , intent,  
  25.                     intent.resolveTypeIfNeeded(who.getContentResolver()),  
  26.                     token, target != null ? target.mEmbeddedID : null,  
  27.                     requestCode, 0, null, options) ;  
  28.         checkStartActivityResult(result, intent) ;  
  29.     } catch (RemoteException e) {  
  30.     }  
  31.     return null;  
  32. }  

這裡的intent.resolveTypeIfNeeded傳回這個intent的MIME類型,如果沒有在AndroidManifest.xml設定MainActivity的MIME類型那就傳回null。 啟動的真正實作類由ActivityManagerNative.getDefault()的startActivity方法完成。先分析下ActivityManagerNative.getDefault()。 [java]  view plain  copy

  1. public abstract class ActivityManagerNative extends Binder implements IActivityManager{  
  2. …………  
  3. private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {  
  4.     protected IActivityManager create() {  
  5.         IBinder b = ServiceManager.getService("activity") ;  
  6.         if ( false) {  
  7.             Log.v ("ActivityManager" , "default service binder = " + b);  
  8.         }  
  9.         IActivityManager am = asInterface (b);  
  10.         if ( false) {  
  11.             Log.v ("ActivityManager" , "default service = " + am);  
  12.         }  
  13.         return am;  
  14.     }  
  15. };  
  16. }  

可以看到 ActivityManagerNative是一個抽象類,它繼承Binder,并實作了IActivityManager接口,ActivityManagerService(下稱AMS)繼承着ActivityManagerNative,是以它是IActivityManager的具體實作類。ActivityManagerNative.getDefault是一個IActivityManager類型的Binder對象,是以它的具體實作是AMS。擷取的AMS的Binder對象是一個單例。 ActivityManagerNative就相當于AIDL檔案自動生成的那個類。ActivityManagerProxy是ActivityManagerNative中的一個代理方法,看下它的startActivity代碼:

[java]  view plain  copy

  1. class ActivityManagerProxy implements IActivityManager  
  2. {  
  3.     public ActivityManagerProxy(IBinder remote)  
  4.     {  
  5.         mRemote = remote;  
  6.     }  
  7.     public IBinder asBinder()  
  8.     {  
  9.         return mRemote;  
  10.     }  
  11.     public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,  
  12.             String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
  13.             int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {  
  14.         Parcel data = Parcel.obtain();  
  15.         Parcel reply = Parcel.obtain();  
  16.         data.writeInterfaceToken(IActivityManager.descriptor);  
  17.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
  18.         data.writeString(callingPackage);  
  19.         intent.writeToParcel(data, 0);  
  20.         data.writeString(resolvedType);  
  21.         data.writeStrongBinder(resultTo);  
  22.         data.writeString(resultWho);  
  23.         data.writeInt(requestCode);  
  24.         data.writeInt(startFlags);  
  25.         if (profilerInfo != null) {  
  26.             data.writeInt(1);  
  27.             profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);  
  28.         } else {  
  29.             data.writeInt(0);  
  30.         }  
  31.         if (options != null) {  
  32.             data.writeInt(1);  
  33.             options.writeToParcel(data, 0);  
  34.         } else {  
  35.             data.writeInt(0);  
  36.         }  
  37.         mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);  
  38.         reply.readException();  
  39.         int result = reply.readInt();  
  40.         reply.recycle();  
  41.         data.recycle();  
  42.         return result;  
  43.     }  
  44.     public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,  
  45.             String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
  46.             int startFlags, ProfilerInfo profilerInfo, Bundle options,  
  47.             int userId) throws RemoteException {  
  48.         Parcel data = Parcel.obtain();  
  49.         Parcel reply = Parcel.obtain();  
  50.         data.writeInterfaceToken(IActivityManager.descriptor);  
  51.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
  52.         data.writeString(callingPackage);  
  53.         intent.writeToParcel(data, 0);  
  54.         data.writeString(resolvedType);  
  55.         data.writeStrongBinder(resultTo);  
  56.         data.writeString(resultWho);  
  57.         data.writeInt(requestCode);  
  58.         data.writeInt(startFlags);  
  59.         if (profilerInfo != null) {  
  60.             data.writeInt(1);  
  61.             profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);  
  62.         } else {  
  63.             data.writeInt(0);  
  64.         }  
  65.         if (options != null) {  
  66.             data.writeInt(1);  
  67.             options.writeToParcel(data, 0);  
  68.         } else {  
  69.             data.writeInt(0);  
  70.         }  
  71.         data.writeInt(userId);  
  72.         mRemote.transact(START_ACTIVITY_AS_USER_TRANSACTION, data, reply, 0);  
  73.         reply.readException();  
  74.         int result = reply.readInt();  
  75.         reply.recycle();  
  76.         data.recycle();  
  77.         return result;  
  78.           …………  
  79. }  

看到這就會發現,其實就是AIDL來進行程序間通信。它是真正實作類還應該是AMS中的 startActivity。 [java]  view plain  copy

  1. public int startActivity(IBinder whoThread, String callingPackage,  
  2.                Intent intent, String resolvedType, Bundle options) {  
  3.            checkCaller();  
  4.            int callingUser = UserHandle.getCallingUserId();  
  5.            TaskRecord tr;  
  6.            IApplicationThread appThread;  
  7.            synchronized (ActivityManagerService.this) {  
  8.                tr = recentTaskForIdLocked(mTaskId);  
  9.                if (tr == null) {  
  10.                    throw new IllegalArgumentException("Unable to find task ID " + mTaskId);  
  11.                }  
  12.                appThread = ApplicationThreadNative.asInterface(whoThread);  
  13.                if (appThread == null) {  
  14.                    throw new IllegalArgumentException("Bad app thread " + appThread);  
  15.                }  
  16.            }  
  17.            return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,  
  18.                    resolvedType, null, null, null, null, 0, 0, null, null,  
  19.                    null, options, callingUser, null, tr);  
  20.        }  

最後調用了   mStackSupervisor.startActivityMayWait,主要看兩部分: 1.解析Intent。

 下面語句對參數intent的内容進行解析,得到MainActivity的相關資訊,儲存在aInfo變量中:

[java]  view plain  copy

  1. ActivityInfo aInfo;    
  2.        try {    
  3.      ResolveInfo rInfo =    
  4.      AppGlobals.getPackageManager().resolveIntent(    
  5.          intent, resolvedType,    
  6.         PackageManager.MATCH_DEFAULT_ONLY    
  7.         | ActivityManagerService.STOCK_PM_FLAGS);    
  8.     aInfo = rInfo != null ? rInfo.activityInfo : null;    
  9.       } catch (RemoteException e) {    
  10.         ......    
  11.       }   

2.:調用 startActivityLocked。 [java]  view plain  copy

  1. int res = startActivityLocked(caller, intent, resolvedType, aInfo,  
  2.                     voiceSession, voiceInteractor, resultTo, resultWho,  
  3.                     requestCode, callingPid, callingUid, callingPackage,  
  4.                     realCallingPid, realCallingUid, startFlags, options,  
  5.                     componentSpecified, null, container, inTask);  

最的傳回了 startActivityLocked,它在 ActivityStackSupervisor 中,再看下它的代碼: [java]  view plain  copy

  1. final int startActivityLocked(IApplicationThread caller,  
  2.             Intent intent, String resolvedType, ActivityInfo aInfo,  
  3.             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,  
  4.             IBinder resultTo, String resultWho, int requestCode,  
  5.             int callingPid, int callingUid, String callingPackage,  
  6.             int realCallingPid, int realCallingUid, int startFlags, Bundle options,  
  7.             boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,  
  8.             TaskRecord inTask) {  
  9.         int err = ActivityManager.START_SUCCESS;  
  10.         ProcessRecord callerApp = null;  
  11.         if (caller != null) {  
  12.             callerApp = mService.getRecordForAppLocked(caller);  
  13.             if (callerApp != null) {  
  14.                 callingPid = callerApp.pid;  
  15.                 callingUid = callerApp.info.uid;  
  16.             } else {  
  17.                 Slog.w(TAG, "Unable to find app for caller " + caller  
  18.                       + " (pid=" + callingPid + ") when starting: "  
  19.                       + intent.toString());  
  20.                 err = ActivityManager.START_PERMISSION_DENIED;  
  21.             }  
  22.         }  
  23. …………  
  24.         ActivityRecord sourceRecord = null;  
  25.         ActivityRecord resultRecord = null;  
  26.         if (resultTo != null) {  
  27.             sourceRecord = isInAnyStackLocked(resultTo);  
  28.             if (DEBUG_RESULTS) Slog.v(  
  29.                 TAG, "Will send result to " + resultTo + " " + sourceRecord);  
  30.             if (sourceRecord != null) {  
  31.                 if (requestCode >= 0 && !sourceRecord.finishing) {  
  32.                     resultRecord = sourceRecord;  
  33.                 }  
  34.             }  
  35.         }  
  36.         final int launchFlags = intent.getFlags();  
  37.         if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {  
  38.             // Transfer the result target from the source activity to the new  
  39.             // one being started, including any failures.  
  40.             if (requestCode >= 0) {  
  41.                 ActivityOptions.abort(options);  
  42.                 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;  
  43.             }  
  44.             resultRecord = sourceRecord.resultTo;  
  45.             resultWho = sourceRecord.resultWho;  
  46.             requestCode = sourceRecord.requestCode;  
  47.             sourceRecord.resultTo = null;  
  48. …………  
  49.  ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,  
  50.                 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,  
  51.                 requestCode, componentSpecified, this, container, options);  
  52. ^………………  
  53.  err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,  
  54.                 startFlags, true, options, inTask);  

分三步: 1. 從傳進來的參數caller得到調用者的程序資訊,并儲存在callerApp變量中,這裡就是Launcher應用程式的程序資訊了。  前面說過,參數resultTo是Launcher這個Activity裡面的一個Binder對象,通過它可以獲得Launcher這個Activity的相關資訊,儲存在sourceRecord變量中。 2. 建立即将要啟動的Activity的相關資訊,并儲存在r變量中。 3.調用startActivityUncheckedLocked。startActivityUncheckedLocked的核心代碼如下: [java]  view plain  copy

  1. final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;  
  2.         final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;  
  3.         final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;  
  4.         int launchFlags = intent.getFlags();  
  5.         if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&  
  6.                 (launchSingleInstance || launchSingleTask)) {  
  7.             // We have a conflict between the Intent and the Activity manifest, manifest wins.  
  8.             Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +  
  9.                     "\"singleInstance\" or \"singleTask\"");  
  10.             launchFlags &=  
  11.                     ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);  
  12. …………  
  13.   if (doResume) {  
  14.                                 resumeTopActivitiesLocked();  
  15.                             }  
  16.                             ActivityOptions.abort(options);  

 函數首先獲得intent的标志值,儲存在launchFlags變量中。 。Activity的啟動方式有四種,接下來一系列判斷就是決定Activity四種不同啟動模式的啟動方式。然後判斷 目前要啟動的Activity是否就是目前堆棧頂端的Activity,如果是的話,在某些情況下,就不用再重新啟動了。 最後調用了 resumeTopActivitiesLocked,現在這個過程己經從ActivityStackSupervisor轉移到 ActivityStack。 [java]  view plain  copy

  1. final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {  
  2.        if (mStackSupervisor.inResumeTopActivity) {  
  3.            // Don't even start recursing.  
  4.            return false;  
  5.        }  
  6.        boolean result = false;  
  7.        try {  
  8.            // Protect against recursion.  
  9.            mStackSupervisor.inResumeTopActivity = true;  
  10.            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {  
  11.                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;  
  12.                mService.updateSleepIfNeededLocked();  
  13.            }  
  14.            result = resumeTopActivityInnerLocked(prev, options);  
  15.        } finally {  
  16.            mStackSupervisor.inResumeTopActivity = false;  
  17.        }  
  18.        return result;  
  19.    }  

通過上面的代碼可知, resumeTopActivitiesLocked調用了resumeTopActivityInnerLocked方法。來看下resumeTopActivityInnerLocked源代碼,由于這部分代碼很長,隻貼出它的最主要流程: [java]  view plain  copy

  1. if ((mService.mSleeping || mService.mShuttingDown)    
  2. <span style="white-space:pre">    </span>            && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {    
  3. <span style="white-space:pre">    </span>            ......    
  4. <span style="white-space:pre">    </span>             return false;    
  5. <span style="white-space:pre">    </span>         }    
  6.          .......      
  7. <span style="white-space:pre">    </span>         // We need to start pausing the current activity so the top one    
  8. <span style="white-space:pre">    </span>         // can be resumed...    
  9. <span style="white-space:pre">    </span>         if (mResumedActivity != null) {    
  10. <span style="white-space:pre">    </span>          if (mResumedActivity != null) {  
  11.            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);  
  12.             pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);  
  13.         }  
  14. <span style="white-space:pre">    </span>             return true;    
  15. <span style="white-space:pre">    </span>        }      
  16. <span style="white-space:pre">    </span>         ......       
  17. <span style="white-space:pre">    </span>         if (next.app != null && next.app.thread != null) {    
  18. <span style="white-space:pre">    </span>             ......       
  19. <span style="white-space:pre">    </span>         } else {    
  20. <span style="white-space:pre">    </span>           ......    
  21. <span style="white-space:pre">    </span>            startSpecificActivityLocked(next, true, true);    
  22. <span style="white-space:pre">    </span>        }       
  23. <span style="white-space:pre">    </span>         return true;    
  24. <span style="white-space:pre">    </span>    }   

由上可以清晰的看到,如果目前activity沒暫停,要先把它暫停。

二.暫停目前Activity

上面己經分析到新Activity啟動會先把之前的Activity暫停,具體是調用startPausingLocked方法。它的核心代碼如下: [java]  view plain  copy

  1. if (prev.app != null && prev.app.thread != null) {  
  2.            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);  
  3.            try {  
  4.                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,  
  5.                        prev.userId, System.identityHashCode(prev),  
  6.                        prev.shortComponentName);  
  7.                mService.updateUsageStats(prev, false);  
  8.                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,  
  9.                        userLeaving, prev.configChangeFlags, dontWait);  

prev.app.thread是一個ApplicationThread對象的遠端接口,它的類型是IApplicationThread。 通過調用這個遠端接口的schedulePauseActivity來通知Activity進入Paused狀态。先看下IApplicationThread接口。 [java]  view plain  copy

  1. public interface IApplicationThread extends IInterface {  
  2.     void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,  
  3.             int configChanges, boolean dontReport) throws RemoteException;  
  4.     void scheduleStopActivity(IBinder token, boolean showWindow,  
  5.             int configChanges) throws RemoteException;  
  6.     void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;  
  7.     void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;  
  8.     void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)  
  9.             throws RemoteException;  
  10.     void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;  
  11.     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
  12.             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,  
  13.             String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,  
  14.             PersistableBundle persistentState, List<ResultInfo> pendingResults,  
  15.             List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,  
  16.             ProfilerInfo profilerInfo) throws RemoteException;  
  17.     void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,  
  18.             List<ReferrerIntent> pendingNewIntents, int configChanges,  
  19.             boolean notResumed, Configuration config) throws RemoteException;  
  20.     void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;  
  21.     void scheduleDestroyActivity(IBinder token, boolean finished,  
  22.             int configChanges) throws RemoteException;  
  23.     void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,  
  24.             int resultCode, String data, Bundle extras, boolean sync,  
  25.             int sendingUser, int processState) throws RemoteException;  
  26.     static final int BACKUP_MODE_INCREMENTAL = 0;  
  27.     static final int BACKUP_MODE_FULL = 1;  
  28.     static final int BACKUP_MODE_RESTORE = 2;  
  29.     static final int BACKUP_MODE_RESTORE_FULL = 3;  
  30.     void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,  
  31.             int backupMode) throws RemoteException;  
  32.     void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)  
  33.             throws RemoteException;  
  34.     void scheduleCreateService(IBinder token, ServiceInfo info,  
  35.             CompatibilityInfo compatInfo, int processState) throws RemoteException;  
  36.     void scheduleBindService(IBinder token,  
  37.             Intent intent, boolean rebind, int processState) throws RemoteException;  
  38.     void scheduleUnbindService(IBinder token,  
  39.             Intent intent) throws RemoteException;  
  40.     void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,  
  41.             int flags, Intent args) throws RemoteException;  
  42.     void scheduleStopService(IBinder token) throws RemoteException;  
  43.     static final int DEBUG_OFF = 0;  
  44.     static final int DEBUG_ON = 1;  
  45.     static final int DEBUG_WAIT = 2;  
  46.     void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,  
  47.             ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,  
  48.             IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,  
  49.             int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,  
  50.             Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,  
  51.             Bundle coreSettings) throws RemoteException;  
  52.     void scheduleExit() throws RemoteException;  
  53.     void scheduleSuicide() throws RemoteException;  
  54.     void scheduleConfigurationChanged(Configuration config) throws RemoteException;  
  55.     void updateTimeZone() throws RemoteException;  
  56.     void clearDnsCache() throws RemoteException;  
  57.     void setHttpProxy(String proxy, String port, String exclList,  
  58.             Uri pacFileUrl) throws RemoteException;  
  59.     void processInBackground() throws RemoteException;  
  60.     void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)  
  61.             throws RemoteException;  
  62.     void dumpProvider(FileDescriptor fd, IBinder servicetoken, String[] args)  
  63.             throws RemoteException;  
  64.     void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,  
  65.             int resultCode, String data, Bundle extras, boolean ordered,  
  66.             boolean sticky, int sendingUser, int processState) throws RemoteException;  
  67.     void scheduleLowMemory() throws RemoteException;  
  68.     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;  
  69.     void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType)  
  70.             throws RemoteException;  
  71.     void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)  
  72.             throws RemoteException;  

由此猜測它與activity,service的開啟有關。IApplicationThread這個IBind實作者完成了大量和Activity以及service有關的功能。 而ApplicationThreadNative就是它的實作類。 [java]  view plain  copy

  1. public abstract class ApplicationThreadNative extends Binder  
  2.         implements IApplicationThread {  
  3.     static public IApplicationThread asInterface(IBinder obj) {  
  4.         if (obj == null) {  
  5.             return null;  
  6.         }  
  7.         IApplicationThread in =  
  8.             (IApplicationThread)obj.queryLocalInterface(descriptor);  
  9.         if (in != null) {  
  10.             return in;  
  11.         }  
  12.         return new ApplicationThreadProxy(obj);  
  13.     }  
  14.     public ApplicationThreadNative() {  
  15.         attachInterface(this, descriptor);  
  16.     }  
  17.     @Override  
  18.     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)  
  19.             throws RemoteException {  
  20.         switch (code) {  
  21.         case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:  
  22.         {  
  23.             data.enforceInterface(IApplicationThread.descriptor);  
  24.             IBinder b = data.readStrongBinder();  
  25.             boolean finished = data.readInt() != 0;  
  26.             boolean userLeaving = data.readInt() != 0;  
  27.             int configChanges = data.readInt();  
  28.             boolean dontReport = data.readInt() != 0;  
  29.             schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport);  
  30.             return true;  
  31.         }  

[java]  view plain  copy

  1. <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,  
  2.             boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {  
  3.         Parcel data = Parcel.obtain();  
  4.         data.writeInterfaceToken(IApplicationThread.descriptor);  
  5.         data.writeStrongBinder(token);  
  6.         data.writeInt(finished ? 1 : 0);  
  7.         data.writeInt(userLeaving ? 1 :0);  
  8.         data.writeInt(configChanges);  
  9.         data.writeInt(dontReport ? 1 : 0);  
  10.         mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,  
  11.                 IBinder.FLAG_ONEWAY);  
  12.         data.recycle();  
  13.     }  

………………}

由上可見它就是一個Binder抽象類, ApplicationThreadProxy是代理類。真正實作類是ApplicationThread。直接看 ApplicationThread的 schedulePauseActivity方法。 [java]  view plain  copy

  1. public final void schedulePauseActivity(IBinder token, boolean finished,  
  2.                boolean userLeaving, int configChanges, boolean dontReport) {  
  3.            sendMessage(  
  4.                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,  
  5.                    token,  
  6.                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),  
  7.                    configChanges);  
  8.        }  

看到這,就知道接下來肯定是用Handler來發送消息了,發送消息的代碼如下: [java]  view plain  copy

  1. private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {  
  2.         if (DEBUG_MESSAGES) Slog.v(  
  3.             TAG, "SCHEDULE " + what + " " + mH.codeToString(what)  
  4.             + ": " + arg1 + " / " + obj);  
  5.         Message msg = Message.obtain();  
  6.         msg.what = what;  
  7.         msg.obj = obj;  
  8.         msg.arg1 = arg1;  
  9.         msg.arg2 = arg2;  
  10.         if (async) {  
  11.             msg.setAsynchronous(true);  
  12.         }  
  13.         mH.sendMessage(msg);  
  14.     }  

就是在發送一個暫停Activity的消息給Handler處理,這個Handler名字為H。H在它的handlerMessage中處理相應的請求,它的實作如下: [java]  view plain  copy

  1.  public void handleMessage(Message msg) {  
  2.             switch (msg.what) {  
  3.              …………  
  4.                 case PAUSE_ACTIVITY:  
  5.                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");  
  6.                     handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,  
  7.                             (msg.arg1&2) != 0);  
  8.                     maybeSnapshot();  
  9.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  10.                     break;  
  11. …………  
  12. }  

看下handlePauseActivity的代碼: [java]  view plain  copy

  1. private void handlePauseActivity(IBinder token, boolean finished,  
  2.             boolean userLeaving, int configChanges, boolean dontReport) {  
  3.         ActivityClientRecord r = mActivities.get(token);  
  4.         if (r != null) {  
  5.             //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);  
  6.             if (userLeaving) {  
  7.                 performUserLeavingActivity(r);  
  8.             }  
  9.             r.activity.mConfigChangeFlags |= configChanges;  
  10.             performPauseActivity(token, finished, r.isPreHoneycomb());  
  11.             // Make sure any pending writes are now committed.  
  12.             if (r.isPreHoneycomb()) {  
  13.                 QueuedWork.waitToFinish();  
  14.             }  
  15.             // Tell the activity manager we have paused.  
  16.             if (!dontReport) {  
  17.                 try {  
  18.                     ActivityManagerNative.getDefault().activityPaused(token);  
  19.                 } catch (RemoteException ex) {  
  20.                 }  
  21.             }  
  22.             mSomeActivitiesChanged = true;  
  23.         }  

  函數首先将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的代碼: [java]  view plain  copy

  1. public final void activityPaused(IBinder token) {  
  2.         final long origId = Binder.clearCallingIdentity();  
  3.         synchronized(this) {  
  4.             ActivityStack stack = ActivityRecord.getStackLocked(token);  
  5.             if (stack != null) {  
  6.                 stack.activityPausedLocked(token, false);  
  7.             }  
  8.         }  
  9.         Binder.restoreCallingIdentity(origId);  
  10.     }  

繞了一大圈又回到了ActivityStack中,調用它的activityPauseLocked方法。

[java]  view plain  copy

  1. final void activityPausedLocked(IBinder token, boolean timeout) {  
  2.        if (DEBUG_PAUSE) Slog.v(  
  3.            TAG, "Activity paused: token=" + token + ", timeout=" + timeout);  
  4.        final ActivityRecord r = isInStackLocked(token);  
  5.        if (r != null) {  
  6.            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);  
  7.            if (mPausingActivity == r) {  
  8.                if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r  
  9.                        + (timeout ? " (due to timeout)" : " (pause complete)"));  
  10.                completePauseLocked(true);  
  11.            } else {  
  12.                EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,  
  13.                        r.userId, System.identityHashCode(r), r.shortComponentName,  
  14.                        mPausingActivity != null  
  15.                            ? mPausingActivity.shortComponentName : "(none)");  
  16.            }  
  17.        }  
  18.    }  

前一個Activity的資訊儲存在mPausingActivity中,是以,這裡mPausingActivity等于r,于是,執行completePauseLocked操作。 [java]  view plain  copy

  1.  private void completePauseLocked(boolean resumeNext) {  
  2. …………  
  3.    if (resumeNext) {  
  4.             final ActivityStack topStack = mStackSupervisor.getFocusedStack();  
  5.             if (!mService.isSleepingOrShuttingDown()) {  
  6.                 mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);  
  7.             } else {  
  8.                 mStackSupervisor.checkReadyForSleepLocked();  
  9.                 ActivityRecord top = topStack.topRunningActivityLocked(null);  
  10.                 if (top == null || (prev != null && top != prev)) {  
  11.                     // If there are no more activities available to run,  
  12.                     // do resume anyway to start something.  Also if the top  
  13.                     // activity on the stack is not the just paused activity,  
  14.                     // we need to go ahead and resume it to ensure we complete  
  15.                     // an in-flight app switch.  
  16.                     mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);  
  17.                 }  
  18.             }  
  19.         }  
  20. …………  
  21. }  

很顯然,又回到了resumeTopActivitiesLocked中,這次activity己經停止,是以它 調用了ActivityStackSupervisor的StartSpecificActivityLocked方法。

三,啟動Activity

其實啟動Activity與暫停很類似,都是在ApplicationThread中實作的,看代碼: [java]  view plain  copy

  1. void startSpecificActivityLocked(ActivityRecord r,  
  2.            boolean andResume, boolean checkConfig) {  
  3.        // Is this activity's application already running?  
  4.        ProcessRecord app = mService.getProcessRecordLocked(r.processName,  
  5.                r.info.applicationInfo.uid, true);  
  6.        r.task.stack.setLaunchTime(r);  
  7.        if (app != null && app.thread != null) {  
  8.            try {  
  9.                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0  
  10.                        || !"android".equals(r.info.packageName)) {  
  11.                    // Don't add this if it is a platform component that is marked  
  12.                    // to run in multiple processes, because this is actually  
  13.                    // part of the framework so doesn't make sense to track as a  
  14.                    // separate apk in the process.  
  15.                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,  
  16.                            mService.mProcessStats);  
  17.                }  
  18.                realStartActivityLocked(r, app, andResume, checkConfig);  
  19.                return;  
  20.            } catch (RemoteException e) {  
  21.                Slog.w(TAG, "Exception when starting activity "  
  22.                        + r.intent.getComponent().flattenToShortString(), e);  
  23.            }  
  24.            // If a dead object exception was thrown -- fall through to  
  25.            // restart the application.  
  26.        }  
  27.        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,  
  28.                "activity", r.intent.getComponent(), false, false, true);  
  29.   }   

接下來重點看下 realStartActivityLocked,它代碼中有以下一段 [java]  view plain  copy

  1. app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,  
  2.                     System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),  
  3.                     r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,  
  4.                     r.icicle, r.persistentState, results, newIntents, !andResume,  
  5.                     mService.isNextTransitionForward(), profilerInfo);  

是不是有種似曾相識的感覺。接下來就是跟暫停一樣了,調用 ApplicationThread中的scheduleLaunchActivity,最終調用H中的HandlerMessage。 [java]  view plain  copy

  1. public void handleMessage(Message msg) {  
  2.             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
  3.             switch (msg.what) {  
  4.                 case LAUNCH_ACTIVITY: {  
  5.                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");  
  6.                     final ActivityClientRecord r = (ActivityClientRecord) msg.obj;  
  7.                     r.packageInfo = getPackageInfoNoCheck(  
  8.                             r.activityInfo.applicationInfo, r.compatInfo);  
  9.                     handleLaunchActivity(r, null);  
  10.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  11.                 } break;  
  12.           ………………  

再看下handleLaunchActivity()的實作,代碼比較長,隻看核心的。 [java]  view plain  copy

  1. if (localLOGV) Slog.v(  
  2.            TAG, "Handling launch of " + r);  
  3.        // Initialize before creating the activity  
  4.        WindowManagerGlobal.initialize();  
  5.        Activity a = performLaunchActivity(r, customIntent);  
  6.        if (a != null) {  
  7.            r.createdConfig = new Configuration(mConfiguration);  
  8.            Bundle oldState = r.state;  
  9.            handleResumeActivity(r.token, false, r.isForward,  
  10.                    !r.activity.mFinished && !r.startsNotResumed);  

performLaunchAcitvity中調用Activity的onCreate(),onStart()方法,handlerResumeActivity調用onResume()方法。重點看下 performLaunchAcitvity, 我們 把它拆分來看,它總共完成以下幾個功能。 1.從ActivityClientRecord中擷取待啟動的Activity的元件資訊 [java]  view plain  copy

  1. ActivityInfo aInfo = r.activityInfo;  
  2.         if (r.packageInfo == null) {  
  3.             r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,  
  4.                     Context.CONTEXT_INCLUDE_CODE);  
  5.         }  
  6.         ComponentName component = r.intent.getComponent();  
  7.         if (component == null) {  
  8.             component = r.intent.resolveActivity(  
  9.                 mInitialApplication.getPackageManager());  
  10.             r.intent.setComponent(component);  
  11.         }  
  12.         if (r.activityInfo.targetActivity != null) {  
  13.             component = new ComponentName(r.activityInfo.packageName,  
  14.                     r.activityInfo.targetActivity);  
  15.         }  

2.通過Instrumentation 的newActivity方法使用類加載器建立Activity對象 [java]  view plain  copy

  1. Activity activity = null;  
  2.         try {  
  3.             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
  4.             activity = mInstrumentation.newActivity(  
  5.                     cl, component.getClassName(), r.intent);  
  6.             StrictMode.incrementExpectedActivityCount(activity.getClass());  
  7.             r.intent.setExtrasClassLoader(cl);  
  8.             r.intent.prepareToEnterProcess();  
  9.             if (r.state != null) {  
  10.                 r.state.setClassLoader(cl);  
  11.             }  
  12.         } catch (Exception e) {  
  13.             if (!mInstrumentation.onException(activity, e)) {  
  14.                 throw new RuntimeException(  
  15.                     "Unable to instantiate activity " + component  
  16.                     + ": " + e.toString(), e);  
  17.             }  
  18.         }  

重點實作在newActivity中 [java]  view plain  copy

  1. public Activity newActivity(ClassLoader cl, String className,  
  2.             Intent intent)  
  3.             throws InstantiationException, IllegalAccessException,  
  4.             ClassNotFoundException {  
  5.         return (Activity)cl.loadClass(className).newInstance();  
  6.     }  

3.通過LoadedApk的makeApplication方法來嘗試建立Application [java]  view plain  copy

  1. public Application makeApplication(boolean forceDefaultAppClass,  
  2.            Instrumentation instrumentation) {  
  3.        if (mApplication != null) {  
  4.            return mApplication;  
  5.        }  
  6.        Application app = null;  
  7.        String appClass = mApplicationInfo.className;  
  8.        if (forceDefaultAppClass || (appClass == null)) {  
  9.            appClass = "android.app.Application";  
  10.        }  
  11.        try {  
  12.            java.lang.ClassLoader cl = getClassLoader();  
  13.            if (!mPackageName.equals("android")) {  
  14.                initializeJavaContextClassLoader();  
  15.            }  
  16.            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);  
  17.            app = mActivityThread.mInstrumentation.newApplication(  
  18.                    cl, appClass, appContext);  
  19.            appContext.setOuterContext(app);  
  20.        } catch (Exception e) {  
  21.            if (!mActivityThread.mInstrumentation.onException(app, e)) {  
  22.                throw new RuntimeException(  
  23.                    "Unable to instantiate application " + appClass  
  24.                    + ": " + e.toString(), e);  
  25.            }  
  26.        }  
  27.        mActivityThread.mAllApplications.add(app);  
  28.        mApplication = app;  
  29.        if (instrumentation != null) {  
  30.            try {  
  31.                instrumentation.callApplicationOnCreate(app);  
  32.            } catch (Exception e) {  
  33.                if (!instrumentation.onException(app, e)) {  
  34.                    throw new RuntimeException(  
  35.                        "Unable to create application " + app.getClass().getName()  
  36.                        + ": " + e.toString(), e);  
  37.                }  
  38.            }  
  39.        }  
  40. ………  

如果Application被建立了,就不會再重複建立了。這也意味着一個應用隻有一個Application,它的建立是通過Instrumentation來完成的。通過類加載載來實作。建立完通過callApplicationOnCreate來調用Application的onCreate()方法。 4,建立ContextImpl對象并通過Activity的attach方法來完成一些重要資料的初始化。 [java]  view plain  copy

  1. Context appContext = createBaseContextForActivity(r, activity);  
  2.                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());  
  3.                Configuration config = new Configuration(mCompatConfiguration);  
  4.                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "  
  5.                        + r.activityInfo.name + " with config " + config);  
  6.                activity.attach(appContext, this, getInstrumentation(), r.token,  
  7.                        r.ident, app, r.intent, r.activityInfo, title, r.parent,  
  8.                        r.embeddedID, r.lastNonConfigurationInstances, config,  
  9.                        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的啟動操作了。

現在再回頭去看下那個啟動圖,應該大部分能看懂了。

目錄(?)[+]

其實寫分析源碼文章總會顯得很複雜很乏味,但是梳理自己看源碼時的一些總結也是一種提高。這篇部落格分析下Activity啟動過程源碼,我會盡量說得簡單點。個人的觀點是看源碼不能看得太細,否則就會花費很多時間并很難理清整個過程。是以本次分析重在理清activity的一個啟動流程。

首先大概總結下activity啟動的整個流程,這個過程涉及到Instrumentation,ActivityThread,和ActivityManagerService(AMS)。通過Binder向AMS發請求,AMS内部有一個ActivityStack,它負責棧内的Activity同步,AMS去通過ActivityThread去調用Activity的生命周期方法完成Activity的啟動。如果對Binder程序間通信不了解可看下IPC——android程序間通信

先上一張總圖,等看完部落格可以再回頭來看下這圖:

Activity啟動過程源碼分析一.啟動預處理二.暫停目前Activity三,啟動Activity四,總結 一.啟動預處理二.暫停目前Activity三,啟動Activity四,總結 

一.啟動預處理

啟動一個activity最常用的方法就是startActivityForResult或者startActivity,而startActivity也是調用startActivityForResult,是以此次分析入口當然是startActivityForResult。

[java]  view plain  copy

  1. public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {  
  2.     if (mParent == null) {  
  3.         Instrumentation.ActivityResult ar =  
  4.             mInstrumentation .execStartActivity(  
  5.                 this, mMainThread .getApplicationThread() , mToken, this,  
  6.                 intent, requestCode, options) ;  
  7.         if (ar != null) {  
  8.             mMainThread .sendActivityResult(  
  9.                 mToken, mEmbeddedID, requestCode , ar.getResultCode(),  
  10.                 ar.getResultData());  
  11.         }  
  12.         if (requestCode >= 0) {  
  13.             // If this start is requesting a result, we can avoid making  
  14.             // the activity visible until the result is received.  Setting  
  15.             // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the  
  16.             // activity hidden during this time, to avoid flickering.  
  17.             // This can only be done when a result is requested because  
  18.             // that guarantees we will get information back when the  
  19.             // activity is finished, no matter what happens to it.  
  20.             mStartedActivity = true;  
  21.         }  
  22.         final View decor = mWindow != null ? mWindow .peekDecorView() : null;  
  23.         if (decor != null) {  
  24.             decor.cancelPendingInputEvents();  
  25.         }  
  26.         // TODO Consider clearing/flushing other event sources and events for child windows.  
  27.     } else {  
  28.         if (options != null) {  
  29.             mParent .startActivityFromChild( this, intent, requestCode, options) ;  
  30.         } else {  
  31.             // Note we want to go through this method for compatibility with  
  32.             // existing applications that may have overridden it.  
  33.             mParent .startActivityFromChild( this, intent, requestCode);  
  34.         }  
  35.     }  
  36.     if (options != null && !isTopOfTask()) {  
  37.         mActivityTransitionState .startExitOutTransition( this, options);  
  38.     }  
  39. }  

Intrumentation它用來監控應用程式和系統的互動。而mMainThread.getApplicationThread()擷取ApplicationThread,它是ActivityThread的一個内部類, 是一個Binder對象,後面我們會看到,ActivityManagerService會使用它來和ActivityThread來進行程序間通信。上面的代碼最終調用了 execStartActivity方法。 [java]  view plain  copy

  1. public ActivityResult execStartActivity(  
  2.         Context who, IBinder contextThread, IBinder token , Activity target,  
  3.         Intent intent , int requestCode, Bundle options) {  
  4.     IApplicationThread whoThread = (IApplicationThread) contextThread;  
  5.     if ( mActivityMonitors != null ) {  
  6.         synchronized (mSync) {  
  7.             final int N = mActivityMonitors.size() ;  
  8.             for ( int i=0 ; i<N; i++) {  
  9.                 final ActivityMonitor am = mActivityMonitors.get(i);  
  10.                 if (am.match(who, null, intent)) {  
  11.                     am. mHits++;  
  12.                     if (am.isBlocking()) {  
  13.                         return requestCode >= 0 ? am.getResult() : null;  
  14.                     }  
  15.                     break;  
  16.                 }  
  17.             }  
  18.         }  
  19.     }  
  20.     try {  
  21.         intent.migrateExtraStreamToClipData();  
  22.         intent.prepareToLeaveProcess() ;  
  23.         int result = ActivityManagerNative. getDefault()  
  24.             .startActivity(whoThread, who.getBasePackageName() , intent,  
  25.                     intent.resolveTypeIfNeeded(who.getContentResolver()),  
  26.                     token, target != null ? target.mEmbeddedID : null,  
  27.                     requestCode, 0, null, options) ;  
  28.         checkStartActivityResult(result, intent) ;  
  29.     } catch (RemoteException e) {  
  30.     }  
  31.     return null;  
  32. }  

這裡的intent.resolveTypeIfNeeded傳回這個intent的MIME類型,如果沒有在AndroidManifest.xml設定MainActivity的MIME類型那就傳回null。 啟動的真正實作類由ActivityManagerNative.getDefault()的startActivity方法完成。先分析下ActivityManagerNative.getDefault()。 [java]  view plain  copy

  1. public abstract class ActivityManagerNative extends Binder implements IActivityManager{  
  2. …………  
  3. private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {  
  4.     protected IActivityManager create() {  
  5.         IBinder b = ServiceManager.getService("activity") ;  
  6.         if ( false) {  
  7.             Log.v ("ActivityManager" , "default service binder = " + b);  
  8.         }  
  9.         IActivityManager am = asInterface (b);  
  10.         if ( false) {  
  11.             Log.v ("ActivityManager" , "default service = " + am);  
  12.         }  
  13.         return am;  
  14.     }  
  15. };  
  16. }  

可以看到 ActivityManagerNative是一個抽象類,它繼承Binder,并實作了IActivityManager接口,ActivityManagerService(下稱AMS)繼承着ActivityManagerNative,是以它是IActivityManager的具體實作類。ActivityManagerNative.getDefault是一個IActivityManager類型的Binder對象,是以它的具體實作是AMS。擷取的AMS的Binder對象是一個單例。 ActivityManagerNative就相當于AIDL檔案自動生成的那個類。ActivityManagerProxy是ActivityManagerNative中的一個代理方法,看下它的startActivity代碼:

[java]  view plain  copy

  1. class ActivityManagerProxy implements IActivityManager  
  2. {  
  3.     public ActivityManagerProxy(IBinder remote)  
  4.     {  
  5.         mRemote = remote;  
  6.     }  
  7.     public IBinder asBinder()  
  8.     {  
  9.         return mRemote;  
  10.     }  
  11.     public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,  
  12.             String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
  13.             int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {  
  14.         Parcel data = Parcel.obtain();  
  15.         Parcel reply = Parcel.obtain();  
  16.         data.writeInterfaceToken(IActivityManager.descriptor);  
  17.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
  18.         data.writeString(callingPackage);  
  19.         intent.writeToParcel(data, 0);  
  20.         data.writeString(resolvedType);  
  21.         data.writeStrongBinder(resultTo);  
  22.         data.writeString(resultWho);  
  23.         data.writeInt(requestCode);  
  24.         data.writeInt(startFlags);  
  25.         if (profilerInfo != null) {  
  26.             data.writeInt(1);  
  27.             profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);  
  28.         } else {  
  29.             data.writeInt(0);  
  30.         }  
  31.         if (options != null) {  
  32.             data.writeInt(1);  
  33.             options.writeToParcel(data, 0);  
  34.         } else {  
  35.             data.writeInt(0);  
  36.         }  
  37.         mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);  
  38.         reply.readException();  
  39.         int result = reply.readInt();  
  40.         reply.recycle();  
  41.         data.recycle();  
  42.         return result;  
  43.     }  
  44.     public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,  
  45.             String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
  46.             int startFlags, ProfilerInfo profilerInfo, Bundle options,  
  47.             int userId) throws RemoteException {  
  48.         Parcel data = Parcel.obtain();  
  49.         Parcel reply = Parcel.obtain();  
  50.         data.writeInterfaceToken(IActivityManager.descriptor);  
  51.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
  52.         data.writeString(callingPackage);  
  53.         intent.writeToParcel(data, 0);  
  54.         data.writeString(resolvedType);  
  55.         data.writeStrongBinder(resultTo);  
  56.         data.writeString(resultWho);  
  57.         data.writeInt(requestCode);  
  58.         data.writeInt(startFlags);  
  59.         if (profilerInfo != null) {  
  60.             data.writeInt(1);  
  61.             profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);  
  62.         } else {  
  63.             data.writeInt(0);  
  64.         }  
  65.         if (options != null) {  
  66.             data.writeInt(1);  
  67.             options.writeToParcel(data, 0);  
  68.         } else {  
  69.             data.writeInt(0);  
  70.         }  
  71.         data.writeInt(userId);  
  72.         mRemote.transact(START_ACTIVITY_AS_USER_TRANSACTION, data, reply, 0);  
  73.         reply.readException();  
  74.         int result = reply.readInt();  
  75.         reply.recycle();  
  76.         data.recycle();  
  77.         return result;  
  78.           …………  
  79. }  

看到這就會發現,其實就是AIDL來進行程序間通信。它是真正實作類還應該是AMS中的 startActivity。 [java]  view plain  copy

  1. public int startActivity(IBinder whoThread, String callingPackage,  
  2.                Intent intent, String resolvedType, Bundle options) {  
  3.            checkCaller();  
  4.            int callingUser = UserHandle.getCallingUserId();  
  5.            TaskRecord tr;  
  6.            IApplicationThread appThread;  
  7.            synchronized (ActivityManagerService.this) {  
  8.                tr = recentTaskForIdLocked(mTaskId);  
  9.                if (tr == null) {  
  10.                    throw new IllegalArgumentException("Unable to find task ID " + mTaskId);  
  11.                }  
  12.                appThread = ApplicationThreadNative.asInterface(whoThread);  
  13.                if (appThread == null) {  
  14.                    throw new IllegalArgumentException("Bad app thread " + appThread);  
  15.                }  
  16.            }  
  17.            return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,  
  18.                    resolvedType, null, null, null, null, 0, 0, null, null,  
  19.                    null, options, callingUser, null, tr);  
  20.        }  

最後調用了   mStackSupervisor.startActivityMayWait,主要看兩部分: 1.解析Intent。

 下面語句對參數intent的内容進行解析,得到MainActivity的相關資訊,儲存在aInfo變量中:

[java]  view plain  copy

  1. ActivityInfo aInfo;    
  2.        try {    
  3.      ResolveInfo rInfo =    
  4.      AppGlobals.getPackageManager().resolveIntent(    
  5.          intent, resolvedType,    
  6.         PackageManager.MATCH_DEFAULT_ONLY    
  7.         | ActivityManagerService.STOCK_PM_FLAGS);    
  8.     aInfo = rInfo != null ? rInfo.activityInfo : null;    
  9.       } catch (RemoteException e) {    
  10.         ......    
  11.       }   

2.:調用 startActivityLocked。 [java]  view plain  copy

  1. int res = startActivityLocked(caller, intent, resolvedType, aInfo,  
  2.                     voiceSession, voiceInteractor, resultTo, resultWho,  
  3.                     requestCode, callingPid, callingUid, callingPackage,  
  4.                     realCallingPid, realCallingUid, startFlags, options,  
  5.                     componentSpecified, null, container, inTask);  

最的傳回了 startActivityLocked,它在 ActivityStackSupervisor 中,再看下它的代碼: [java]  view plain  copy

  1. final int startActivityLocked(IApplicationThread caller,  
  2.             Intent intent, String resolvedType, ActivityInfo aInfo,  
  3.             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,  
  4.             IBinder resultTo, String resultWho, int requestCode,  
  5.             int callingPid, int callingUid, String callingPackage,  
  6.             int realCallingPid, int realCallingUid, int startFlags, Bundle options,  
  7.             boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,  
  8.             TaskRecord inTask) {  
  9.         int err = ActivityManager.START_SUCCESS;  
  10.         ProcessRecord callerApp = null;  
  11.         if (caller != null) {  
  12.             callerApp = mService.getRecordForAppLocked(caller);  
  13.             if (callerApp != null) {  
  14.                 callingPid = callerApp.pid;  
  15.                 callingUid = callerApp.info.uid;  
  16.             } else {  
  17.                 Slog.w(TAG, "Unable to find app for caller " + caller  
  18.                       + " (pid=" + callingPid + ") when starting: "  
  19.                       + intent.toString());  
  20.                 err = ActivityManager.START_PERMISSION_DENIED;  
  21.             }  
  22.         }  
  23. …………  
  24.         ActivityRecord sourceRecord = null;  
  25.         ActivityRecord resultRecord = null;  
  26.         if (resultTo != null) {  
  27.             sourceRecord = isInAnyStackLocked(resultTo);  
  28.             if (DEBUG_RESULTS) Slog.v(  
  29.                 TAG, "Will send result to " + resultTo + " " + sourceRecord);  
  30.             if (sourceRecord != null) {  
  31.                 if (requestCode >= 0 && !sourceRecord.finishing) {  
  32.                     resultRecord = sourceRecord;  
  33.                 }  
  34.             }  
  35.         }  
  36.         final int launchFlags = intent.getFlags();  
  37.         if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {  
  38.             // Transfer the result target from the source activity to the new  
  39.             // one being started, including any failures.  
  40.             if (requestCode >= 0) {  
  41.                 ActivityOptions.abort(options);  
  42.                 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;  
  43.             }  
  44.             resultRecord = sourceRecord.resultTo;  
  45.             resultWho = sourceRecord.resultWho;  
  46.             requestCode = sourceRecord.requestCode;  
  47.             sourceRecord.resultTo = null;  
  48. …………  
  49.  ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,  
  50.                 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,  
  51.                 requestCode, componentSpecified, this, container, options);  
  52. ^………………  
  53.  err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,  
  54.                 startFlags, true, options, inTask);  

分三步: 1. 從傳進來的參數caller得到調用者的程序資訊,并儲存在callerApp變量中,這裡就是Launcher應用程式的程序資訊了。  前面說過,參數resultTo是Launcher這個Activity裡面的一個Binder對象,通過它可以獲得Launcher這個Activity的相關資訊,儲存在sourceRecord變量中。 2. 建立即将要啟動的Activity的相關資訊,并儲存在r變量中。 3.調用startActivityUncheckedLocked。startActivityUncheckedLocked的核心代碼如下: [java]  view plain  copy

  1. final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;  
  2.         final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;  
  3.         final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;  
  4.         int launchFlags = intent.getFlags();  
  5.         if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&  
  6.                 (launchSingleInstance || launchSingleTask)) {  
  7.             // We have a conflict between the Intent and the Activity manifest, manifest wins.  
  8.             Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +  
  9.                     "\"singleInstance\" or \"singleTask\"");  
  10.             launchFlags &=  
  11.                     ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);  
  12. …………  
  13.   if (doResume) {  
  14.                                 resumeTopActivitiesLocked();  
  15.                             }  
  16.                             ActivityOptions.abort(options);  

 函數首先獲得intent的标志值,儲存在launchFlags變量中。 。Activity的啟動方式有四種,接下來一系列判斷就是決定Activity四種不同啟動模式的啟動方式。然後判斷 目前要啟動的Activity是否就是目前堆棧頂端的Activity,如果是的話,在某些情況下,就不用再重新啟動了。 最後調用了 resumeTopActivitiesLocked,現在這個過程己經從ActivityStackSupervisor轉移到 ActivityStack。 [java]  view plain  copy

  1. final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {  
  2.        if (mStackSupervisor.inResumeTopActivity) {  
  3.            // Don't even start recursing.  
  4.            return false;  
  5.        }  
  6.        boolean result = false;  
  7.        try {  
  8.            // Protect against recursion.  
  9.            mStackSupervisor.inResumeTopActivity = true;  
  10.            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {  
  11.                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;  
  12.                mService.updateSleepIfNeededLocked();  
  13.            }  
  14.            result = resumeTopActivityInnerLocked(prev, options);  
  15.        } finally {  
  16.            mStackSupervisor.inResumeTopActivity = false;  
  17.        }  
  18.        return result;  
  19.    }  

通過上面的代碼可知, resumeTopActivitiesLocked調用了resumeTopActivityInnerLocked方法。來看下resumeTopActivityInnerLocked源代碼,由于這部分代碼很長,隻貼出它的最主要流程: [java]  view plain  copy

  1. if ((mService.mSleeping || mService.mShuttingDown)    
  2. <span style="white-space:pre">    </span>            && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {    
  3. <span style="white-space:pre">    </span>            ......    
  4. <span style="white-space:pre">    </span>             return false;    
  5. <span style="white-space:pre">    </span>         }    
  6.          .......      
  7. <span style="white-space:pre">    </span>         // We need to start pausing the current activity so the top one    
  8. <span style="white-space:pre">    </span>         // can be resumed...    
  9. <span style="white-space:pre">    </span>         if (mResumedActivity != null) {    
  10. <span style="white-space:pre">    </span>          if (mResumedActivity != null) {  
  11.            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);  
  12.             pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);  
  13.         }  
  14. <span style="white-space:pre">    </span>             return true;    
  15. <span style="white-space:pre">    </span>        }      
  16. <span style="white-space:pre">    </span>         ......       
  17. <span style="white-space:pre">    </span>         if (next.app != null && next.app.thread != null) {    
  18. <span style="white-space:pre">    </span>             ......       
  19. <span style="white-space:pre">    </span>         } else {    
  20. <span style="white-space:pre">    </span>           ......    
  21. <span style="white-space:pre">    </span>            startSpecificActivityLocked(next, true, true);    
  22. <span style="white-space:pre">    </span>        }       
  23. <span style="white-space:pre">    </span>         return true;    
  24. <span style="white-space:pre">    </span>    }   

由上可以清晰的看到,如果目前activity沒暫停,要先把它暫停。

二.暫停目前Activity

上面己經分析到新Activity啟動會先把之前的Activity暫停,具體是調用startPausingLocked方法。它的核心代碼如下: [java]  view plain  copy

  1. if (prev.app != null && prev.app.thread != null) {  
  2.            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);  
  3.            try {  
  4.                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,  
  5.                        prev.userId, System.identityHashCode(prev),  
  6.                        prev.shortComponentName);  
  7.                mService.updateUsageStats(prev, false);  
  8.                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,  
  9.                        userLeaving, prev.configChangeFlags, dontWait);  

prev.app.thread是一個ApplicationThread對象的遠端接口,它的類型是IApplicationThread。 通過調用這個遠端接口的schedulePauseActivity來通知Activity進入Paused狀态。先看下IApplicationThread接口。 [java]  view plain  copy

  1. public interface IApplicationThread extends IInterface {  
  2.     void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,  
  3.             int configChanges, boolean dontReport) throws RemoteException;  
  4.     void scheduleStopActivity(IBinder token, boolean showWindow,  
  5.             int configChanges) throws RemoteException;  
  6.     void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;  
  7.     void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;  
  8.     void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)  
  9.             throws RemoteException;  
  10.     void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;  
  11.     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
  12.             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,  
  13.             String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,  
  14.             PersistableBundle persistentState, List<ResultInfo> pendingResults,  
  15.             List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,  
  16.             ProfilerInfo profilerInfo) throws RemoteException;  
  17.     void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,  
  18.             List<ReferrerIntent> pendingNewIntents, int configChanges,  
  19.             boolean notResumed, Configuration config) throws RemoteException;  
  20.     void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;  
  21.     void scheduleDestroyActivity(IBinder token, boolean finished,  
  22.             int configChanges) throws RemoteException;  
  23.     void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,  
  24.             int resultCode, String data, Bundle extras, boolean sync,  
  25.             int sendingUser, int processState) throws RemoteException;  
  26.     static final int BACKUP_MODE_INCREMENTAL = 0;  
  27.     static final int BACKUP_MODE_FULL = 1;  
  28.     static final int BACKUP_MODE_RESTORE = 2;  
  29.     static final int BACKUP_MODE_RESTORE_FULL = 3;  
  30.     void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,  
  31.             int backupMode) throws RemoteException;  
  32.     void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)  
  33.             throws RemoteException;  
  34.     void scheduleCreateService(IBinder token, ServiceInfo info,  
  35.             CompatibilityInfo compatInfo, int processState) throws RemoteException;  
  36.     void scheduleBindService(IBinder token,  
  37.             Intent intent, boolean rebind, int processState) throws RemoteException;  
  38.     void scheduleUnbindService(IBinder token,  
  39.             Intent intent) throws RemoteException;  
  40.     void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,  
  41.             int flags, Intent args) throws RemoteException;  
  42.     void scheduleStopService(IBinder token) throws RemoteException;  
  43.     static final int DEBUG_OFF = 0;  
  44.     static final int DEBUG_ON = 1;  
  45.     static final int DEBUG_WAIT = 2;  
  46.     void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,  
  47.             ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,  
  48.             IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,  
  49.             int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,  
  50.             Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,  
  51.             Bundle coreSettings) throws RemoteException;  
  52.     void scheduleExit() throws RemoteException;  
  53.     void scheduleSuicide() throws RemoteException;  
  54.     void scheduleConfigurationChanged(Configuration config) throws RemoteException;  
  55.     void updateTimeZone() throws RemoteException;  
  56.     void clearDnsCache() throws RemoteException;  
  57.     void setHttpProxy(String proxy, String port, String exclList,  
  58.             Uri pacFileUrl) throws RemoteException;  
  59.     void processInBackground() throws RemoteException;  
  60.     void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)  
  61.             throws RemoteException;  
  62.     void dumpProvider(FileDescriptor fd, IBinder servicetoken, String[] args)  
  63.             throws RemoteException;  
  64.     void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,  
  65.             int resultCode, String data, Bundle extras, boolean ordered,  
  66.             boolean sticky, int sendingUser, int processState) throws RemoteException;  
  67.     void scheduleLowMemory() throws RemoteException;  
  68.     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;  
  69.     void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType)  
  70.             throws RemoteException;  
  71.     void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)  
  72.             throws RemoteException;  

由此猜測它與activity,service的開啟有關。IApplicationThread這個IBind實作者完成了大量和Activity以及service有關的功能。 而ApplicationThreadNative就是它的實作類。 [java]  view plain  copy

  1. public abstract class ApplicationThreadNative extends Binder  
  2.         implements IApplicationThread {  
  3.     static public IApplicationThread asInterface(IBinder obj) {  
  4.         if (obj == null) {  
  5.             return null;  
  6.         }  
  7.         IApplicationThread in =  
  8.             (IApplicationThread)obj.queryLocalInterface(descriptor);  
  9.         if (in != null) {  
  10.             return in;  
  11.         }  
  12.         return new ApplicationThreadProxy(obj);  
  13.     }  
  14.     public ApplicationThreadNative() {  
  15.         attachInterface(this, descriptor);  
  16.     }  
  17.     @Override  
  18.     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)  
  19.             throws RemoteException {  
  20.         switch (code) {  
  21.         case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:  
  22.         {  
  23.             data.enforceInterface(IApplicationThread.descriptor);  
  24.             IBinder b = data.readStrongBinder();  
  25.             boolean finished = data.readInt() != 0;  
  26.             boolean userLeaving = data.readInt() != 0;  
  27.             int configChanges = data.readInt();  
  28.             boolean dontReport = data.readInt() != 0;  
  29.             schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport);  
  30.             return true;  
  31.         }  

[java]  view plain  copy

  1. <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,  
  2.             boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {  
  3.         Parcel data = Parcel.obtain();  
  4.         data.writeInterfaceToken(IApplicationThread.descriptor);  
  5.         data.writeStrongBinder(token);  
  6.         data.writeInt(finished ? 1 : 0);  
  7.         data.writeInt(userLeaving ? 1 :0);  
  8.         data.writeInt(configChanges);  
  9.         data.writeInt(dontReport ? 1 : 0);  
  10.         mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,  
  11.                 IBinder.FLAG_ONEWAY);  
  12.         data.recycle();  
  13.     }  

………………}

由上可見它就是一個Binder抽象類, ApplicationThreadProxy是代理類。真正實作類是ApplicationThread。直接看 ApplicationThread的 schedulePauseActivity方法。 [java]  view plain  copy

  1. public final void schedulePauseActivity(IBinder token, boolean finished,  
  2.                boolean userLeaving, int configChanges, boolean dontReport) {  
  3.            sendMessage(  
  4.                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,  
  5.                    token,  
  6.                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),  
  7.                    configChanges);  
  8.        }  

看到這,就知道接下來肯定是用Handler來發送消息了,發送消息的代碼如下: [java]  view plain  copy

  1. private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {  
  2.         if (DEBUG_MESSAGES) Slog.v(  
  3.             TAG, "SCHEDULE " + what + " " + mH.codeToString(what)  
  4.             + ": " + arg1 + " / " + obj);  
  5.         Message msg = Message.obtain();  
  6.         msg.what = what;  
  7.         msg.obj = obj;  
  8.         msg.arg1 = arg1;  
  9.         msg.arg2 = arg2;  
  10.         if (async) {  
  11.             msg.setAsynchronous(true);  
  12.         }  
  13.         mH.sendMessage(msg);  
  14.     }  

就是在發送一個暫停Activity的消息給Handler處理,這個Handler名字為H。H在它的handlerMessage中處理相應的請求,它的實作如下: [java]  view plain  copy

  1.  public void handleMessage(Message msg) {  
  2.             switch (msg.what) {  
  3.              …………  
  4.                 case PAUSE_ACTIVITY:  
  5.                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");  
  6.                     handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,  
  7.                             (msg.arg1&2) != 0);  
  8.                     maybeSnapshot();  
  9.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  10.                     break;  
  11. …………  
  12. }  

看下handlePauseActivity的代碼: [java]  view plain  copy

  1. private void handlePauseActivity(IBinder token, boolean finished,  
  2.             boolean userLeaving, int configChanges, boolean dontReport) {  
  3.         ActivityClientRecord r = mActivities.get(token);  
  4.         if (r != null) {  
  5.             //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);  
  6.             if (userLeaving) {  
  7.                 performUserLeavingActivity(r);  
  8.             }  
  9.             r.activity.mConfigChangeFlags |= configChanges;  
  10.             performPauseActivity(token, finished, r.isPreHoneycomb());  
  11.             // Make sure any pending writes are now committed.  
  12.             if (r.isPreHoneycomb()) {  
  13.                 QueuedWork.waitToFinish();  
  14.             }  
  15.             // Tell the activity manager we have paused.  
  16.             if (!dontReport) {  
  17.                 try {  
  18.                     ActivityManagerNative.getDefault().activityPaused(token);  
  19.                 } catch (RemoteException ex) {  
  20.                 }  
  21.             }  
  22.             mSomeActivitiesChanged = true;  
  23.         }  

  函數首先将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的代碼: [java]  view plain  copy

  1. public final void activityPaused(IBinder token) {  
  2.         final long origId = Binder.clearCallingIdentity();  
  3.         synchronized(this) {  
  4.             ActivityStack stack = ActivityRecord.getStackLocked(token);  
  5.             if (stack != null) {  
  6.                 stack.activityPausedLocked(token, false);  
  7.             }  
  8.         }  
  9.         Binder.restoreCallingIdentity(origId);  
  10.     }  

繞了一大圈又回到了ActivityStack中,調用它的activityPauseLocked方法。

[java]  view plain  copy

  1. final void activityPausedLocked(IBinder token, boolean timeout) {  
  2.        if (DEBUG_PAUSE) Slog.v(  
  3.            TAG, "Activity paused: token=" + token + ", timeout=" + timeout);  
  4.        final ActivityRecord r = isInStackLocked(token);  
  5.        if (r != null) {  
  6.            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);  
  7.            if (mPausingActivity == r) {  
  8.                if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r  
  9.                        + (timeout ? " (due to timeout)" : " (pause complete)"));  
  10.                completePauseLocked(true);  
  11.            } else {  
  12.                EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,  
  13.                        r.userId, System.identityHashCode(r), r.shortComponentName,  
  14.                        mPausingActivity != null  
  15.                            ? mPausingActivity.shortComponentName : "(none)");  
  16.            }  
  17.        }  
  18.    }  

前一個Activity的資訊儲存在mPausingActivity中,是以,這裡mPausingActivity等于r,于是,執行completePauseLocked操作。 [java]  view plain  copy

  1.  private void completePauseLocked(boolean resumeNext) {  
  2. …………  
  3.    if (resumeNext) {  
  4.             final ActivityStack topStack = mStackSupervisor.getFocusedStack();  
  5.             if (!mService.isSleepingOrShuttingDown()) {  
  6.                 mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);  
  7.             } else {  
  8.                 mStackSupervisor.checkReadyForSleepLocked();  
  9.                 ActivityRecord top = topStack.topRunningActivityLocked(null);  
  10.                 if (top == null || (prev != null && top != prev)) {  
  11.                     // If there are no more activities available to run,  
  12.                     // do resume anyway to start something.  Also if the top  
  13.                     // activity on the stack is not the just paused activity,  
  14.                     // we need to go ahead and resume it to ensure we complete  
  15.                     // an in-flight app switch.  
  16.                     mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);  
  17.                 }  
  18.             }  
  19.         }  
  20. …………  
  21. }  

很顯然,又回到了resumeTopActivitiesLocked中,這次activity己經停止,是以它 調用了ActivityStackSupervisor的StartSpecificActivityLocked方法。

三,啟動Activity

其實啟動Activity與暫停很類似,都是在ApplicationThread中實作的,看代碼: [java]  view plain  copy

  1. void startSpecificActivityLocked(ActivityRecord r,  
  2.            boolean andResume, boolean checkConfig) {  
  3.        // Is this activity's application already running?  
  4.        ProcessRecord app = mService.getProcessRecordLocked(r.processName,  
  5.                r.info.applicationInfo.uid, true);  
  6.        r.task.stack.setLaunchTime(r);  
  7.        if (app != null && app.thread != null) {  
  8.            try {  
  9.                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0  
  10.                        || !"android".equals(r.info.packageName)) {  
  11.                    // Don't add this if it is a platform component that is marked  
  12.                    // to run in multiple processes, because this is actually  
  13.                    // part of the framework so doesn't make sense to track as a  
  14.                    // separate apk in the process.  
  15.                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,  
  16.                            mService.mProcessStats);  
  17.                }  
  18.                realStartActivityLocked(r, app, andResume, checkConfig);  
  19.                return;  
  20.            } catch (RemoteException e) {  
  21.                Slog.w(TAG, "Exception when starting activity "  
  22.                        + r.intent.getComponent().flattenToShortString(), e);  
  23.            }  
  24.            // If a dead object exception was thrown -- fall through to  
  25.            // restart the application.  
  26.        }  
  27.        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,  
  28.                "activity", r.intent.getComponent(), false, false, true);  
  29.   }   

接下來重點看下 realStartActivityLocked,它代碼中有以下一段 [java]  view plain  copy

  1. app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,  
  2.                     System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),  
  3.                     r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,  
  4.                     r.icicle, r.persistentState, results, newIntents, !andResume,  
  5.                     mService.isNextTransitionForward(), profilerInfo);  

是不是有種似曾相識的感覺。接下來就是跟暫停一樣了,調用 ApplicationThread中的scheduleLaunchActivity,最終調用H中的HandlerMessage。 [java]  view plain  copy

  1. public void handleMessage(Message msg) {  
  2.             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
  3.             switch (msg.what) {  
  4.                 case LAUNCH_ACTIVITY: {  
  5.                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");  
  6.                     final ActivityClientRecord r = (ActivityClientRecord) msg.obj;  
  7.                     r.packageInfo = getPackageInfoNoCheck(  
  8.                             r.activityInfo.applicationInfo, r.compatInfo);  
  9.                     handleLaunchActivity(r, null);  
  10.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  11.                 } break;  
  12.           ………………  

再看下handleLaunchActivity()的實作,代碼比較長,隻看核心的。 [java]  view plain  copy

  1. if (localLOGV) Slog.v(  
  2.            TAG, "Handling launch of " + r);  
  3.        // Initialize before creating the activity  
  4.        WindowManagerGlobal.initialize();  
  5.        Activity a = performLaunchActivity(r, customIntent);  
  6.        if (a != null) {  
  7.            r.createdConfig = new Configuration(mConfiguration);  
  8.            Bundle oldState = r.state;  
  9.            handleResumeActivity(r.token, false, r.isForward,  
  10.                    !r.activity.mFinished && !r.startsNotResumed);  

performLaunchAcitvity中調用Activity的onCreate(),onStart()方法,handlerResumeActivity調用onResume()方法。重點看下 performLaunchAcitvity, 我們 把它拆分來看,它總共完成以下幾個功能。 1.從ActivityClientRecord中擷取待啟動的Activity的元件資訊 [java]  view plain  copy

  1. ActivityInfo aInfo = r.activityInfo;  
  2.         if (r.packageInfo == null) {  
  3.             r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,  
  4.                     Context.CONTEXT_INCLUDE_CODE);  
  5.         }  
  6.         ComponentName component = r.intent.getComponent();  
  7.         if (component == null) {  
  8.             component = r.intent.resolveActivity(  
  9.                 mInitialApplication.getPackageManager());  
  10.             r.intent.setComponent(component);  
  11.         }  
  12.         if (r.activityInfo.targetActivity != null) {  
  13.             component = new ComponentName(r.activityInfo.packageName,  
  14.                     r.activityInfo.targetActivity);  
  15.         }  

2.通過Instrumentation 的newActivity方法使用類加載器建立Activity對象 [java]  view plain  copy

  1. Activity activity = null;  
  2.         try {  
  3.             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
  4.             activity = mInstrumentation.newActivity(  
  5.                     cl, component.getClassName(), r.intent);  
  6.             StrictMode.incrementExpectedActivityCount(activity.getClass());  
  7.             r.intent.setExtrasClassLoader(cl);  
  8.             r.intent.prepareToEnterProcess();  
  9.             if (r.state != null) {  
  10.                 r.state.setClassLoader(cl);  
  11.             }  
  12.         } catch (Exception e) {  
  13.             if (!mInstrumentation.onException(activity, e)) {  
  14.                 throw new RuntimeException(  
  15.                     "Unable to instantiate activity " + component  
  16.                     + ": " + e.toString(), e);  
  17.             }  
  18.         }  

重點實作在newActivity中 [java]  view plain  copy

  1. public Activity newActivity(ClassLoader cl, String className,  
  2.             Intent intent)  
  3.             throws InstantiationException, IllegalAccessException,  
  4.             ClassNotFoundException {  
  5.         return (Activity)cl.loadClass(className).newInstance();  
  6.     }  

3.通過LoadedApk的makeApplication方法來嘗試建立Application [java]  view plain  copy

  1. public Application makeApplication(boolean forceDefaultAppClass,  
  2.            Instrumentation instrumentation) {  
  3.        if (mApplication != null) {  
  4.            return mApplication;  
  5.        }  
  6.        Application app = null;  
  7.        String appClass = mApplicationInfo.className;  
  8.        if (forceDefaultAppClass || (appClass == null)) {  
  9.            appClass = "android.app.Application";  
  10.        }  
  11.        try {  
  12.            java.lang.ClassLoader cl = getClassLoader();  
  13.            if (!mPackageName.equals("android")) {  
  14.                initializeJavaContextClassLoader();  
  15.            }  
  16.            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);  
  17.            app = mActivityThread.mInstrumentation.newApplication(  
  18.                    cl, appClass, appContext);  
  19.            appContext.setOuterContext(app);  
  20.        } catch (Exception e) {  
  21.            if (!mActivityThread.mInstrumentation.onException(app, e)) {  
  22.                throw new RuntimeException(  
  23.                    "Unable to instantiate application " + appClass  
  24.                    + ": " + e.toString(), e);  
  25.            }  
  26.        }  
  27.        mActivityThread.mAllApplications.add(app);  
  28.        mApplication = app;  
  29.        if (instrumentation != null) {  
  30.            try {  
  31.                instrumentation.callApplicationOnCreate(app);  
  32.            } catch (Exception e) {  
  33.                if (!instrumentation.onException(app, e)) {  
  34.                    throw new RuntimeException(  
  35.                        "Unable to create application " + app.getClass().getName()  
  36.                        + ": " + e.toString(), e);  
  37.                }  
  38.            }  
  39.        }  
  40. ………  

如果Application被建立了,就不會再重複建立了。這也意味着一個應用隻有一個Application,它的建立是通過Instrumentation來完成的。通過類加載載來實作。建立完通過callApplicationOnCreate來調用Application的onCreate()方法。 4,建立ContextImpl對象并通過Activity的attach方法來完成一些重要資料的初始化。 [java]  view plain  copy

  1. Context appContext = createBaseContextForActivity(r, activity);  
  2.                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());  
  3.                Configuration config = new Configuration(mCompatConfiguration);  
  4.                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "  
  5.                        + r.activityInfo.name + " with config " + config);  
  6.                activity.attach(appContext, this, getInstrumentation(), r.token,  
  7.                        r.ident, app, r.intent, r.activityInfo, title, r.parent,  
  8.                        r.embeddedID, r.lastNonConfigurationInstances, config,  
  9.                        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的啟動操作了。

現在再回頭去看下那個啟動圖,應該大部分能看懂了。