Android源码分析挖掘(二) fork大师zygote进程

序言

上一篇Android源码分析挖掘(一) 开天辟地init进程分析了Android系统从按下开机键到init进程启动服务的过程,init进程启动了很多服务,如Zygote,ServiceManager,SurfaceFlinger等,本片分析一下Zygote进程被启动后都干了些啥。

上篇介绍了init进程通过init.rc文件启动了服务,那么Zygote服务是在init.rc哪一条指令被定义的呢,回到源码init.rc文件,路径:system/core/rootdir/init.rc

复制代码
# Copyright (C) 2012 The Android Open Source Project
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#

import /init.environ.rc
import /system/etc/init/hw/init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /system/etc/init/hw/init.usb.configfs.rc
import /system/etc/init/hw/init.${ro.zygote}.rc

...

可以看到,import /system/etc/init/hw/init.${ro.zygote}.rc,这一行的import的意思就是读取这个路径文件的所有内容,在init进程启动服务时,会一并启动。

在init.rc同目录下就能找到几个对应的文件:init.zygote32_64.rc、``init.zygote32.rc、``init.zygote64_32.rc、``init.zygote64.rc,具体import哪个文件与具体设备硬件有关,这里就以init.zygote64.rc分析,代码内容如下:

复制代码
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

暂时可以只关注第一行,简单点认为,可以认为启动了/system/bin/app_process64这个程序,后面携带了一系列参数,这些参数需要重点关注,因为关系到后续是启动SystemServer还是app:

复制代码
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server

那么这个zygote程序源码在哪里呢?可以通过以上启动systemserver参数的字符串全局查找一下,命令如下:

复制代码
grep "start-system-server" ./ -rn


//搜索结果
./base/cmds/app_process/app_main.cpp:200:    // --start-system-server : Start the system server.
./base/cmds/app_process/app_main.cpp:269:        } else if (strcmp(arg, "--start-system-server") == 0) {
./base/cmds/app_process/app_main.cpp:310:            args.add(String8("start-system-server"));
./base/core/java/com/android/internal/os/ZygoteInit.java:920:                if ("start-system-server".equals(argv[i])) {
./base/core/jni/AndroidRuntime.cpp:1195:    static const String8 startSystemServer("start-system-server");

可以看到有c++代码,也有java代码,但是由于此时虚拟机环境还没有建立,不可能进入到java代码中,所以源码一定是./base/cmds/app_process/app_main.cpp,查看源码:

复制代码
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif

int main(int argc, char* const argv[])
{
    //打印传入的参数日志
    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append("\"");
        argv_String.append(argv[i]);
        argv_String.append("\" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.string());
    }

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    int i;
    ...
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    String8 niceName;
    ...
    while (i < argc) {
        const char* arg = argv[i++];
        //如果参数中携带有--zygote,就把zygote置为true,并将nicName赋值为zygoteXX
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        //如果参数中携带有--start-system-server,就把startSystemServer置为true
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else

        ...
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        ...
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();
        //上面startSystemServer为true,args中加入start-system-server
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
        ...

        //系统架构
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        //把剩余参数都添加到Vector容器中
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    //修改进程的名称为zygoteXX
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
        //执行AndroidRuntime的start函数,并传入参数com.android.internal.os.ZygoteInit, args,true
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } 
    ...
}

整体流程还是很简单的,基本可以概括为:

1.解析参数,检查参数中是否存在--zygote、--start-system-server

2.根据解析出来的内容,重新装填参数

2.将进程名称修改为zygoteXX

3.调用AndroidRuntime.start函数,并传入"com.android.internal.os.ZygoteInit",重新装填的参数和true

通过文件内搜索可知,AppRuntime继承自AndroidRuntime:

复制代码
class AppRuntime : public AndroidRuntime
{
    ...
}

故而分析AndroidRuntime代码,通过如下命令搜索:

复制代码
find -name AndroidRuntime.cpp

//搜索结果
./base/core/jni/AndroidRuntime.cpp

源码如下:

复制代码
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    //配置环境变量
    ...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    //加载libart.so
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //启动VM
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    //回调AppRuntime重写的方法
    onVmCreated(env);

    /*
     * Register android functions.
     */
    //注册jni函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    //将Vector转换为String数组
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    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);
    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);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    //查找com.android.internal.os.ZygoteInit的class对象
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        //查找main方法,参数为String数组
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            //执行com.android.internal.os.ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            ...
        }
    }
    ...
}

start主要做了一下几件事:

1.配置系统环境变量

2.加载libart.so库

3.启动虚拟机,注册jni函数

