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组件。

另外对android源码解析方法感兴趣的可参考我的:
android源码解析之(一)–>android项目构建过程
android源码解析之(二)–>异步消息机制
android源码解析之(三)–>异步任务AsyncTask
android源码解析之(四)–>HandlerThread
android源码解析之(五)–>IntentService
android源码解析之(六)–>Log
android源码解析之(七)–>LruCache
android源码解析之(八)–>Zygote进程启动流程
android源码解析之(九)–>SystemServer进程启动流程
android源码解析之(十)–>Launcher启动流程


本文以同步至github中:https://github.com/yipianfengye/androidSource,欢迎star和follow


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_23547831/article/details/51119333
个人分类: android源码解析
所属专栏: android源码解析
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