Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> android源碼解析之(十一)--)應用進程啟動流程

android源碼解析之(十一)--)應用進程啟動流程

編輯:關於android開發

android源碼解析之(十一)--)應用進程啟動流程


在android guide中有這樣的一段關於android應用程序進程的描述:

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應用中的組件需要被執行的時候啟動這個應用進程,並且會在這個應用進程沒有任何組件執行或者是系統需要為其他應用申請更多內存的時候殺死這個應用進程。所以當我們需要啟動這個應用的四大組件之一的時候如果這個應用的進程還沒有啟動,那麼就會先啟動這個應用程序進程。

本節主要是通過分析Activity的啟動過程介紹應用程序進程的啟動流程。

在上一篇文章中我們簡要的介紹了Launcher的啟動流程,在SystemServer進程執行完成,各種系統服務啟動完成之後,會調用ActivityManagerService中的systemReady()方法,在systemReady()方法中會執行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);
    }

好吧,最後調用的還是這個重載方法:

= 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);
            }
        }
    }" data-snippet-id="ext.a4d05821523ca3cace9fa20a2ea364f3" data-snippet-saved="false" data-codota-status="done">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組件。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved