Android进阶笔记-1. Android系统启动流程

1,219 阅读11分钟

init进程

从启动电源到init

  • 启动电源以及系统启动:

    • 当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。
  • 引导程序Bootloader

    • 引导程序是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
  • linux内核启动

    • 内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。
    • 当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。
  • init进程启动

    • 创建一些文件夹并挂载设备
    • 初始化和启动属性服务
    • 解析init.rc配置文件并启动zygote进程
  • 前面几步过于底层,下面我们主要看看真正涉及到Android系统的init进程

init入口函数

  • system/core/init/init.cpp
  • 入口函数为main
    • 初始化属性相关资源: property_init();
    • 启动属性服务: start_property_service();
    • 解析init.rc配置文件: parser.ParseConfig("/init.rc");

init.rc

  • system/core/rootdir/init.rc
  • init.rc是一个配置文件,内部由Android初始化语言(Android Init Language)编写的脚本;
  • 主要包含五种类型语句:Action、Commands、Services、Options和Import。
  • 在Android 7.0中对init.rc文件进行了拆分,每个服务一个rc文件。我们要分析的zygote服务的启动脚本则在init.zygoteXX.rc中定义,这里拿64位处理器为例system/core/rootdir/init.zygote64.rc;
//其中service用于通知init进程创建名zygote的进程,这个zygote进程执行程序的路径为/system/bin/app_process64,后面的则是要传给app_process64的参数。class main指的是zygote的class name为main

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

解析service

  • system/core/init/service.cpp
  • 两个主要函数:
    • ParseSection函数: 解析service的rc文件,比如上文讲到的init.zygote64.rc,主要用来搭建service的架子。
    • ParseLineSection函数用于解析子项。

init启动zygote

  • system/core/rootdir/init.rc
  • init启动zygote时主要是调用app_main.cpp的main函数中的AppRuntime的start函数来启动zygote进程;
on nonencrypted    
    # A/B update verifier that marks a successful boot.  
    exec - root -- /system/bin/update_verifier nonencrypted  
    class_start main         
    class_start late_start 
//之前提到zygote的class name为main,因此class_start main用来启动zygote

属性服务

  • 类似Windows平台的注册表管理器
  • system/core/init/init.cpp中和属性服务相关的代码有:
property_init();
start_property_service();
//初始化属性服务配置并启动属性服务

Zygote进程

