ActivityThread应用进程

Posted xhBruce

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ActivityThread应用进程相关的知识,希望对你有一定的参考价值。

ActivityThread应用进程

android12-release


涉及进程

  • system_server进程:启动和管理整个Java framework中服务;
  • Zygote进程:init进程fork第一个Java进程,Zygote是所有Java进程的父进程,包括system_server进程以及所有的App进程都是Zygote的子进程,注意这里说的是子进程,而非子线程。

时序图

简明流程图

  1. Launcher/App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,则发送进程便是该App所在进程。发起进程先通过binder发送消息给system_server进程。
  2. system_server进程:调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求。
  3. zygote进程:在执行ZygoteInit.main()后便进入zygoteServer.runSelectLoop()循环体内,当有客户端连接时便会执行ZygoteConnection.processCommand()方法,最后fork出新的应用进程。
  4. 新进程:执行handleChildProc()方法,最后调用ActivityThread.main()方法。

system_server进程中调用Process.start()方法

frameworks/base/core/java/android/os/Process.java
frameworks/base/core/java/android/os/ZygoteProcess.java

  • argsForZygote数组保存了进程的uid、gid、groups、target-sdk-version、nice-name等一系列参数。
  • openZygoteSocketIfNeeded(abi)根据当前的abi来选择与zygote还是zygote64来进行通信。通过socket向Zygote进程发送消息。
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                  @Nullable final String niceName,
                                                  final int uid, final int gid,
                                                  @Nullable final int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  boolean startChildZygote,
                                                  @Nullable String packageName,
                                                  int zygotePolicyFlags,
                                                  boolean isTopApp,
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          pkgDataInfoMap,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          allowlistedDataInfoList,
                                                  boolean bindMountAppsData,
                                                  boolean bindMountAppStorageDirs,
                                                  @Nullable String[] extraArgs)
                                                  throws ZygoteStartFailedEx 
    ArrayList<String> argsForZygote = new ArrayList<>();

    // --runtime-args, --setuid=, --setgid=,
    // and --setgroups= must go first
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    argsForZygote.add("--runtime-flags=" + runtimeFlags);
    if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) 
        argsForZygote.add("--mount-external-default");
     else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) 
        argsForZygote.add("--mount-external-installer");
     else if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) 
        argsForZygote.add("--mount-external-pass-through");
     else if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) 
        argsForZygote.add("--mount-external-android-writable");
    

    argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

    // --setgroups is a comma-separated list
    if (gids != null && gids.length > 0) 
        final StringBuilder sb = new StringBuilder();
        sb.append("--setgroups=");

        final int sz = gids.length;
        for (int i = 0; i < sz; i++) 
            if (i != 0) 
                sb.append(',');
            
            sb.append(gids[i]);
        

        argsForZygote.add(sb.toString());
    

    if (niceName != null) 
        argsForZygote.add("--nice-name=" + niceName);
    

    if (seInfo != null) 
        argsForZygote.add("--seinfo=" + seInfo);
    

    if (instructionSet != null) 
        argsForZygote.add("--instruction-set=" + instructionSet);
    

    if (appDataDir != null) 
        argsForZygote.add("--app-data-dir=" + appDataDir);
    

    if (invokeWith != null) 
        argsForZygote.add("--invoke-with");
        argsForZygote.add(invokeWith);
    

    if (startChildZygote) 
        argsForZygote.add("--start-child-zygote");
    

    if (packageName != null) 
        argsForZygote.add("--package-name=" + packageName);
    

    if (isTopApp) 
        argsForZygote.add(Zygote.START_AS_TOP_APP_ARG);
    
    if (pkgDataInfoMap != null && pkgDataInfoMap.size() > 0) 
        StringBuilder sb = new StringBuilder();
        sb.append(Zygote.PKG_DATA_INFO_MAP);
        sb.append("=");
        boolean started = false;
        for (Map.Entry<String, Pair<String, Long>> entry : pkgDataInfoMap.entrySet()) 
            if (started) 
                sb.append(',');
            
            started = true;
            sb.append(entry.getKey());
            sb.append(',');
            sb.append(entry.getValue().first);
            sb.append(',');
            sb.append(entry.getValue().second);
        
        argsForZygote.add(sb.toString());
    
    if (allowlistedDataInfoList != null && allowlistedDataInfoList.size() > 0) 
        StringBuilder sb = new StringBuilder();
        sb.append(Zygote.ALLOWLISTED_DATA_INFO_MAP);
        sb.append("=");
        boolean started = false;
        for (Map.Entry<String, Pair<String, Long>> entry : allowlistedDataInfoList.entrySet()) 
            if (started) 
                sb.append(',');
            
            started = true;
            sb.append(entry.getKey());
            sb.append(',');
            sb.append(entry.getValue().first);
            sb.append(',');
            sb.append(entry.getValue().second);
        
        argsForZygote.add(sb.toString());
    

    if (bindMountAppStorageDirs) 
        argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
    

    if (bindMountAppsData) 
        argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
    

    if (disabledCompatChanges != null && disabledCompatChanges.length > 0) 
        StringBuilder sb = new StringBuilder();
        sb.append("--disabled-compat-changes=");

        int sz = disabledCompatChanges.length;
        for (int i = 0; i < sz; i++) 
            if (i != 0) 
                sb.append(',');
            
            sb.append(disabledCompatChanges[i]);
        

        argsForZygote.add(sb.toString());
    

    argsForZygote.add(processClass);

    if (extraArgs != null) 
        Collections.addAll(argsForZygote, extraArgs);
    

    synchronized(mLock) 
        // The USAP pool can not be used if the application will not use the systems graphics
        // driver.  If that driver is requested use the Zygote application start path.
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                          zygotePolicyFlags,
                                          argsForZygote);
    

