1. 程式人生 > >Android原始碼解析之(十一)-->應用程序啟動流程

Android原始碼解析之(十一)-->應用程序啟動流程

本節主要是通過分析Activity的啟動過程介紹應用程式程序的啟動流程。關於Android的應用程序在android guide中有這樣的一段描述:

By default, every application runs in its own Linux process. Android starts the process when any of the application’s components need to be executed, then shuts down the process when it’s no longer needed or when the system must recover memory for other applications.

每一個android應用預設都是在他自己的linux程序中執行。android作業系統會在這個android應用中的元件需要被執行的時候啟動這個應用程序,並且會在這個應用程序沒有任何元件執行或者是系統需要為其他應用申請更多記憶體的時候殺死這個應用程序。所以當我們需要啟動這個應用的四大元件之一的時候如果這個應用的程序還沒有啟動,那麼就會先啟動這個應用程式程序。

在上一篇文章中我們簡要的介紹了Launcher的啟動流程,在SystemServer程序執行完成,各種系統服務啟動完成之後,會呼叫ActivityManagerService中的systemReady()方法,在systemReady()方法中會執行Launcher啟動的相關邏輯了,具體可以參考:

android原始碼解析之(十)–>Launcher啟動流程

Launcher應用程式在啟動過程中會通過PackageManagerService服務請求查詢系統所有的已安裝應用的包名,圖示和應用名稱等資訊,然後填充到Launcher中的Adapter中,這樣點選某一項應用圖示的時候就可以根據該圖示的包名和啟動Activity的類名初始化Intent物件,然後呼叫startActivity(Intent)啟動相關的應用程式了。

其實android中應用程序可以通過許多方式啟動,比如啟動一個Activity,啟動一個Service,啟動一個ContentProvider或者是一個BroadcastReceiver,也就是說我們可以通過啟動四大元件的方式啟動應用程序,在應用程序沒有啟動的時候,如果我們通過啟動這些元件,這時候系統會判斷當前這些元件所需要的應用程序是否已經啟動,若沒有的話,則會啟動應用程序。

這裡我們通過Launcher簡單分析一下應用程序的啟動流程。通過上一篇Launcher啟動流程,我們知道每一個launcher中的圖示對應著一個應用報名和啟動activity類名,檢視LauncherActivity中的圖示點選事件:

protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }

在通過應用包名和啟動activity類名構造完成Intent之後,我們呼叫了startActivity方法來啟動這個activity,很明顯的,當前這個應用並沒有啟動,也就是說我們呼叫的startActivity方法不單單為我們啟動了這個activity也同時在啟動activity之前啟動了這個應用程序,好了,那我們這裡就以這個方法為入口分析一下應用程序的啟動流程。

跟蹤程式碼到Activity,發現其呼叫了startActivity的過載方法:

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

繼續跟進:

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

很明顯的我們此時傳遞的options為空:

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

好吧,最後呼叫的還是這個過載方法:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

可以發現這裡呼叫了mInstrumentation.execStartActivity方法,這裡先簡單介紹一下Instrumentation物件,他是Android系統中應用程式端操作Activity的具體操作類,這裡的操作段是相對於ActivityManagerService服務端來說的。也就是說當我們在執行對Activity的具體操作時,比如回撥生命週期的各個方法都是藉助於Instrumentation類來實現的。

好了,下面我們繼續看一下Instrumentation的execStartActivity方法:

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

這裡主要關注這個程式碼:

int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

這斷程式碼實際上是程序間通訊,我們可以發現ActivityManagerNative繼承於Binder介面,所以ActivityManagerNative就是一個Binder物件,然後上面一節我們介紹SystemServer程序的時候對ActivityManagerService有過了解,發現其繼承於ActivityManagerNative,好吧,瞭解過Binder機制的童鞋就知道了,ActivityManagerService就是這個Binder機制的伺服器端而ActivityManagerNative就是這個Binder機制的客戶端,所以我們這裡呼叫的startActivity實際上是講引數傳遞給ActivityManagerService並執行ActivityManagerService的startActivity方法。

既然這樣,我們看一下ActivityManagerService的startActivity方法:

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

呼叫了startActivityAsUser方法,然後我們繼續看一下startActivityAsUser方法:

@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

繼續檢視startActivityMayWait方法:

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 config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
        ...

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

            ...

            return res;
        }
    }

這個方法的邏輯比較多,我們重點關注的是其呼叫了startActivityLocked方法,也就是說在初始化其他邏輯之後,這個方法會呼叫startActivityLocked方法:

err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

程式碼量也是比較大的,在方法體中呼叫了startActivityUncheckedLocked方法,然後我們繼續跟進startActivityUncheckedLocked方法:

targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);

然後我們檢視startActivityLocked方法的實現:

if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }

可以發現其呼叫了resumeTopActivitiesLocked方法:

stack.resumeTopActivityLocked(null);

繼續跟進:

final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }

然後我們看一下resumeTopActivityLocked方法的實現:

result = resumeTopActivityInnerLocked(prev, options);

繼續檢視resumeTopActivityInnerLocked方法的實現:

mStackSupervisor.startSpecificActivityLocked(next, true, true);

可以發現在方法體中執行了相關邏輯判斷與初始化操作之後呼叫了startSpecificActivityLocked方法:

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);

可以發現在方法體中呼叫了startProcessLocked方法,從名字可以看出來這個方法就是啟動程序的。

final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

檢視startProcessLocked方法的實現:

checkTime(startTime, "startProcess: stepping in to startProcess");
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");

檢視startProcessLocked方法的具體實現;

checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, "startProcess: returned from zygote!");

檢視關鍵程式碼,這裡呼叫了Process.start方法:

public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

這裡的processClass就是要啟動的程序的名稱,這裡傳遞的就是ActivityThread:

"android.app.ActivityThread"

具體的Process啟動程序的Native層程式碼這裡不做過多的分析,這個方法就是啟動了AcitivtyThread程序並執行了ActivityThread的main方法,所以我們經常說的程序的啟動方法就是ActivityThread的main方法就是這裡體現的。

總結:

  • android應用程序會在需要啟動其元件的時候啟動,當沒有任何元件執行或者是系統記憶體較低的時候應用程序會被殺死。

  • 在啟動應用四大元件的時候若發現當前應用的程序沒有啟動,則會首先啟動應用程式的程序。

  • 我們可以為應用程式配置多個程序,每個程序都有自己的JVM和執行環境,各個程序之間的通訊需要通過Binder機制。

  • Launcher啟動的過程也是先啟動Launcher程序再啟動其Activity元件。