Zygote简介

  • 也称为孵化器,创建了DVM(Dalvik虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程;
  • 由于Zygote进程在启动时会创建DVM,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM的实例拷贝。
  • 主要步骤:
    • 创建AppRuntime并调用其start方法,启动Zygote进程。
    • 创建DVM并为DVM注册JNI.
    • 通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。
    • 通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用程序进程。
    • 启动SystemServer进程。
  • 入口:frameworks/base/cmds/app_process/app_main.cpp的main函数
int main(int argc, char* const argv[])
{
...

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
   ...
     Vector<String8> args;
    if (!className.isEmpty()) {
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();
        if (startSystemServer) {
            args.add(String8("start-system-server"));//1
        }
        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//2
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}
  • 注释1处如果startSystemServer为true的话(默认为true),将”start-system-server”放入启动的参数args。
  • 注释2处这里调用runtime的start函数来启动zygote进程,并将args传入,这样启动zygote进程后,zygote进程会将SystemServer进程启动。我们知道runtime指的就是AppRuntime,AppRuntime声明也在app_main.cpp中,它继承AndroidRuntime,也就是我们调用start其实是调用AndroidRuntime的start函数:
  • frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {//1
        return;
    }
    onVmCreated(env);
    if (startReg(env) < 0) {//2
        ALOGE("Unable to register all android natives\n");
        return;
    }
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    //创建数组
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    //从app_main的main函数得知className为com.android.internal.os.ZygoteInit
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
    //找到ZygoteInit的main函数
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");//3
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
        //通过JNI调用ZygoteInit的main函数
            env->CallStaticVoidMethod(startClass, startMeth, strArray);//4

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
  ...
}
  • 注释1处调用startVm函数来创建JavaVm(DVM)
  • 注释2处调用startReg函数用来为DVM注册JNI。
  • 注释3处的代码用来找到ZygoteInit的main函数,其中startClass从app_main的main函数得知为com.android.internal.os.ZygoteInit。
  • 注释4处通过JNI调用ZygoteInit的main函数,因为ZygoteInit的main函数是Java编写的,因此需要通过JNI调用。

Zygote的Java框架层

  • 上文我们通过JNI调用ZygoteInit的main函数后,Zygote便进入了Java框架层,此前没有任何代码进入过Java框架层,换句话说Zygote开创了Java框架层。
  • frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
   ...
   try {
    ...       
       //注册Zygote用的Socket
       registerZygoteSocket(socketName);//1
      ...
      //预加载类和资源
      preload();//2
      ...
       if (startSystemServer) {
       //启动SystemServer进程
           startSystemServer(abiList, socketName);//3
       }
       Log.i(TAG, "Accepting command socket connections");
       //等待客户端请求
       runSelectLoop(abiList);//4
       closeServerSocket();
   } catch (MethodAndArgsCaller caller) {
       caller.run();
   } catch (RuntimeException ex) {
       Log.e(TAG, "Zygote died with exception", ex);
       closeServerSocket();
       throw ex;
   }
}
  • 通过上面代码得知,ZygoteInit的main函数主要做了4件事:
    • registerZygoteSocket:创建LocalServerSocket,也就是服务端的Socket,当Zygote进程将SystemServer进程启动后,就会在这个服务端的Socket上来等待ActivityManagerService请求Zygote进程来创建新的应用程序进程。
    • 启动SystemServer进程:创建args数组,这个数组用来保存启动SystemServer的启动参数,将args数组封装成Arguments对象并供forkSystemServer函数调用。forkSystemServer函数通过fork函数在当前进程创建一个子进程,如果返回的pid为0,也就是表示在新创建的子进程中执行的,则执行handleSystemServerProcess来启动SystemServer进程。
    • runSelectLoop: 启动SystemServer 进程后,最后进入 runSelectLoop 函数

SyetemServer进程

SyetemServer进程的启动过程

  • 主要步骤:
    • 1.启动Binder线程池,这样就可以与其他进程进行通信。
    • 2.创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理。
    • 3.启动各种系统服务。
  • 上面说了ZygoteInit.java的startSystemServer函数中启动了SyetemServer进程;
  • 在startSystemServer函数中调用handleSystemServerProcess来启动SyetemServer进程,代码如下
private static boolean startSystemServer(String abiList, String socketName) 
    throws MethodAndArgsCaller, RuntimeException {
...
   if (pid == 0) {
       if (hasSecondZygote(abiList)) {
           waitForSecondaryZygote(socketName);
       }
       handleSystemServerProcess(parsedArgs);
   }
   return true;
}
  • handleSystemServerProcess代码:
private static void handleSystemServerProcess(
      ZygoteConnection.Arguments parsedArgs)
      throws ZygoteInit.MethodAndArgsCaller {
  closeServerSocket();
  //SyetemServer进程是复制了Zygote进程的地址空间,因此也会得到Zygote进程创建的Socket,
  //这个Socket对于SyetemServer进程没有用处,因此,需要关闭该Socket。
...
  if (parsedArgs.invokeWith != null) {
     ...
  } else {
      ClassLoader cl = null;
      if (systemServerClasspath != null) {
          cl = createSystemServerClassLoader(systemServerClasspath,
                                             parsedArgs.targetSdkVersion);
          Thread.currentThread().setContextClassLoader(cl);
      }
      
      //调用RuntimeInit的zygoteInit函数
      RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
  }
}
  • 上面代码调用了调用RuntimeInit的zygoteInit函数,zygoteInit函数中又调用了nativeZygoteInit函数,代码如下,其主要做的就是启动Binder线程池,这样SyetemServer进程就可以使用Binder来与其他进程进行通信了。
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
    redirectLogStreams();
    commonInit();
    nativeZygoteInit();//1
    applicationInit(targetSdkVersion, argv, classLoader);//2
}
  • 上面applicationInit函数中主要调用了invokeStaticMain函数,invokeStaticMain最终通过反射调用到SystemServer的main函数;
  • frameworks/base/services/java/com/android/server/SystemServer.java的main函数如下:
