1. 程式人生 > 其它 >根Activity的啟動過程

根Activity的啟動過程

《安卓進階解密》讀書筆記

這裡分析的原始碼基於android-8.0.0_r4.

「根Activity的啟動過程」和「Activity的啟動_5.0」筆記記錄的,有大部分過程是一樣的.

概述

Activity啟動過程中設計到的程序及其互動

時序圖如下

這裡將根Activity的啟動劃分為四部分

  1. Launcher請求AMS過程
  2. AMS判斷根Activity所需的應用程式程序是否已經存在並啟動,若不存在,則請求Zygote程序建立應用程式程序,詳情檢視《應用程式程序啟動過程》的筆記。應用程式程序啟動後,則進入下一個步驟
  3. AMS到ApplicationThread的呼叫過程
  4. ActivityThread啟動Activity的過程

這裡先看下第2部分,為什麼會存在根Activity所需的應用程序已經啟動的情況呢?比如現在要寫一個音樂播放器App,第一次開啟這個App,那麼應用程序當然是未啟動的,這時候為了啟動根Activity,就需要先啟動應用程式程序,再啟動根Activity,現在它們都啟動完畢,並且運行了一段時間,現在在程式中播放一首歌曲,音樂播放器放在Service中管理,現在按返回鍵,銷燬所有的Activity,銷燬完之後,會發現音樂還在播放,這時候雖然Activity都被銷燬了,但是程序還是存活的,並且Service還是存活的,音樂仍然在播放,那麼這時候,如果點選應用程式的快捷圖示,將會啟動根Activity

,這種情況下就是根Activity所需的應用程序已經啟動的情況。

另外,好像沒有找到在哪裡判斷的「根Activity所需的應用程式程序是否已經存在並啟動」的程式碼,是在ActivityStackSupervisor::startSpecificActivityLocked當中嗎?

後面會講解其餘的三個部分。

相關類介紹

Instrumentation:儀表盤,具體到應用程式中是管理Activity的一個工具類,包括建立和啟動ActivityActivity的生命週期方法都是由Instrumentation來控制的,一個程序只用一個Instrumentation例項

ActivityManagerService

Android中最核心的服務,主要負責系統中四大元件的啟動、切換、排程及應用程式的管理和排程等工作

ActivityThread:管理應用程式程序中主執行緒的執行,根據Activity管理者的請求排程和執行activitiesbroadcasts及其相關的操作

ApplicationThread:用來實現ActivityManagerServiceActivityThread之間的互動,是ActivityThread的內部類

ActivityStack:負責單個Activity棧的狀態和管理

ActivityStackSupervisor:負責所有Activity棧的管理

ActivityStarter:Android 7.0新加入的類,它是載入Activity的控制類

HActivityThread的內部類,繼承至Handler,是應用程式程序中主執行緒的訊息管理類

ProcessRecord:用於描述一個應用程式程序

ActivityRecord:用於描述一個Activity,用來記錄一個Activity的所有資訊

TaskRecord:用於描述一個任務棧

LoadedApk:用來描述已載入的APK檔案

Activity:變數說明

  • mMainThreadActivityThread
  • mMainThread.getApplicationThread()ApplicationThread
  • ApplicationThreadActivityThread的一個內部類,這兩個類在Activity啟動的過程中都發揮著重要的作用

IBinder

這裡簡單說明根Activity啟動時涉及到的Binder類、Binder介面,這部分內容在《Activity的啟動_5.0》筆記中有記錄過,但是Android 8.0之前,IActivityManager以及IApplicationThread的定義宣告等並沒有採用AIDL的形式,而是一種類似AIDL的形式,在Android 8.0中,採取的是一種AIDL的形式

Android 5.0的筆記

IActivityManager:

//Binder介面
public interface IActivityManager extends IInterface {...}

//Binder類,相當於Stub
public abstract class ActivityManagerNative extends Binder implements IActivityManager{.}

//Binder類的具體實現
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...}

//Binder類的本地代理,相當於Proxy,定義在ActivityManagerNative裡面,不同程序下,通過 //ActivityManagerNative的asInterface,即可將AMS「繼承至Stub」轉化為ActivityManagerProxy      //「Proxy」
class ActivityManagerProxy implements IActivityManager{...}

IApplicationThread:

//Binder介面
public interface IApplicationThread extends IInterface {...}

//Binder類,相當於Stub
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {}

//繼承至Binder類,也就說這個相當於是Binder類的真正實現,相當於上面AMS的aidl邏輯分析中的Binder_1
private class ApplicationThread extends ApplicationThreadNative {...}

//代理物件如下,定義在ActivityThreadNative裡面
class ApplicationThreadProxy implements IApplicationThread {...}

Android 8.0的變化

原始碼地址:IActivityManager.java.

public interface IActivityManager extends android.os.IInterface{
	...
    public static abstract class Stub extends android.os.Binder implements 
        android.app.IActivityManager{
    	...
        private static class Proxy implements android.app.IActivityManager{
        	...
        }
    }
}

原始碼地址:ActivityManagerService.java.

