android启动流程浅谈(代码片段)

ShouCeng ShouCeng     2022-11-03     270

关键词:

一、开机启动流程:

Android系统启动是由BootLoader引导开机,然后依次进入kernel、Native、Framework、App。

二、冷起进程创建流程:

进程的创建,主要涉及到两个进程的通信
system_server进程和Zygote进程:

  • system_server进程:是用于管理整个Java framework层,包含ActivityManager,PowerManager等各种系统服务;
  • Zygote进程:是Android系统的首个Java进程,Zygote是所有Java进程的父进程,包括 system_server进程以及所有的App进程都是Zygote的子进程,注意这里说的是子进程。

1、AMS发送请求启动进程

//文件位置:/Users/XXX/Library/Android/sdk/sources/android-30/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")
final ProcessRecord startProcessLocked(。。。) 
    return mProcessList.startProcessLocked(。。。);


//文件位置:/Users/duanshoucheng/Library/Android/sdk/sources/android-30/com/android/server/am/ProcessList.java
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
        int mountExternal, String seInfo, String requiredAbi, String instructionSet,
        String invokeWith, long startTime) 
    try 
        final Process.ProcessStartResult startResult;
        if (hostingRecord.usesWebviewZygote()) 
            startResult = startWebView(。。。); //Process.startWebView,是静态方法
         else 
            startResult = Process.start(。。。);
        
        checkSlow(startTime, "startProcess: returned from zygote!");
        return startResult;
     finally 
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    


//文件位置:/Users/duanshoucheng/Library/Android/sdk/sources/android-30/android/os/Process.java
Process.start(...) ->ZYGOTE_PROCESS.start(...) -> ... -> zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),...);  //会有两次机会和Zygote进程match。这里是LocalSocket

HostRecord构造参数HostingType,可取值:“activity”,“service”, “broadcast”, “contentProvider”
Java层进程的创建都是通过Process.start()方法,告知Zygote进程创建fork子进程,创建新进程后将ActivityThread类加载到新进程,并调用ActivityThread.main()方法。

2、Zygote处理请求

zygote进程在系统开机时就创建了。

//文件位置:/Users/xxx/Library/Android/sdk/sources/android-30/com/android/internal/os/ZygoteInit.java
@UnsupportedAppUsage
public static void main(String[] argv) 
        ZygoteServer zygoteServer = null;
         ...
        try 
            ...
            // 跟进该方法内,可以看到都是提前加载框架通用类和系统资源等
            if(!enableLazypreload)
                preload(bootTimingsTraceLog);
            
            ...
            // 创建zygote进程的socket server服务端对象
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            
            if (startSystemServer) 
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) 
                    r.run();
                    return;
                
            
            ...
            // 等待AMS发请求过来
            caller = zygoteServer.runSelectLoop(abiList);
            ...
        
        ...
    
    
    //文件位置:/Users/xxx/Library/Android/sdk/sources/android-30/com/android/internal/os/ZygoteServer.java
 ZygoteServer.runSelectLoop(...) ->
 ZygoteConnection.processCommand -> handleChildProc(...);
 private Runnable handleChildProc(ZygoteArguments parsedArgs,
            FileDescriptor pipeFd, boolean isZygote) 
       ...
        if (parsedArgs.mInvokeWith != null) 
           ...
         else 
            if (!isZygote) 
                // 继续进入ZygoteInit#zygoteInit继续完成子应用进程的相关初始化工作
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mDisabledCompatChanges,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            
        
    

3、应用进程初始化

public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) 
   
    RuntimeInit.redirectLogStreams();

    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit(); //native方法,jni调用启动进程的binder线程池
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
            classLoader);

应用进程至此就启动了,启动之后需要main方法的入口:

//文件位置:/Users/xxx/Library/Android/sdk/sources/android-30/com/android/internal/os/RuntimeInit.java

protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) 
    ...
    final Arguments args = new Arguments(argv);
    // Remaining arguments are passed to the start class's static main
    return findStaticMain(args.startClass, args.startArgs, classLoader);


