1. 程式人生 > >Android Activity啟動流程(基於Android8.0系統)

Android Activity啟動流程(基於Android8.0系統)

主要物件介紹

  • ActivityManagerService:負責系統中所有Activity的生命週期;
  • ActivityThread:App的真正入口,當App啟動後,會呼叫其main方法開始執行,開啟訊息迴圈佇列。是傳說中的UI執行緒,即主執行緒。與ActivityManagerService配合,一起完成Activity的管理工作;
  • ApplicationThread:用來實現ActivityManagerService與ActivityThread之間的互動。在ActivityManagerService需要管理相關Application中的Activity的生命週期,通過ApplicationThread的代理物件與ActivityThread通訊;
  • ApplictationThreadProxy:是ApplicationThread在服務端的代理物件,負責和客戶端的ApplicationThread通訊。AMS就是通過這個代理物件與ActivityThread進行通訊的,Android 8.0上以刪除該類,採用AIDL介面的方式來進行IPC,實現RPC操作
  • Instrumentation:每一個應用程式都只有一個Instrumentation物件,每個Activity內都有一個對該物件的引用。Instrumentation可以理解為應用程序的管家,ActivityThread要建立或者開啟某個Activity時,都需要通過Instrumentation來進行具體的操作;
  • ActvitityStack:Activity在AMS的棧管理,用來記錄已經啟動的Activity的先後關係、狀態資訊等。通過ActivityStack決定是否需要啟動新的程序;
  • ActivityRecord:ActivityStatck的管理物件,每個Activity在AMS對應的一個ActivityRecord,來記錄Activity的狀態以及其他資訊。可以理解為Activity在服務端的Activity物件的對映;
  • ActivityClientRecord:與ActivityRecord是在服務端(AMS)的記錄相對應,是Activity在客戶端(ActivityThread)的記錄;
  • TaskRecord:AMS抽象出來的任務棧的概念。一個TaskRecord包含若干個ActivityRecord。ASM用它來確保Activity啟動和退出順序。它與Activity的啟動模式直接相關。
  • ActivityStarter:啟動Activity的控制器,主要用於用來將Intent和flags轉換成activity和相關任務棧;
  • ActivityStackSupervisor:主要管理著mHomeStack和mFocusedStack兩個ActivityStack等相關資訊;

Binder通訊

  • 在Android 8.0以前,Binder通訊的流程如下:
    客戶端: ActivityManagerProxy -> Binder驅動 -> 服務端:ActivityManagerService
    服務端: ApplicationThreadProxy -> Binder驅動 -> 客戶端:ApplicationThread
  • Android8.0開始,刪除了ActivityManagerNative,AMS的繼承類也發生了變化,繼承了IActivityManager.Stub介面類。瞭解Android的Binder機制應該知道,這裡IActivityManager.aidl生成的介面類。Android8.0開始,把一些Binder程式碼轉化為了AIDL模板方式:
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

ActivityManager中的程式碼:

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
  • 而在Android7.0及其以前的版本上,則是客戶端通過ActivityManaagerProxy與服務端的ActivityManager進行通訊的
    ActivityManagerNative:
**
*獲得IActivityManager類
*/
static public IActivityManager getDefault() {
        return gDefault.get();
    }

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
 
        return new ActivityManagerProxy(obj);

}

ActivityManager:

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;
        }
};

可以看出來,兩個寫法不一樣,本質上都是一樣的,Android 8.0可能使用了AIDL方式進行ipc。

  • 同理,ApplicationThread同上述一樣做了更改:
 private class ApplicationThread extends IApplicationThread.Stub {
    ...
 }

所以在Android 8.0上不存在ActivityManagerProxy和ApplicationThreadProxy,而是採用了AIDL介面的方式來進行通訊的。

原始碼呼叫棧(基於Android 8.0)

按照自上而下的呼叫棧的順序進行呼叫,以類檔案為單位來計步,方便大家去了解呼叫流程,主要涉及的幾個原始檔:Instumentation,ActivityMangerService,ActivityStack,ActivityStarter,ActivityStackSupervisor,ActivityThread,Activity等。

  1. Activity