public class ActivityManagerService extends IActivityManager.Stub...{
    ...
}

形式上和《Android 開發藝術探索》介紹的一樣。Android 8.0去除了ActivityManagerNative的內部類ActivityManagerProxy,代替它的是IActivityManager.Stub.ProxyActivityManagerService繼承至IActivityManager.Stub

IApplicationThread應該也是這樣。另外,ApplicationThreadActivityThread的內部類

這裡沒有去找原始碼,所以只能說應該,沒找原始碼是因為aidl檔案,是在編譯的時候才轉化為.java檔案,原始碼怎麼找嘛~~

PS:IActivityManager.java是通過程式碼的跳轉連結找到的~~

Launcher請求AMS過程

當我們點選某個應用程式的快捷圖示時,就會通過Launcher請求AMS來啟動該應用程式,也就是啟動根Activity,時序圖如下

首先檢視Launcher的繼承關係

public class Launcher extends BaseActivity implements ... {...}

public abstract class BaseActivity extends Activity {...}

可以看出,Launcher就是Activity的子類.

首先是LauncherstartActivitySafely方法

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
 	...
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//該Flag表明根Activity會在新的任務棧啟動
    ...
    startActivity(intent, optsBundle);
    ...
}

呼叫父類ActivitystartActivity方法

public void startActivity(Intent intent, @Nullable Bundle options) {
    ...
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }    
}

這裡出現了startActivityForResult方法的兩個過載,兩個引數的那個方法,最終會呼叫到三個引數的,如下

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

這裡檢視三個引數的startActivityForResult方法

    # requestCode:如果requestCode >= 0,該Activity銷燬時,requestCode值會返回到
    #              onActivityResult方法裡 
	public void startActivityForResult(@RequiresPermission Intent intent, int 
    		requestCode,@Nullable Bundle options) {	
    	if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
           	...
        } else {
            ...
        }
    }
  • Activity mParent代表的是ActivityGroupActivityGroup最開始被用來一個介面中嵌入多個子Activity,後來在API 13 中被廢棄了,使用Fragment代替,所以這裡只用看mParent == null的邏輯

  • 這裡傳入的requestCode的值為-1,表明Launcher不需要知道Activity啟動的結果

接著檢視InstrumentationexecStartActivity方法

	public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
           Intent intent, int requestCode, Bundle options) {
        
    	IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...
        try {
            ...
            int result = ActivityManager.getService()
               .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                       requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;    
    }

這裡通過ActivityManager.getService()獲取到AMS的本地代理,遠端呼叫AMSstartActivity,首先檢視ActivityManager.getService()方法

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

這裡通過單例類Singleton獲取AMS的本地代理,Android 8.0之前 是通過ActivityManagerNativegetDefault來完成的,Android 8.0則將該邏輯封裝到了ActivityManager當中

程序切換:Launcher程序 -> AMS所在程序(SystemServer程序)

AMS -> ApplicationThread

接下來的邏輯就進入了AMS所在程序.

時序圖如下

下面只列舉出幾個重要的方法

首先是ActivityStarter的幾個方法,先說一下ActivityStarter這個類,Android 7.0新加入的,是載入Activity的控制類,它會收集所有的邏輯,來決定如何將IntentFlags轉換為Activity,並將ActivityTask以及Stack相關聯.

ActivityStarter::startActivity,這裡講解的是第一個startActivity方法

private int startActivity(IApplicationThread caller ...) {
    ...
    ProcessRecord callerApp = null;
    if (caller != null) {
        callerApp = mService.getRecordForAppLocked(caller);
		...
    }
    ...
    //建立即將要啟動的Activity的描述類ActivityRecord    
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
        callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
        resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
         mSupervisor, container, options, sourceRecord);
    //outActivity:ActivityRecord[]型別
    if (outActivity != null) {
        outActivity[0] = r;
    }    
}
  • caller:方法呼叫一路傳來,是Launcher程序的Instrumentation::execStartActivity傳來的,指向的是Launcher程序的ApplicationThread物件

  • callerApp:代表Launcher程序的ProcessRecord物件

ActivityStarter::startActivityUnchecked,該方法主要處理與棧管理相關的邏輯

private int startActivityUnchecked(...){
    ...
    //1.
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
       newTask = true;
       //2. 
       result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack);
    }
    ...
    //3.    
    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                		mOptions);
}
  • 註釋1:在Luncher::startActivitySafely中,會為根Activity的Intent設定FLAG_ACTIVITY_NEW_TASKFlag,在註釋1中可以進入If語句

  • 註釋2:內部會建立一個新的Activity任務棧,建立一個新的TaskRecord

  • 註釋3:呼叫ActivityStackSupervisor::resumeFocusedStackTopActivityLocked