4.启动java类com.android.internal.os.ZygoteInit的main方法,并传入之前的参数

加载libart.so

下面简要分析一下以上流程,环境变量就不说了,看一下jni_invocation.Init(NULL)加载libart.so的流程,由于我通过JniInvocation.cpp没有搜索到内容,所以先通过AndroidRuntime.cpp中导入的头文件来搜索,搜索JniInvocation.h,搜索到源码路径:libnativehelper/include_platform/nativehelper/JniInvocation.h,源码如下:

复制代码
struct JniInvocationImpl* JniInvocationCreate();

bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library);

class JniInvocation final {

//构造函数
 public:
  JniInvocation() {
    impl_ = JniInvocationCreate();
  }

  ~JniInvocation() {
    JniInvocationDestroy(impl_);
  }

  //这个就是调用的init方法
  bool Init(const char* library) {
    //调用JniInvocationInit函数,library传入NULL
    return JniInvocationInit(impl_, library) != 0;
  }

  static const char* GetLibrary(const char* library, char* buffer) {
    return JniInvocationGetLibrary(library, buffer);
  }

 private:
  JniInvocation(const JniInvocation&) = delete;
  JniInvocation& operator=(const JniInvocation&) = delete;

  //原来最终是这个cpp文件
  JniInvocationImpl* impl_;
};

原来JniInvocation只是一个代理包装类,业务是交给JniInvocationImpl实现的,搜索JniInvocationImpl.cpp文件,结果也没有搜到,嘿,奇了怪了,总不能没有吧,后来使用 grep JniInvocationImpl ./ -rn 来搜索,果然就搜索到了,原来一直在关注.cpp,忽略了linux也可以运行.c的,搜索结果如下:

复制代码
./JniInvocation.c:35:struct JniInvocationImpl {
./JniInvocation.c:48:static struct JniInvocationImpl g_impl;
./JniInvocation.c:138:struct JniInvocationImpl* JniInvocationCreate() {
./JniInvocation.c:146:bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library_name) {
./JniInvocation.c:199:void JniInvocationDestroy(struct JniInvocationImpl* instance) {
./include_platform/nativehelper/JniInvocation.h:33:struct JniInvocationImpl;
./include_platform/nativehelper/JniInvocation.h:36: * Creates an instance of a JniInvocationImpl.
./include_platform/nativehelper/JniInvocation.h:38:struct JniInvocationImpl* JniInvocationCreate();
./include_platform/nativehelper/JniInvocation.h:41: * Associates a library with a JniInvocationImpl instance. The library should export C symbols for
./include_platform/nativehelper/JniInvocation.h:56:bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library);
./include_platform/nativehelper/JniInvocation.h:59: * Release resources associated with JniInvocationImpl instance.
./include_platform/nativehelper/JniInvocation.h:61:void JniInvocationDestroy(struct JniInvocationImpl* instance);
./include_platform/nativehelper/JniInvocation.h:122:  JniInvocationImpl* impl_;
./libnativehelper_lazy.c:257:struct JniInvocationImpl* JniInvocationCreate() {
./libnativehelper_lazy.c:258:    typedef struct JniInvocationImpl* (*M)();
./libnativehelper_lazy.c:262:void JniInvocationDestroy(struct JniInvocationImpl* instance) {
./libnativehelper_lazy.c:263:    typedef void (*M)(struct JniInvocationImpl*);
./libnativehelper_lazy.c:267:bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library) {
./libnativehelper_lazy.c:268:    typedef bool (*M)(struct JniInvocationImpl*, const char*);

可以很确定说,源码肯定在./JniInvocation.c中,打开源码文件,查看:

复制代码
static const char* kDefaultJniInvocationLibrary = "libart.so";

bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library_name) {
  //传入的library_name为NULL
  library_name = JniInvocationGetLibrary(library_name, buffer);
  //看函数名字应该是调用linux的dlopen函数,用于打开library为命名的so
  DlLibrary library = DlOpenLibrary(library_name);
  if (library == NULL) {
    //如果library为空,library_name不是libart.so
    if (strcmp(library_name, kDefaultJniInvocationLibrary) == 0) {
    ALOGW("Falling back from %s to %s after dlopen error: %s",
          library_name, kDefaultJniInvocationLibrary, DlGetError());
    //就加载libart.so
    library_name = kDefaultJniInvocationLibrary;
    library = DlOpenLibrary(library_name);
    //如果加载libart.so失败,就返回
    if (library == NULL) {
      ALOGE("Failed to dlopen %s: %s", library_name, DlGetError());
      return false;
    }
  }

  //查找函数JNI_GetDefaultJavaVMInitArgs
  DlSymbol JNI_GetDefaultJavaVMInitArgs_ = FindSymbol(library, "JNI_GetDefaultJavaVMInitArgs");
  if (JNI_GetDefaultJavaVMInitArgs_ == NULL) {
    return false;
  }

  //查找函数JNI_CreateJavaVM
  DlSymbol JNI_CreateJavaVM_ = FindSymbol(library, "JNI_CreateJavaVM");
  if (JNI_CreateJavaVM_ == NULL) {
    return false;
  }

  //查找函数JNI_GetCreatedJavaVMs
  DlSymbol JNI_GetCreatedJavaVMs_ = FindSymbol(library, "JNI_GetCreatedJavaVMs");
  if (JNI_GetCreatedJavaVMs_ == NULL) {
    return false;
  }

  instance->jni_provider_library_name = library_name;
  instance->jni_provider_library = library;
  instance->JNI_GetDefaultJavaVMInitArgs = (jint (*)(void *)) JNI_GetDefaultJavaVMInitArgs_;
  instance->JNI_CreateJavaVM = (jint (*)(JavaVM**, JNIEnv**, void*)) JNI_CreateJavaVM_;
  instance->JNI_GetCreatedJavaVMs = (jint (*)(JavaVM**, jsize, jsize*)) JNI_GetCreatedJavaVMs_;
  return true;
}

先看一下JniInvocationGetLibrary函数:

复制代码
const char* JniInvocationGetLibrary(const char* library, char* buffer) {
  bool debuggable = IsDebuggable();
  const char* system_preferred_library = NULL;
  if (buffer != NULL && (GetLibrarySystemProperty(buffer) > 0)) {
    system_preferred_library = buffer;
  }
  //调用到JniInvocationGetLibraryWith函数中
  return JniInvocationGetLibraryWith(library, debuggable, system_preferred_library);
}

const char* JniInvocationGetLibraryWith(const char* library,
                                        bool is_debuggable,
                                        const char* system_preferred_library) {
  //是否debug
  if (is_debuggable) {
    // Debuggable property is set. Allow library providing JNI Invocation API to be overridden.

    // Choose the library parameter (if provided).
    if (library != NULL) {
      return library;
    }
    // Choose the system_preferred_library (if provided).
    if (system_preferred_library != NULL) {
      return system_preferred_library;
    }
  }
  //返回libart.so字段
  return kDefaultJniInvocationLibrary;
}

再看一下DlOpenLibrary函数,源码位置在:./DlHelp.c:28行

复制代码
DlLibrary DlOpenLibrary(const char* filename) {
#ifdef _WIN32
  return LoadLibrary(filename);
#else
  // Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed.
  // This is due to the fact that it is possible that some threads might have yet to finish
  // exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is
  // unloaded.
  //加载的linux的dlopen函数
  return dlopen(filename, RTLD_NOW | RTLD_NODELETE);
#endif
}

接着往下看,看一下FindSymbol函数的调用:

复制代码
static DlSymbol FindSymbol(DlLibrary library, const char* symbol) {
  //又调用了DlGetSymbol函数
  DlSymbol s = DlGetSymbol(library, symbol);
  if (s == NULL) {
    ALOGE("Failed to find symbol: %s", symbol);
  }
  return s;
}

DlGetSymbol函数也在./DlHelp.c中第48行:

复制代码
DlSymbol DlGetSymbol(DlLibrary handle, const char* symbol) {
#ifdef _WIN32
  return (DlSymbol) GetProcAddress(handle, symbol);
#else
  //调用的是linux的dlsym函数
  return dlsym(handle, symbol);
#endif
}

通过以上分析,可以明确第2点,加载libart.so库,这个so库的源码位置再art/runtime/jni/java_vm_ext.cc中,这里就不做分析了。

启动虚拟机

顺着主线继续,然后再来分析第3步,启动虚拟机startVm的流程, 回到源码:/frameworks/base/core/jni/AndroidRuntime.cpp中:

复制代码
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
    JavaVMInitArgs initArgs;
    //配置了很多虚拟机参数
    ...

    initArgs.version = JNI_VERSION_1_4;
    initArgs.options = mOptions.editArray();
    initArgs.nOptions = mOptions.size();
    initArgs.ignoreUnrecognized = JNI_FALSE;

    /*
     * Initialize the VM.
     *
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
    //创建java虚拟机
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
    return 0;
}

注册JNI函数

startReg方法调用主要是注册jni函数,下面看一下是如何注册的:

复制代码
static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ...
    env->PushLocalFrame(200);

    //注册jni函数的方法,跟一下register_jni_procs函数
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    //createJavaThread("fubar", quickTest, (void*) "hello");

    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    //通过for循环,注册全部jni函数
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
            ...
            return -1;
        }
    }
    return 0;
}

//将这些jni函数全部注册
static const RegJNIRec gRegJNI[] = {
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
        REG_JNI(register_android_os_SystemClock),
        REG_JNI(register_android_util_CharsetUtils),
        REG_JNI(register_android_util_EventLog),
        REG_JNI(register_android_util_Log),
        REG_JNI(register_android_util_MemoryIntArray),
        REG_JNI(register_android_app_admin_SecurityLog),
        REG_JNI(register_android_content_AssetManager),
        REG_JNI(register_android_content_StringBlock),
        REG_JNI(register_android_content_XmlBlock),
        REG_JNI(register_android_content_res_ApkAssets),
        REG_JNI(register_android_text_AndroidCharacter),
        REG_JNI(register_android_text_Hyphenator),
        REG_JNI(register_android_view_InputDevice),
        REG_JNI(register_android_view_KeyCharacterMap),
        REG_JNI(register_android_os_Process),
        REG_JNI(register_android_os_SystemProperties),
        REG_JNI(register_android_os_Binder),
        ...
};

register_com_android_internal_os_RuntimeInit这些函数还可以继续往下分析,其实就是调用了jniEnv的RegisterNatives函数,这个函数在app动态注册函数时使用的是同一个方法,这里就不再继续深入了。

启动ZygoteInit

经过以上的加载虚拟机,注册jni函数完成后,终于通过反射启动了ZygoteInit.java的静态main方法入口,ZygoteInit源码位置:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

复制代码
public class ZygoteInit {
    public static void main(String[] argv) {
        //申明zygoteServer
        ZygoteServer zygoteServer = null;

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        //抑制线程启动,保证zygote单线程启动
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        //设置进程组的id
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        Runnable caller;
        try {
            ...

            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                //包含start-system-server,将startSystemServer置为true
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                //从AndroidRuntime.cpp中带过来的也有这个信息
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else ...
            }

            ...

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            //enableLazyPreload是false
            if (!enableLazyPreload) {
                ...
                //加载android资源
                preload(bootTimingsTraceLog);
                ...
            }

            // Do an initial gc to clean up after startup
            //调用gc进行初始清理回收
            gcAndFinalize();
            //调用AppRuntime的onZygoteInit函数
            Zygote.initNativeState(isPrimaryZygote);

            //中止抑制子线程启动,即将fork,要保证线程可以创建线程
            ZygoteHooks.stopZygoteNoThreadCreation();

            //初始化ZygoteServer创建socket
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            //此时startSystemServer为true,会启动systemServer
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the child (system_server) process.
                //r==null时为zygote进程,r!=null时为子进程
                if (r != null) {
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            //在子进程中会有返回值,在zygote进程中永远循环
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            //出现异常或子进程返回,需要关闭socket
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the command.
        //子进程返回后,会执行
        if (caller != null) {
            caller.run();
        }
    }
}

以上流程备注的比较详细了,下面针对其中的步骤做详细分析。

首先看一下ZygoteHooks.startZygoteNoThreadCreation(),禁止创建线程,之所以要禁止创建线程,是因为Zygote必须保证线程单一,这和fork机制有关,fork函数只会将当前线程复制到子进程,同时,fork会将锁也复制到子进程中,如果在fork之前,有一个线程持有了锁,但是fork的时候没把这个线程复制到子进程中,这把锁就被永久持有了,会造成死锁。

preload

接下来重点看一下加载android资源,进入到preload方法中看一下:

复制代码
static void preload(TimingsTraceLog bootTimingsTraceLog) {
    ...
    //预加载android中的java类
    preloadClasses();

    //加载三个jar
    /* /system/framework/android.hidl.base-V1.0-java.jar */
    /* /system/framework/android.hidl.manager-V1.0-java.jar */
    /* /system/framework/android.test.base.jar */
    cacheNonBootClasspathClassLoaders();
    //预加载资源
    preloadResources();
    //加载硬件抽象层
    nativePreloadAppProcessHALs();
    //加载渲染相关opengl等
    maybePreloadGraphicsDriver();
    //加载动态库
    preloadSharedLibraries();
    //加载front库
    preloadTextResources();
    // Ask the WebViewFactory to do any initialization that must run in the zygote process,
    // for memory sharing purposes.
    //预加载webviewchromium
    WebViewFactory.prepareWebViewInZygote();
    ...
}

先看一下源码:

复制代码
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";    

private static void preloadClasses() {
    final VMRuntime runtime = VMRuntime.getRuntime();

    InputStream is;
    try {
        is = new FileInputStream(PRELOADED_CLASSES);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
        return;
    }
    ...
    try {
        BufferedReader br =
                new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);

        int count = 0;
        int missingLambdaCount = 0;
        String line;
        while ((line = br.readLine()) != null) {
            // Skip comments and blank lines.
            line = line.trim();
            //如果被注释或者是空的,直接continue
            if (line.startsWith("#") || line.equals("")) {
                continue;
            }
            try {
                //加载类
                Class.forName(line, true, null);
                count++;
            } catch (ClassNotFoundException e) {
                ...
            } catch (UnsatisfiedLinkError e) {
                Log.w(TAG, "Problem preloading " + line + ": " + e);
            } catch (Throwable t) {
                ...
            }
        }
    } catch (IOException e) {
        Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
    } finally {
        IoUtils.closeQuietly(is);

        //用预加载带来的类、字段和方法填充dex缓存
        runtime.preloadDexCaches();

        ...
    }
}

可以看到主要就是通过类加载器从/system/etc/preloaded-classes这个路径文件中预加载类,这个路径文件在源码的路径为:frameworks/base/config/preloaded-classes,可以进去看一下:

复制代码
android.R$styleable
android.accessibilityservice.AccessibilityServiceInfo$1
android.accessibilityservice.AccessibilityServiceInfo
android.accessibilityservice.IAccessibilityServiceClient$Stub$Proxy
android.accessibilityservice.IAccessibilityServiceClient$Stub
android.accessibilityservice.IAccessibilityServiceClient
android.accounts.AbstractAccountAuthenticator$Transport
android.accounts.AbstractAccountAuthenticator
android.accounts.Account$1
android.accounts.Account
android.accounts.AccountAndUser
android.accounts.AccountAuthenticatorResponse$1
android.accounts.AccountAuthenticatorResponse
android.accounts.AccountManager$10
android.accounts.AccountManager$11
android.accounts.AccountManager$15
android.accounts.AccountManager$16
android.accounts.AccountManager$17
android.accounts.AccountManager$18
android.accounts.AccountManager$1
android.accounts.AccountManager$20
android.accounts.AccountManager$2
android.accounts.AccountManager$3
android.accounts.AccountManager$8
android.accounts.AccountManager$AmsTask$1
android.accounts.AccountManager$AmsTask$Response
android.accounts.AccountManager$AmsTask
android.accounts.AccountManager$BaseFutureTask$1
android.accounts.AccountManager$BaseFutureTask$Response
android.accounts.AccountManager$BaseFutureTask
android.accounts.AccountManager$Future2Task$1
android.accounts.AccountManager$Future2Task
android.accounts.AccountManager
android.accounts.AccountManagerCallback
...

为什么需要在zygote中预加载类呢?

这是由于父子进程的资源是共享的,每启动一个app,都需要使用虚拟机、加载类等,直接在父进程中预加载这些,fork后子进程就可以直接使用它们,就不需要每个app都要去加载一次,降低系统效率,浪费资源。

cacheNonBootClasspathClassLoaders

再看一下cacheNonBootClasspathClassLoaders加载了三个jar

复制代码
    private static void cacheNonBootClasspathClassLoaders() {
        // These libraries used to be part of the bootclasspath, but had to be removed.
        // Old system applications still get them for backwards compatibility reasons,
        // so they are cached here in order to preserve performance characteristics.

        //这些库曾经是bootclasspath的一部分,但必须删除,由于向后兼容性的原因,旧的系统应用程序仍然得到它们,所以缓存再这里
        SharedLibraryInfo hidlBase = new SharedLibraryInfo(
                "/system/framework/android.hidl.base-V1.0-java.jar", null /*packageName*/,
                null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
                null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
                false /*isNative*/);
        SharedLibraryInfo hidlManager = new SharedLibraryInfo(
                "/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/,
                null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
                null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
                false /*isNative*/);

        SharedLibraryInfo androidTestBase = new SharedLibraryInfo(
                "/system/framework/android.test.base.jar", null /*packageName*/,
                null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
                null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
                false /*isNative*/);

        ApplicationLoaders.getDefault().createAndCacheNonBootclasspathSystemClassLoaders(
                new SharedLibraryInfo[]{
                    // ordered dependencies first
                    hidlBase,
                    hidlManager,
                    androidTestBase,
                });
    }

preloadResources

preloadResources主要预加载资源和检查资源

复制代码
private static final boolean PRELOAD_RESOURCES = true;

private static void preloadResources() {
    try {
        mResources = Resources.getSystem();
        mResources.startPreloading();
        if (PRELOAD_RESOURCES) {
            //加载所有drawable
            TypedArray ar = mResources.obtainTypedArray(
                    com.android.internal.R.array.preloaded_drawables);
            int N = preloadDrawables(ar);
            ar.recycle();
            //加载color属性
            ar = mResources.obtainTypedArray(
                    com.android.internal.R.array.preloaded_color_state_lists);
            N = preloadColorStateLists(ar);
            ar.recycle();

            ...
        }
        mResources.finishPreloading();
    } catch (RuntimeException e) {
        Log.w(TAG, "Failure preloading resources", e);
    }
}

private static int preloadDrawables(TypedArray ar) {
    int N = ar.length();
    for (int i = 0; i < N; i++) {
        int id = ar.getResourceId(i, 0);

        if (id != 0) {
            //
            if (mResources.getDrawable(id, null) == null) {
                throw new IllegalArgumentException(
                        "Unable to find preloaded drawable resource #0x"
                                + Integer.toHexString(id)
                                + " (" + ar.getString(i) + ")");
            }
        }
    }
    return N;
}

private static int preloadColorStateLists(TypedArray ar) {
    int N = ar.length();
    for (int i = 0; i < N; i++) {
        int id = ar.getResourceId(i, 0);

        if (id != 0) {
            if (mResources.getColorStateList(id, null) == null) {
                throw new IllegalArgumentException(
                        "Unable to find preloaded color resource #0x"
                                + Integer.toHexString(id)
                                + " (" + ar.getString(i) + ")");
            }
        }
    }
    return N;
}

直接上面分析了几种,其他项基本都是预加载各种资源,就不再一个一个的看了,接着主线流程,往preload下面看:

ZygoteServer

可以看到调用两次创建socket的方法,传入不同的参数,分别创建了一个socket

java 复制代码
//ZygoteServer的构造方法,此时isPrimaryZygote为true
ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

        if (isPrimaryZygote) {
            //创建本地socket,传入zygote
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            //创建本地socket,传入usap_pool_primary
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        } else {
            //创建本地socket,传入zygote_secondary
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
            //创建本地socket,传入usap_pool_secondary
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
        }

        mUsapPoolSupported = true;
        fetchUsapPoolPolicyProps();
}

调用了Zygote.java中的静态方法,接着往下追代码:

java 复制代码
/** Prefix prepended to socket names created by init */
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";

/**
 * @hide for internal use only.
 */
public static final String PRIMARY_SOCKET_NAME = "zygote";

/**
 * @hide for internal use only.
 */
public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";

/**
 * @hide for internal use only
 */
public static final String USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary";

/**
 * @hide for internal use only
 */
public static final String USAP_POOL_SECONDARY_SOCKET_NAME = "usap_pool_secondary";

static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
    int fileDesc;
    final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

    try {
        //获取指定环境变量fullSocketName的值
        String env = System.getenv(fullSocketName);
        fileDesc = Integer.parseInt(env);
    } catch (RuntimeException ex) {
        throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
    }

    try {
        //创建fd并绑定节点
        FileDescriptor fd = new FileDescriptor();
        fd.setInt$(fileDesc);
        //创建LocalServerSocket对象,并传入fd
        return new LocalServerSocket(fd);
    } catch (IOException ex) {
        throw new RuntimeException(
            "Error building socket from file descriptor: " + fileDesc, ex);
    }
}