protected static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) 
    Class<?> cl;

    try 
        //反射加载创建ActivityThread类对象
        cl = Class.forName(className, true, classLoader);
     catch (ClassNotFoundException ex) 
        throw new RuntimeException(
                "Missing class when invoking static main " + className, ex);
    

    Method m;
    try 
        //反射调用main方法
        m = cl.getMethod("main", new Class[]  String[].class );
     catch (NoSuchMethodException ex) 
        throw new RuntimeException(
                "Missing static main on " + className, ex);
     catch (SecurityException ex) 
        throw new RuntimeException(
                "Problem getting static main on " + className, ex);
    

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) 
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    
    /*
     * This throw gets caught in ZygoteInit.main(), which responds
     * by invoking the exception's run() method. This arrangement
     * clears up all the stack frames that were required in setting
     * up the process.
     */
    return new MethodAndArgsCaller(m, argv);


//内部静态类
static class MethodAndArgsCaller implements Runnable 
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) 
        mMethod = method;
        mArgs = args;
    

    public void run() 
        try 
            mMethod.invoke(null, new Object[]  mArgs );
         ...
    

4、新进程app

//文件位置:/Users/xxx/Library/Android/sdk/sources/android-30/android/app/ActivityThread.java
public static void main(String[] args) 
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) 
        sMainThreadHandler = thread.getHandler();
    
    Looper.loop();


@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread(); //内部类,继承IApplicationThread.Stub

@UnsupportedAppUsage
private void attach(boolean system, long startSeq) 
    
    RuntimeInit.setApplicationObject(mAppThread.asBinder());
    final IActivityManager mgr = ActivityManager.getService();
    mgr.attachApplication(mAppThread, startSeq);

简单总结下:
初始化完,主线程就有了完整的 Looper、MessageQueue、Handler,此时 ActivityThread 的 Handler 就可以开始处理 Message,包括 Application、Activity、ContentProvider、Service、Broadcast 等组件的生命周期函数,都会以 Message 的形式,在主线程按照顺序处理。

5、总结

应用进程的启动是被动式的,在桌面点击图标启动一个组件如Activity实,如果该进程不存在,就会创建并启动进程。应用进程是由Zygote进程fork创建的,AMS在需要创建应用进程时,会通过socket并通知到Zygote进程进程在开机阶段就创建好的socket服务端,然后由Zygote进程fork创建出应用进程。

三、Service启动流程

1、startService调用链

启动方式:startService()和binderService()。也是由ActivityManagerService来完成。
Launcher#startService()–> ContextWrapper#startService()–>ContextImpl#startService() -->

//文件位置:/Users/xxx/Library/Android/sdk/sources/android-30/android/app/ContextImpl.java
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) 
    try 
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this); //ActivityManagerService
        ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                getOpPackageName(), getAttributionTag(), user.getIdentifier());
        ...
        return cn;
     catch (RemoteException e) 
        throw e.rethrowFromSystemServer();
    

获取AMS:

//文件位置:/Users/xxx/Library/Android/sdk/sources/android-30/android/app/ActivityManager.java
@UnsupportedAppUsage
public static IActivityManager getService() 
    return IActivityManagerSingleton.get(); //其实就是ActivityManagerService,AMS也是继承该类


private static IActivityTaskManager getTaskService() 
    return ActivityTaskManager.getService();


@UnsupportedAppUsage
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;
            
        ;
// AMS
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage,
        String callingFeatureId, int userId)
        throws TransactionTooLargeException 
           ...
        ComponentName res;
        try 
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, callingFeatureId, userId);
         finally 
            Binder.restoreCallingIdentity(origId);
        
        return res;
    

参数:

  • caller:类型是IApplicationThread,是ActivityThread.java内部类,IApplicationThread.Stub的子类
  • service:Intent类型,包含需要运行的service信息
  • callingPackage: String类型,调用该方法的package
    然后ActiveService#startServiceLocked -> ActiveService#startServiceInnerLocked->ActiveService#bringUpServiceLocked
//文件位置: /Users/xxx/Library/Android/sdk/sources/android-30/com/android/server/am/ActiveService.java