ActivityStackSupervisor::startSpecificActivityLocked

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        //1.獲取即將啟動的Activity的所在的應用程式程序
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);

        //2.
        if (app != null && app.thread != null) {
            try {
                ...
                //3.    
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        // 如果程序不存在,則通過zygote建立應用程序
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
  • 註釋2:app指的是即將啟動的Activity的所在的應用程式程序;app.thread的型別是IApplicationThread,它的實現是要啟動的Activity所在的應用程式程序的ActivityThread的內部類ApplicationThreadApplicationThread繼承了IApplication.Stub,這裡app.thread得到的是ApplicationThreadSystemServer程序的代理
  • 註釋3:呼叫自身的realStartActivityLocked方法

ActivityStackSupervisor::realStartActivityLocked

	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,      
                mergedConfiguration.getGlobalConfiguration(),
                mergedConfiguration.getOverrideConfiguration(), r.compat,
                r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, !andResume,
                mService.isNextTransitionForward(), profilerInfo);
        ...
        return true;    
    }

這裡呼叫了app.threadscheduleLaunchActivity,也就是呼叫應用程式程序的ApplicationThreadscheduleLaunchActivity方法

程序切換:AMS所在程序(SystemServer程序) -> 即將啟動的Activity所在的應用程式程序

ActivityThread啟動Activity的過程

目前程式碼邏輯執行在應用程式程序,時序圖如下

ApplicationThread::scheduleLaunchActivity

        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) {

            updateProcessState(procState, false);
			
            //將啟動Activity的引數封裝成ActivityClientRecord
            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            ...
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

H類傳送型別為H.LAUNCH_ACTIVITY的訊息,並將ActivityClientRecord傳遞過去,H類是ActivityThread的內部類,繼承至Handler,是應用程式程序中主執行緒的訊息管理類

ActivityThread::sendMessage

    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) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

由於ApplicationThread是一個Binder,它的呼叫邏輯執行在Binder執行緒池中,因此這裡通過H,將程式碼邏輯切回主執行緒.

執行緒切換:應用程式Binder執行緒 -> 應用程式主執行緒

H::handleMessage

private class H extends Handler {
	...
    public void handleMessage(Message msg) {
    	if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
				//1.
                r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
                //2.
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
            ...
        }
        ...
                
    }
}
  • 註釋1:獲取LoadedApk型別的物件賦值給ActivityClientRecordpackageInfo,應用程式程序要啟動Activity時需要將該Activity所屬的APK載入進來,而LoadApk就是用來描述已載入的APK檔案的
  • 呼叫ActivityThread::handleLaunchActivity

ActivityThread::handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
	...
    //啟動Activity    
    Activity a = performLaunchActivity(r, customIntent);    
   	if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        //將Activity的狀態設定為Resume
        handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished
                     && !r.startsNotResumed, r.lastProcessedSeq, reason);

        if (!r.activity.mFinished && r.startsNotResumed) {
            performPauseActivityIfNeeded(r, reason);
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }  
        
     } else {
        try {
            //如果Activity為null,則通知AMS停止啟動Activity
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
     }          
}

ActivityThread::performLaunchActivity

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //1.獲取ActivityInfo類
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            //2.獲取APK檔案的描述類LoadedApk
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        //3.獲取要啟動的Activity的ComponentName
        //ComponentName儲存了該Activity的包名和類名
        ComponentName component = r.intent.getComponent();
        ...
		//4.建立要啟動的Activity的上下文環境
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //5.用載入器來建立該Activity的例項
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } catch (Exception e) {
            ...
        }

        try {
            //6.嘗試建立Application,makeApplication內部會呼叫Application的onCreate
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ...

            if (activity != null) {
                ...
                appContext.setOuterContext(activity);    
                //7.初始化Activity   
                //內部包括建立PhoneWindow與Activity自身關聯;關聯ContextImpl...    
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

                ...
                if (r.isPersistable()) {
                    //8.呼叫Instrumentation::callActivityOnCreate啟動Activity
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            ...
        }

        return activity;
    }

註釋4:建立Activity的上下文環境

 private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
     ...
     ContextImpl appContext = ContextImpl.createActivityContext(
           this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
     ...
     return appContext;
 }

Activityattach中會將ContextImpl進行關聯

註釋6:嘗試建立Application,r.packageInfo的型別是LoadedApkLoadedApk::makeApplication

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        // 如果Application已經被建立過了,那麼就不會再重複建立了,這意味著一個應用程序只有
    	// 一個Application物件
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;
       	...
           
        try {
            java.lang.ClassLoader cl = getClassLoader();
            ...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            // Application物件的建立通過Instrumentation來完成,內部通過類載入器來實現
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ...
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                // 這裡面會呼叫Application的onCreate()方法
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                ...
            }
        }

        ...
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        return app;
    }

回到ActivityThreadperformLaunchActivity中,呼叫了Instrumentation::callActivityOnCreate

    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }

Activity::performCreate

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

Activity::onCreate

    public void onCreate(@Nullable Bundle savedInstanceState,
            @Nullable PersistableBundle persistentState) {
        onCreate(savedInstanceState);
    }

呼叫到了void onCreate(@Nullable Bundle savedInstanceState) {...},至此,根Activity就啟動了,即應用程式就啟動了

可以結合《Activity的啟動_5.0》的筆記一起看,那裡關於一些細節記錄得更詳細一些~~

參考

《安卓進階解密》