进入到LocalServerSocket类中,其中又创建了LocalSocketImpl对象,然后设置了fd和BACKLOG为50的监听:

java 复制代码
private static final int LISTEN_BACKLOG = 50;

public LocalServerSocket(FileDescriptor fd) throws IOException
{
    //创建LocalSocketImpl对象
    impl = new LocalSocketImpl(fd);
    //添加监听,监听BACKLOG为50
    impl.listen(LISTEN_BACKLOG);
    //获取本地地址
    localAddress = impl.getSockAddress();
}

LocalSocketImpl构造方法什么都没干,listene方法内部就是调用的Os.listen(FileDescriptor fd, int backlog),就不再往下分析了。

forkSystemServer

java 复制代码
//传入的参数:架构, zygote, zygoteServer对象
private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {
    ...
    /* Hardcoded command line to start the system server */
    //fork内容要传入的参数
    String[] args = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                    + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
            "com.android.server.SystemServer",
    };
    ZygoteArguments parsedArgs;

    int pid;

    try {
        ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
        try {
            parsedArgs = ZygoteArguments.getInstance(commandBuffer);
        } catch (EOFException e) {
            throw new AssertionError("Unexpected argument error for forking system server", e);
        }
        commandBuffer.close();
        ...
        /* Enable gwp-asan on the system server with a small probability. This is the same
         * policy as applied to native processes and system apps. */
        parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;

        if (shouldProfileSystemServer()) {
            parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
        }

        /* Request to fork the system server process */
        //进入到zygote的静态方法中
        pid = Zygote.forkSystemServer(
                parsedArgs.mUid, parsedArgs.mGid,
                parsedArgs.mGids,
                parsedArgs.mRuntimeFlags,
                null,
                parsedArgs.mPermittedCapabilities,
                parsedArgs.mEffectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    /* For child process */
    //子进程创建成功,进入子进程
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            //等待secondZygote
            waitForSecondaryZygote(socketName);
        }
        //停止自己的serverSocket
        zygoteServer.closeServerSocket();
        //调用了handleSystemServerProcess
        return handleSystemServerProcess(parsedArgs);
    }

    return null;
}