//2848行,bindService最后也会走这里
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException 
    if (r.app != null && r.app.thread != null) 
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    
    ....
        if (app != null && app.thread != null) 
            try 
                app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                realStartServiceLocked(r, app, execInFg); //启动服务
                return null;
            ...
            

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

    // 进程没启动,需要启动进程
    if (app == null && !permissionsReviewRequired) 
        if ((app=mAm.startProcessLocked(...) 
            ...
        
    
...
    return null;

总结下:该方法流程比较多,重要的是realStartServiceLocked和startProcessLocked两个启动方法,如果进程不存在,执行AMS#startProcessLocked–>AMS#attachApplicationLocked,然后执行realStartServiceLocked.

2、startProcessLocked创建进程

AMS#startProcessLocked -> ProcessList#startProcessLocked,之后的流程参考第二节,下面是第二节之后继续执行的流程:

//AMS.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) 
    if (thread == null) 
        throw new SecurityException("Invalid application interface");
    
    synchronized (this) 
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    


private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) 
        ...
        
        thread.bindApplication(processName, appInfo, providerList,
        instr2.mClass,
        profilerInfo, instr2.mArguments,
        instr2.mWatcher,
        instr2.mUiAutomationConnection, testMode,
        mBinderTransactionTrackingEnabled, enableTrackAllocation,
        isRestrictedBackupMode || !normalMode, app.isPersistent(),
        new Configuration(app.getWindowProcessController().getConfiguration()),
        app.compat, getCommonServicesLocked(app.isolated),
        mCoreSettingsObserver.getCoreSettingsLocked(),
        buildSerial, autofillOptions, contentCaptureOptions,
        app.mDisabledCompatChanges);
        ...
        
// Find any services that should be running in this process...
        if (!badApp) 
            try 
                didSomething |= mServices.attachApplicationLocked(app, processName);
            //mServices是ActiveService    

继续

boolean attachApplicationLocked(ProcessRecord proc, String processName)
        throws RemoteException 
    boolean didSomething = false;
    // Collect any services that are waiting for this process to come up.
    if (mPendingServices.size() > 0) 
                ...
                realStartServiceLocked(sr, proc, sr.createdFromFg);
                didSomething = true;
                ...
    
    return didSomething;

看到了吧,第6行,创建了新的进程之后,会继续执行ActiveService#realStartServiceLocked。
忽略第2小节,继续第1小节的流程:realStartServiceLocked().

3、realStartServiceLocked继续启动服务

//文件位置: /Users/xxx/Library/Android/sdk/sources/android-30/com/android/server/am/ActiveService.java
private final void realStartServiceLoc

android启动流程浅谈(代码片段)

一、开机启动流程:Android系统启动是由BootLoader引导开机,然后依次进入kernel、Native、Framework、App。二、冷起进程创建流程:进程的创建,主要涉及到两个进程的通信system_server进程和Zygote进程:system_server进程&... 查看详情

android开发浅谈之packagemanagerservice(pkms)(代码片段)

本文基于Android10.0主要从以下几个方面着手:PKMS启动PKMS安装APKPKMS卸载APKPKMS启动这里我简单的将其分为以下几个步骤:1.SystemServer通过PKMS的main方法启动PKMS2.PKMS构造方法中初始化Settings3.扫描各个系统目录下APP相关信息1.Sys... 查看详情

android开发浅谈之packagemanagerservice(pkms)(代码片段)

本文基于Android10.0主要从以下几个方面着手:PKMS启动PKMS安装APKPKMS卸载APKPKMS启动这里我简单的将其分为以下几个步骤:1.SystemServer通过PKMS的main方法启动PKMS2.PKMS构造方法中初始化Settings3.扫描各个系统目录下APP相关信息1.Sys... 查看详情

android启动过程android应用启动流程|activity启动流程(代码片段)

文章目录一、Android系统启动流程二、Activity启动流程一、Android系统启动流程打开Android手机电源键后,先运行BootLoader,然后使用BootLoader加载LinuxKernel,之后会启动init进程,init进程会启动Zygote(受精卵)进程,Zygote进程会调用system_server进... 查看详情

说说android系统的启动流程(代码片段)

Android系统的启动流程Android系统的启动流程可以分三部分来分析,Android系统有哪些主要的系统进程?这些系统进程是怎么启动的?启动之后都做了什么事?首先看下图,分三个阶段介绍Android系统的启动流程... 查看详情

android:图解activity启动流程源码(整体流程)(代码片段)

Intentintent=newIntent(this,TestActivity.class);startActivity(intent);以上代码对于Android开发者再熟悉不过了,功能即启动TextActivity。这是最基本的Intent使用知识,通过显示Intent来触发Activity的启动,而Activity,四大组件中 查看详情

android启动过程activity启动源码分析(activitythread流程分析二)(代码片段)

文章目录前言一、ActivityManagerService.attachApplicationLocked二、ActivityStackSupervisor.attachApplicationLocked三、ActivityStackSupervisor.realStartActivityLocked前言在上一篇博客【Android启动过程】Activity启动源码分析(ActivityThre 查看详情

tomcat组件架构图梳理(代码片段)

本文适合有基础的小伙伴,如果你对tomcat启动及请求的流程处理不熟悉,可能看起来会比较吃力。有兴趣了解的小伙伴可以参考我之前的博客,希望对你有帮助:浅谈Tomcat的启动流程(源码级别)浅谈Tomcat... 查看详情

tomcat组件架构图梳理(代码片段)

本文适合有基础的小伙伴,如果你对tomcat启动及请求的流程处理不熟悉,可能看起来会比较吃力。有兴趣了解的小伙伴可以参考我之前的博客,希望对你有帮助:浅谈Tomcat的启动流程(源码级别)浅谈Tomcat... 查看详情

android启动-application的启动流程(代码片段)

基于Android11-API30总览获取applicationThread,AMS这两个Binder2.attach时,将获取applicationThread对象也传递到AMS进程,请求远程调用通知AMS应用进程想要创建Application,此时AMS为服务端AMS收到消息,请求调用applicationThread... 查看详情

android逆向android进程简介(android应用启动流程)(代码片段)

文章目录前言一、Android进程二、Android应用启动流程前言参考【Android逆向】Android系统文件分析(/proc/pid进程号对应进程目录|oom_adj|maps|smaps|mem|task|environ)博客,/proc/目录中存放的是所有进程相关信息;一、Android进程Android操作系统中... 查看详情

android逆向android进程简介(android应用启动流程)(代码片段)

文章目录前言一、Android进程二、Android应用启动流程前言参考【Android逆向】Android系统文件分析(/proc/pid进程号对应进程目录|oom_adj|maps|smaps|mem|task|environ)博客,/proc/目录中存放的是所有进程相关信息;一、Android进程Android操作系统中... 查看详情

android系统启动流程分析(代码片段)

...在做系统启动耗时优化,之前看了两遍罗升阳大神《Android系统源代码情景分析》都只是看了,没有实践,没有运用到项目中,因此借项目在做系统优化的机会,再次将Android系统的启动流程细细的在撸一遍࿰... 查看详情

android启动过程activity启动源码分析(activitythread流程分析一)(代码片段)

文章目录一、ActivityThread主函数启动二、ActivityThread绑定ApplicationThread三、AMSattachApplication->attachApplicationLocked绑定ApplicationThread四、ApplicationThread.bindApplication绑定ApplicationThread五、ActivityThread. 查看详情

android应用启动流程分析(代码片段)

1前言网上看过很多Activity启动过程的源码解析,很多文章会贴上一大段代码,然后从startActivity()函数开始深究整个源码的调用栈。个人感觉这类文章代码细节太多,反而容易迷失在源码调用之中,从而忽略了Activit... 查看详情

android7.0系统启动流程分析(代码片段)

随着Android版本的升级,aosp项目中的代码也有了些变化,本文基于Android7.0分析Android系统启动流程.当我们按下电源键后,整个Android设备大体经过了一下过程:今天我们只想来分析init进程及其后的过程,也就是下图所示部分:init进程init进... 查看详情

android系统启动流程分析(代码片段)

一、启动初探在android手机上,当我们点击桌面上的按钮启动一个应用,就能打开应用的界面。这里我们所说的桌面其实就是android系统启动后的就已经帮我们运行的第一个程序,launcher程序。launcher程序可以理解为作为... 查看详情

android7.0应用冷启动流程分析(代码片段)

最近在为自己MotoG定制Rom,顺便重新读了一遍Android7.0的相关源码,特此记录当做笔记.在开始正文之前,首先要明白冷启动和热启动.所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会创建一个进程分配给它(AMS通过Socket... 查看详情