public void startActivity(Intent intent)
    
public void startActivity(Intent intent, @Nullable Bundle options)

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options)
  1. Intrumentation
public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, Activity target,
    Intent intent, int requestCode, Bundle options){
    ...
    int result = ActivityManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null,
            requestCode, 0, null, options);
    ...
}
  1. ActivityManagerService
public final int startActivity(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    ...
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
}
     
            
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    ...
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
  1. ActivityStarter
final int startActivityMayWait(IApplicationThread caller, int callingUid,
    String callingPackage, Intent intent, String resolvedType,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int startFlags,
    ProfilerInfo profilerInfo, WaitResult outResult,
    Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, 
    int userId,askRecord inTask, String reason) { 
    ...
    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
        aInfo, rInfo, voiceSession, voiceInteractor,
        resultTo, resultWho, requestCode, callingPid,
        callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
        options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
        reason);
    ...
}
        

int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
    String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
    String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
    ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
    ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
    ...
    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
    aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
    callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
    options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
            inTask);
    ...
}
            
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
    String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
    String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
    ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
    ActivityRecord[] outActivity, TaskRecord inTask) {
    ...
    doPendingActivityLaunchesLocked(false);
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
    options, inTask, outActivity);
}
            

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {
    ...
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
        startFlags, doResume, options, inTask, outActivity);
    ...
}  
            
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {
    ...
    if (mDoResume) {
        mSupervisor.resumeFocusedStackTopActivityLocked();
    }
    ...
}
  1. ActivityStackSupervisor
boolean resumeFocusedStackTopActivityLocked() {
    return resumeFocusedStackTopActivityLocked(null, null, null);
}
    
boolean resumeFocusedStackTopActivityLocked(
    ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    ...
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } 
    ...
}
  1. ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 
   ....
    if (mResumedActivity != null) {
        //同步等待pause當前Activity的結果
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
    ....
      //開始啟動下一個Activity
      mStackSupervisor.startSpecificActivityLocked(next, true, false);
    ....
}


final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately) {
    ....
    //去當前Activity所在應用程序暫停當前activity
     prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
            userLeaving, prev.configChangeFlags, pauseImmediately);
    ....
}
       
  1. ActivityThread$ApplicationThread
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 ? USER_LEAVING: 0) | (dontReport ? DONT_REPORT: 0), configChanges, seq);
    ...
}
  1. ActivityThread
private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
    Message msg = Message.obtain();
    ....
    mH.sendMessage(msg);
}
  1. ActivityThread$H
public void handleMessage(Message msg) {
   ...
    switch (msg.what) {
    case PAUSE_ACTIVITY:
        {
            SomeArgs args = (SomeArgs) msg.obj;
            handlePauseActivity((IBinder) args.arg1, false, (args.argi1 & USER_LEAVING) != 0,
            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
        }
        break;
    }
    ...
}
  1. ActivityThread
private void handlePauseActivity(IBinder token, boolean finished, 
    boolean userLeaving, int configChanges, boolean dontReport, int seq) {
    ...
    performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
    ...
    //執行完後通知AMS當前Activity已經pause
    ActivityManager.getService().activityPaused(token);
    ...
}

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
     boolean saveState, String reason) {
         ...
         performPauseActivityIfNeeded(r, reason);
         ...
}


private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
    ...
     mInstrumentation.callActivityOnPause(r.activity);
    ...
}
  1. Instrumentation
public void callActivityOnPause(Activity activity) {
    activity.performPause();
}
  1. Activity
final void performPause() {
    ...
    onPause();
    ...
}

由於在ActivityThread中handlePauseActivity的方法裡,在pause成功後,需要通知AMS已經pause成功,所以接著分析ActivityManagerService.activityPaused方法。

  1. ActivityManagerService
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);
}
  1. ActivityStack