//Zygote.forkSystemServer
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    ZygoteHooks.preFork();
    //调用了nativeForkSystemServer,这是一个native方法,可以通过命令搜索源码
    int pid = nativeForkSystemServer(
            uid, gid, gids, runtimeFlags, rlimits,
            permittedCapabilities, effectiveCapabilities);

    // Set the Java Language thread priority to the default value for new apps.
    //设置新进程的线程优先级
    Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

    ZygoteHooks.postForkCommon();
    return pid;
}

通过如下命令搜索:

java 复制代码
grep nativeForkSystemServer ./ -rn

进入到nativeForkSystemServer源码中:

java 复制代码
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
        jlong effective_capabilities) {
  ...
  //调用了zygote的ForkCommon方法,再跟一下
  pid_t pid = zygote::ForkCommon(env, true,
                                 fds_to_close,
                                 fds_to_ignore,
                                 true);
  if (pid == 0) {
      // System server prcoess does not need data isolation so no need to
      // know pkg_data_info_list.
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
                       effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                       false, nullptr, nullptr, /* is_top_app= */ false,
                       /* pkg_data_info_list */ nullptr,
                       /* allowlisted_data_info_list */ nullptr, false, false);
  }
  return pid;
}

//ForkCommon
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();
  ...
  //fork前先阻塞SIGCHLD信号
  BlockSignal(SIGCHLD, fail_fn);
  ...
  //最终是调用了fork方法
  pid_t pid = fork();
  ...
  // We blocked SIGCHLD prior to a fork, we unblock it here.
  //恢复SIGCHLD信号
  UnblockSignal(SIGCHLD, fail_fn);
  return pid;
}