public static void main(String[] args) {
   new SystemServer().run();
}
  • 可以看到main函数中只调用了SystemServer的run函数
private void run() {
   ...
        //加载了libandroid_servers.so
       System.loadLibrary("android_servers");
   ...
        //创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。
       mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
       LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
   ...    
    try {
       Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
       
       //startBootstrapServices函数中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。
       startBootstrapServices();
       
       //startCoreServices函数启动了BatteryService、UsageStatsService和WebViewUpdateService。
       startCoreServices();
       
       //startOtherServices函数中则启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类为SystemService。
       startOtherServices();
   } catch (Throwable ex) {
       Slog.e("System", "******************************************");
       Slog.e("System", "************ Failure starting system services", ex);
       throw ex;
   } finally {
       Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
   }
   ...
}
  • 由上面代码可以看出官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务;
  • 比如要启动PowerManagerService则会调用如下代码:
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
  • SystemServiceManager的startService函数如下
  public <T extends SystemService> T startService(Class<T> serviceClass) {
...
        final T service;
        try {
            //创建入参类型的SystemService,如PowerManagerService
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service could not be instantiated", ex);
        }
...
        // Register it.
        //将PowerManagerService添加到mServices中,这里mServices是一个存储SystemService类型的ArrayList
        mServices.add(service);//2
        // Start it.
        try {
            //接着调用PowerManagerService的onStart函数启动PowerManagerService并返回,这样就完成了PowerManagerService启动的过程。
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + name
                    + ": onStart threw an exception", ex);
        }
        return service;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }
}
  • 除了用mSystemServiceManager的startService函数来启动系统服务外,也可以通过如下形式来启动系统服务,以PackageManagerService为例:
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
               mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//直接调用了PackageManagerService的main函数

Launcher进程

Launcher的启动流程

  • 前面讲了init进程、Zygote进程和SyetemServer进程的启动过程,现在就来到了Android系统启动流程的最后一步,Launcher的启动流程;
  • Android系统启动的最后一步是启动一个Home应用程序,这个应用程序用来显示系统中已经安装的应用程序,这个Home应用程序就叫做Launcher。
  • 应用程序Launcher在启动过程中会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序。
  • SyetemServer进程在启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。在此前已经启动的ActivityManagerService会将Launcher启动起来。
  • 启动Launcher的入口为ActivityManagerService的systemReady函数,代码如下:
    • frameworks/base/services/java/com/android/server/SystemServer.java

 private void startOtherServices() {
 ...
  mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                Slog.i(TAG, "Making services ready");
                mSystemServiceManager.startBootPhase(
                      SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
}
  • 经过多次调用,最终会调用到startHomeActivityLocked
boolean startHomeActivityLocked(int userId, String reason) {
     if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
             && mTopAction == null) {//1
         return false;
     }
     Intent intent = getHomeIntent();//2
     ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
     if (aInfo != null) {
         intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
         aInfo = new ActivityInfo(aInfo);
         aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
         ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                 aInfo.applicationInfo.uid, true);
         if (app == null || app.instrumentationClass == null) {//3
             intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
             mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);//4
         }
     } else {
         Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
     }

     return true;
 }
  • 上面的getHomeIntent函数代码如下:
Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}
  • mTopAction的值为Intent.ACTION_MAIN, 并且如果系统运行模式不是低级工厂模式则将intent的Category设置为Intent.CATEGORY_HOME。假设系统的运行模式不是低级工厂模式,则判断符合Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME的应用程序是否已经启动,如果没启动则调用mActivityStarter.startHomeActivityLocked方法启动该应用程序。
  • 这个被启动的应用程序就是Launcher,因为Launcher的Manifest文件中的intent-filter标签匹配了Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME。
  • 这样,应用程序Launcher就会被启动起来,并执行它的onCreate函数。