zygote进程中fork()\\RuntimeInit.applicationInit()

fork()

frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

相关日志Zygote : Forked child process 26092
am_proc_start: [0,26092,10264,com.tencent.mobileqq,pre-top-activity,com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity]
am_proc_bound: [0,26092,com.tencent.mobileqq]

// Utility routine to fork a process from the zygote.
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
                         const std::vector<int>& fds_to_close,
                         const std::vector<int>& fds_to_ignore,
                         bool is_priority_fork,
                         bool purge) 
  SetSignalHandlers();

  // Curry a failure function.
  auto fail_fn = std::bind(zygote::ZygoteFailure, env,
                           is_system_server ? "system_server" : "zygote",
                           nullptr, _1);

  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
  // log, which would result in the logging FDs we close being reopened.
  // This would cause failures because the FDs are not allowlisted.
  //
  // Note that the zygote process is single threaded at this point.
  BlockSignal(SIGCHLD, fail_fn);
  // ... ...
  pid_t pid = fork();

  if (pid == 0) 
    // ... ...
   else 
    ALOGD("Forked child process %d", pid);
  
  // ... ...
  return pid;

bionic/libc/bionic/fork.cpp
bionic/libc/bionic/pthread_atfork.cpp

fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次,返回值有3种类型。

  • 父进程中,fork返回新创建的子进程的pid;
  • 子进程中,fork返回0;
  • 当出现错误时,fork返回负数。(当进程数超过上限或者系统内存不足时会出错)
int fork() 
  __bionic_atfork_run_prepare();

  int result = __clone_for_fork();

  if (result == 0) 
    // Disable fdsan and fdtrack post-fork, so we don't falsely trigger on processes that
    // fork, close all of their fds, and then exec.
    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
    android_fdtrack_set_globally_enabled(false);

    // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
    // parent process.
    __set_stack_and_tls_vma_name(true);

    __bionic_atfork_run_child();
   else 
    __bionic_atfork_run_parent();
  
  return result;

RuntimeInit.applicationInit()

  • 此处args.startClass为”android.app.ActivityThread”。
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) 
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    
  • 反射调用到ActivityThread.main()
Class<?> cl = Class.forName(className, true, classLoader);
Method m = cl.getMethod("main", new Class[]  String[].class );
mMethod.invoke(null, new Object[]  mArgs );

ActivityThread.main

  • 如果是startActivity则将要进入Activity的onCreate/onStart/onResume等生命周期。
  • 如果是startService则将要进入Service的onCreate等生命周期。

以上是关于ActivityThread应用进程的主要内容,如果未能解决你的问题,请参考以下文章

Android ActivityThread(主线程或UI线程)简介

Android 桌面应用启动APP的流程

Android 桌面应用启动APP的流程

Android 源码分析 Activity 启动

Android 源码分析 Activity 启动

Windows 7 中一个进程的 GDI 对象上限是多少?