这里佐证了forkSystemServer是通过fork来实现的进程启动,forSystemServer返回值是一个Runnable,看一下这个Runnable怎么被创建出来的,可以看到再pid==0子进程创建成功后,调用了handleSystemServerProcess,看一下源码:

java 复制代码
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
    // set umask to 0077 so new files and directories will default to owner-only permissions.
    //设置权限掩码
    Os.umask(S_IRWXG | S_IRWXO);
    //设置进程名称为system_server
    if (parsedArgs.mNiceName != null) {
        Process.setArgV0(parsedArgs.mNiceName);
    }
    ...
    if (parsedArgs.mInvokeWith != null) {
        ...
    } else {
        //创建classloader
        ClassLoader cl = getOrCreateSystemServerClassLoader();
        if (cl != null) {
            Thread.currentThread().setContextClassLoader(cl);
        }

        /*
         * Pass the remaining arguments to SystemServer.
         */
        //调用了ZygoteInit.zygoteInit方法
        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                parsedArgs.mDisabledCompatChanges,
                parsedArgs.mRemainingArgs, cl);
    }
}

进入到zygoteInit方法中:

java 复制代码
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) {
    ...
    RuntimeInit.redirectLogStreams();
    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit();
    //调用到了RuntimeInit.applicationInit
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

调用到了RuntimeInit.applicationInit,继续追踪

java 复制代码
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) {
    ....
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    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
    //调用findStaticMain, 查找main方法,在追踪一下
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

//findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) {
    //反射获取类对象
    Class<?> cl;
    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }
    //反射获取main方法对象
    Method m;
    try {
        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);
    }
    //new MethodAndArgsCaller其实就是一个Runnable,其中的run方法就是invoke这个main方法,可以通过源码印证
    return new MethodAndArgsCaller(m, argv);
}