Launcher中应用图标显示流程

//加载系统已经安装的应用程序信息:
private void loadAndBindAllApps() {
    if (DEBUG_LOADERS) {
        Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
    }
    if (!mAllAppsLoaded) {
        loadAllApps();//1
        synchronized (LoaderTask.this) {
            if (mStopped) {
                return;
            }
        }
        updateIconCache();
        synchronized (LoaderTask.this) {
            if (mStopped) {
                return;
            }
            mAllAppsLoaded = true;
        }
    } else {
        onlyBindAllApps();
    }
}
//如果系统没有加载已经安装的应用程序信息,则会调用注释1处的loadAllApps函数:
private void loadAllApps() {
...
    mHandler.post(new Runnable() {
        public void run() {
            final long bindTime = SystemClock.uptimeMillis();
            final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
            if (callbacks != null) {
                callbacks.bindAllApplications(added);//1
                if (DEBUG_LOADERS) {
                    Log.d(TAG, "bound " + added.size() + " apps in "
                            + (SystemClock.uptimeMillis() - bindTime) + "ms");
                }
            } else {
                Log.i(TAG, "not binding apps: no Launcher activity");
            }
        }
    });
   ...
}
//callbacks.bindAllApplications这个callbacks实际是指向Launcher的
public void bindAllApplications(final ArrayList<AppInfo> apps) {
    if (waitUntilResume(mBindAllApplicationsRunnable, true)) {
        mTmpAppsList = apps;
        return;
    }
    if (mAppsView != null) {
        mAppsView.setApps(apps);//1
    }
    if (mLauncherCallbacks != null) {
        mLauncherCallbacks.bindAllApplications(apps);
    }
}
//在注释1处会调用AllAppsContainerView的setApps函数,并将包含应用信息的列表apps传进去;
//包含应用信息的列表apps已经传给了AllAppsContainerView,查看AllAppsContainerView的onFinishInflate函数:
 @Override
protected void onFinishInflate() {
    super.onFinishInflate();
...
    // Load the all apps recycler view
    mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);//1
    mAppsRecyclerView.setApps(mApps);//2
    mAppsRecyclerView.setLayoutManager(mLayoutManager);
    mAppsRecyclerView.setAdapter(mAdapter);//3
    mAppsRecyclerView.setHasFixedSize(true);
    mAppsRecyclerView.addOnScrollListener(mElevationController);
    mAppsRecyclerView.setElevationController(mElevationController);
...
}
//onFinishInflate函数在加载完xml文件时就会调用,在注释1处得到AllAppsRecyclerView用来显示App列表,并在注释2处将apps的信息列表传进去,并在注释3处为AllAppsRecyclerView设置Adapter。这样应用程序快捷图标的列表就会显示在屏幕上。

Android系统启动流程

  1. 启动电源以及系统启动
    • 当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。
  2. 引导程序BootLoader
    • 引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
  3. Linux内核启动
    • 内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。
  4. init进程启动
    • 初始化和启动属性服务,并且启动Zygote进程。
  5. Zygote进程启动
    • 创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动SystemServer进程。
  6. SystemServer进程启动
    • 启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
  7. Launcher启动
    • 被SystemServer进程启动的ActivityManagerService会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。

我是今阳,如果想要进阶和了解更多的干货,欢迎关注微信公众号 “今阳说” 接收我的最新文章