final void activityPausedLocked(IBinder token, boolean timeout) {
    ...
    mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
    ...
    completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
    ...
}

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
    ...
    mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
    ...
}
  1. ActivityStackSupervisor
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    //如果啟動Activity和要啟動的Activity在同一個ActivityStack中,呼叫targetStack物件的方法
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    //如果不在同一個ActivityStack中,則呼叫mFocusStack物件的方法
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }

    return false;
}
  1. ActivityStatck
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 
   ...
    if (mResumedActivity != null) {
        //同步等待pause當前Activity的結果,但在pause時,已經把mResumedActivity置為了null,所以不走這裡
        pausing |= startPausingLocked(userLeaving, false, next, false);
        ...
    }
    ...
    return true;
    ...
      //開始啟動下一個Activity
      mStackSupervisor.startSpecificActivityLocked(next, true, false);
    ...
}
  1. ActivityStackSupervisor
void startSpecificActivityLocked(ActivityRecord r,
    boolean andResume, boolean checkConfig) { 
    if (app != null && app.thread != null) { 
        ...
        realStartActivityLocked(r, app, andResume, checkConfig);
        return;
    }
    ...
    //啟動跨程序的Activity需要先開啟新的應用程序
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
        "activity", r.intent.getComponent(), false, false, true);
}

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
    boolean andResume, boolean checkConfig) throws RemoteException { 
    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global
        // and override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, !andResume,
        mService.isNextTransitionForward(), profilerInfo);
    ...
}
  1. ActivityThread$ApplicationThread
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
    ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
    CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
    int procState, Bundle state, PersistableBundle persistentState,
    List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
    boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
}
  1. ActivityThread
private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}
 
 
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    ...
    mH.sendMessage(msg);
} 
 
  1. ActivityThread$H
public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
    case LAUNCH_ACTIVITY:
        {
            ....
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            ....
        }
        break;
        ...
    }
}
  1. ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){ 
    ...
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    ...
}
  1. Instumentation
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}
  1. Activity
final void performCreate(Bundle icicle) {
    performCreate(icicle, null);
}

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    ...
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
   ...
}

Activity啟動流程

為了敘述方便,我們假設Activity A要啟動Activity B。

  1. Activity A向AMS傳送一個啟動Activity B的程序間通訊請求;
  2. AMS會將要啟動的Activity B的元件資訊儲存下來,然後通過Binder通訊(ApplicationThread及其介面定義語言),讓Activity A執行pause操作;
  3. Activity B完成pause操作後,通過Binder通訊(ActivityManagerService及其介面定義語言)通知AMS,可以執行啟動Activity B的操作了(要啟動的activity資訊儲存在了棧頂);
  4. 在啟動之前,如果發現Activity B的應用程式程序不存在,會先啟動一個新的程序(上述呼叫棧沒涉及,同學們可自行檢視原始碼);
  5. AMS執行一系列啟動Activity B的操作,並通過Binder通訊(ApplicationThread及其介面定義語言)進行跨程序呼叫,將Activity B啟動起來;

關於AMS

  • AMS的啟動是在SystemServer(系統程序)中啟動的,同其他Android應用一樣,也是由Zygote程序fork出來的:
public final class SystemServer {

    /**
     * The main entry point from zygote.
     * 註釋寫的很清楚了,SystemServer程序是有Zygote程序fork出來的
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }    
    
    private void run() {
        ...
         startBootstrapServices();
        ...
    }
    
    private void startBootstrapServices() {
        ...
        // Activity manager runs the show.
        traceBeginAndSlog("StartActivityManager");
        //開啟ActivityManagerService程序
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        traceEnd();        
        ...
    }    
}
  • AMS與APP程序的通訊:
  1. APP程序通過IActivityManager.aidl介面向AMS程序進行通訊。
    ActivityManager.getService()獲得AMS的Binder介面,再通過Stub.asInterface的方式,轉成IActivityManager的介面,通過IActivityManager與AMS進行通訊,實現RPC遠端跨程序呼叫;
    Instrumentation
int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);

ActivityManager

public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
}
 
private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
        @Override
        protected IActivityManager create() {
            final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
            final IActivityManager am = IActivityManager.Stub.asInterface(b);
            return am;
        }
};

  1. AMS程序通過IApplication.aidl介面向APP程序進行通訊。
    在AMS內部持有每個ActivityThread的IApplicatinThread介面例項,用時可以直接呼叫。同IActivityManager,也是通過Binder進行程序間通訊。