//MethodAndArgsCaller
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;
    }
    //run方法,调用后会调用main方法
    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InvocationTargetException ex) {
            Throwable cause = ex.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            }
            throw new RuntimeException(ex);
        }
    }
}

整个过程就是调用到了SystemServer的main方法中启动了SystemServer,SystemServer启动后做了什么留在后面章节分析,这里继续将剩余的流程分析完。

runSelectLoop

ZygoteInit类中如果startSystemServer为false,则会调用zygoteServer.runSelectLoop方法,看一下这个方法做了什么:

java 复制代码
Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        //将server socket fd加到列表头(后面需要判断是否为server socket)
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);

        while (true) {
            ...
            //等待fd的事件
            try {
                Os.poll(pollFDs, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

            boolean usapPoolFDRead = false;

            while (--pollIndex >= 0) {
                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                    continue;
                }
                //pollIndex == 0说明fd是ZygoteServer socket的fd
                if (pollIndex == 0) {
                    // Zygote server socket
                    //接受并建立一个socket连接
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());

                } else if (pollIndex < usapPoolEventFDIndex) {
                    // Session socket accepted from the Zygote server socket

                    try {
                        ZygoteConnection connection = peers.get(pollIndex);
                        final Runnable command = connection.processOneCommand(this);

                        // TODO (chriswailes): Is this extra check necessary?
                        if (mIsForkChild) {
                            // We're in the child. We should always have a command to run at this
                            // stage if processOneCommand hasn't called "exec".
                            if (command == null) {
                                throw new IllegalStateException("command == null");
                            }

                            return command;
                        } else {
                            // We're in the server - we should never have any commands to run.
                            if (command != null) {
                                throw new IllegalStateException("command != null");
                            }

                            // We don't know whether the remote side of the socket was closed or
                            // not until we attempt to read from it from processOneCommand. This
                            // shows up as a regular POLLIN event in our regular processing loop.
                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(pollIndex);
                                socketFDs.remove(pollIndex);
                            }
                        }
                    } catch (Exception e) {
                        if (!mIsForkChild) {
                            // We're in the server so any exception here is one that has taken place
                            // pre-fork while processing commands or reading / writing from the
                            // control socket. Make a loud noise about any such exceptions so that
                            // we know exactly what failed and why.

                            Slog.e(TAG, "Exception executing zygote command: ", e);

                            // Make sure the socket is closed so that the other end knows
                            // immediately that something has gone wrong and doesn't time out
                            // waiting for a response.
                            ZygoteConnection conn = peers.remove(pollIndex);
                            conn.closeSocket();

                            socketFDs.remove(pollIndex);
                        } else {
                            // We're in the child so any exception caught here has happened post
                            // fork and before we execute ActivityThread.main (or any other main()
                            // method). Log the details of the exception and bring down the process.
                            Log.e(TAG, "Caught post-fork exception in child process.", e);
                            throw e;
                        }
                    } finally {
                        // Reset the child flag, in the event that the child process is a child-
                        // zygote. The flag will not be consulted this loop pass after the Runnable
                        // is returned.
                        mIsForkChild = false;
                    }
                } else {
                    // Either the USAP pool event FD or a USAP reporting pipe.

                    // If this is the event FD the payload will be the number of USAPs removed.
                    // If this is a reporting pipe FD the payload will be the PID of the USAP
                    // that was just specialized.
                    long messagePayload = -1;

                    try {
                        byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
                        int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);

                        if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
                            DataInputStream inputStream =
                                    new DataInputStream(new ByteArrayInputStream(buffer));

                            messagePayload = inputStream.readLong();
                        } else {
                            Log.e(TAG, "Incomplete read from USAP management FD of size "
                                    + readBytes);
                            continue;
                        }
                    } catch (Exception ex) {
                        if (pollIndex == usapPoolEventFDIndex) {
                            Log.e(TAG, "Failed to read from USAP pool event FD: "
                                    + ex.getMessage());
                        } else {
                            Log.e(TAG, "Failed to read from USAP reporting pipe: "
                                    + ex.getMessage());
                        }

                        continue;
                    }

                    if (pollIndex > usapPoolEventFDIndex) {
                        Zygote.removeUsapTableEntry((int) messagePayload);
                    }

                    usapPoolFDRead = true;
                }
            }

            // Check to see if the USAP pool needs to be refilled.
            if (usapPoolFDRead) {
                int[] sessionSocketRawFDs =
                        socketFDs.subList(1, socketFDs.size())
                                .stream()
                                .mapToInt(fd -> fd.getInt$())
                                .toArray();

                final Runnable command = fillUsapPool(sessionSocketRawFDs);

                if (command != null) {
                    return command;
                }
            }
        }
    }

未完待续...

相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui