前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发之漫漫长途 XI——从I到X的小结

Android开发之漫漫长途 XI——从I到X的小结

作者头像
LoveWFan
发布2018-08-07 15:50:34
8520
发布2018-08-07 15:50:34
举报

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!!另外,本系列文章知识可能需要有一定Android开发基础和项目经验的同学才能更好理解,也就是说该系列文章面向的是Android中高级开发工程师。


前言

上面十几篇文章我们从Android的创世之初到了Activity显示以及View的绘制、事件体系,我们也分析了Binder和Handler。读者是不是觉得我这个系列要完了呀。那你们就大错特错了。介绍前面的知识我们是为了后面的知识打底的。那么本篇文章呢,是对前面文章的一个总结。毕竟一下子放出那么多东西,我怕你们的小心脏已经爆棚了。所以本篇文章我们再梳理一下。

注:前面文章我们主要讲了和显示相关的知识如Activity、Window、View等

注:以下源码来自android-6.0.0_r5

奇点——init进程

我们在Android开发之漫漫长途 Ⅰ——Android系统的创世之初以及Activity的生命周期就提到了init进程,init也是Android系 统中用户空间的第一个进程,它的进程号是1。 作为天字第一号进 程,init进程负责创建系统中的几个关键进程,尤其是zygote,它更是Java世界的开创者。 关于进程的概念,我想读者们应该都很清楚了,不论我们使用的是c语言还是java语言,我们在最初写HelloWordld程序的时候,我们创建.cpp或者.java文件,关键的是在文件中定义入口方法main,我们在main方法中打印出一行HelloWord,然后我们编译运行该程序,我们这个运行起来的程序就可以看做是一个进程。而我们init进程也不例外,它是由c++编写的一个可执行程序,我们很容易的就想到要先看其main方法。

[init.cpp]

代码语言:javascript
复制
int main(int argc, char** argv) {
    .....
    //解析init.rc文件
    init_parse_config_file("/init.rc");
    .....
    //执行各个阶段的动作,创建zygote的工作就是在其中的某个
阶段完成的
    action_for_each_trigger("early-init", action_add_queue_tail);

    .....
   
  
    action_for_each_trigger("init", action_add_queue_tail);

    .....
    //init进入一个无限循环,并且等待一些事情的发生
    while (true) {
        
    }

    return 0;
}

init进程的工作还是挺繁重的,我们精简之后得到上面三步:

解析init.rc文件

init.rc文件的解析是init进程的重要工作,我们的重要进程如SM进程、Zygote进程等都是解析该文件然后创建的。下面给出的节选自init.rc文件中的内容

[init.rc]

代码语言:javascript
复制
//导入其他配置文件

import /init.${ro.hardware}.rc
//看这个难道是导入zygote相关的配置文件吗??
import /init.${ro.zygote}.rc


on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000

    # Set the security context of /adb_keys if present.
    restorecon /adb_keys

    start ueventd

on init
    sysclktz 0

那么这个ro.zygote又是个什么鬼,其实它是定义在product_64_only.mk和core_minimal.mk中的,根据平台是32位还是64位ro.zygote被赋值为zygote64或者zygote32

[init.zygote64.rc]

代码语言:javascript
复制
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 media
onrestart restart netd

那么有了上面的文件之后,我们是怎么解析上面的配置文件的呢,我们在init.cpp中的init_parse_config_file函数就是完成这个功能的。我们来稍微看一下这个函数

[init_parser.cpp]

代码语言:javascript
复制
int init_parse_config_file(const char* path) {
    .....
    std::string data;
    .....
    //读取文件,这个文件就是init.rc
    if (!read_file(path, &data)) {
        return -1;
    }
    .....
    //调用parse_config做真正的解析
    parse_config(path, data);
    .....
    return 0;
}

关于这个具体的解析过程很复杂,读者如果有兴趣可以自行参看《深入理解Android 卷Ⅰ》第3章,我们这里就不详细分析了,,因为要分析它至少需要两篇博客。

我们知道zygote是在init.rc文件中定义,init进程通过解析该文件并fork出Android中Java世界的开创者zygote。

小结

init进程是奇点,那么奇点爆炸后得到了什么呢?看下图

我们来分析zygote进程,至于ServiceManager进程我们已经在 Android开发之漫漫长途 IX——彻底掌握Binder中分析了,至于其他进程的启动我们以后有机会再来一一分析。

zygote进程

zygote本身是一个Native的应用程序,与驱动、 内核等均无关 系。 根据第上面对init的介绍我们可以知道,zygote是由init进程根 据init.rc文件中的配置项创建的。 我们一样来看一下其main函数

代码语言:javascript
复制
int main(int argc, char* const argv[])
{
    //我们参数图如上图,这个数据来自在init.zygote64.rc中设置的/system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    ......
    argc--;
    //忽略argv[0];
    argv++;

    ......
    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }
    ......
    unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    //这时我们的i指向了--zygote所在的索引
    ++i; 
    
    while (i < argc) {
        //取出值,,这里取出arg=--zygote,然后i++
        const char* arg = argv[i++];

        if (strcmp(arg, "--zygote") == 0) {//进入这个分支
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            //第2次循环进入这个分支
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    Vector<String8> args;
    if (!className.isEmpty()) {
       
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
       
        ......
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        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);

       
        ......
    }
    /*由上面的操作我们得到了
    *niceName=ZYGOTE_NICE_NAME;
    *zygote = true;
    *startSystemServer = true;
    *
    *args=["start-system-server","--abi-list="];
    *这里args第2个元素"--abi-list="这个字符串的后面内容是根据支持的abi来拼接的,但是目前我们只有这2个元素是确定的
    */
    
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) {
        //调用Runtime.start方法
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } 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;
    }
}

AppRuntime

上面我们的代码走到了AppRuntime的start函数中,我们来看AppRuntime

[app_main.cpp]

代码语言:javascript
复制
class AppRuntime : public AndroidRuntime

其继承于AndroidRuntime,但是并没有在其中找到start方法,那么应该在AndroidRuntime中了

[AndroidRuntime.cpp]

代码语言:javascript
复制
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    

    /* 启动虚拟机 */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

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

    /*
     * 传递给java层的ZygoteInit.main函数的参数
     */
    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);
    }

    /*
     *反射调用java层的ZygoteInit.main函数
     * 
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        
    } else {
        //看到了吧 ,main
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
           
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

        }
    }
   
}

我们分析到了Native层Zygote的启动,至于Java中ZygoteInit.main函数我们来看一下

[ZygoteInit.java]

代码语言:javascript
复制
public static void main(String argv[]) {
    try {
        ......

        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        for (int i = 1; i < argv.length; i++) {
            if ("start-system-server".equals(argv[i])) {//进入该分支
                
                startSystemServer = true;
            } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                abiList = argv[i].substring(ABI_LIST_ARG.length());
            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                socketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException("Unknown command line argument: " + argv[i]);
            }
        }

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

        //建立IPC通信服务端zygote及系统中其他程序的通信没有使用Binder,而是采用了基于AF_UNIX类型的Socket

        registerZygoteSocket(socketName);
        ......
        
        if (startSystemServer) {
            //启动SystemServer进程
            startSystemServer(abiList, socketName);
        }

        //处理来自上面的socket的请求
        runSelectLoop(abiList);

        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        //这里需要注意
        caller.run();
    } catch (RuntimeException ex) {
        Log.e(TAG, "Zygote died with exception", ex);
        closeServerSocket();
        throw ex;
    }
}

小结

zygote"生下"了SystemServer进程,然后就去等待请求了,看下图

SystemServer

SystemServer进程作为zygote的大儿子,其任务也是不少啊。我们来看其启动过程。

SystemServer的启动

[ZygoteInit.java]

代码语言:javascript
复制
private static boolean startSystemServer(String abiList, String socketName)
        throws MethodAndArgsCaller, RuntimeException {
    long capabilities = posixCapabilitiesAsBits(
        OsConstants.CAP_BLOCK_SUSPEND,
        OsConstants.CAP_KILL,
        OsConstants.CAP_NET_ADMIN,
        OsConstants.CAP_NET_BIND_SERVICE,
        OsConstants.CAP_NET_BROADCAST,
        OsConstants.CAP_NET_RAW,
        OsConstants.CAP_SYS_MODULE,
        OsConstants.CAP_SYS_NICE,
        OsConstants.CAP_SYS_RESOURCE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG
    );
    /* Hardcoded command line to start the system server */
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        /* 创建SystemServer进程 */
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    /* 如果pid为零,则表示处于子进程中,也就是处于system_server进程中。*/
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        //system_server进程的工作
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

SystemServer的重要使命

SystemServer进程启动之后,便在其进程中调用handleSystemServerProcess方法完成其重要使命。

[ZygoteInit.java]

代码语言:javascript
复制
private static void handleSystemServerProcess(
        ZygoteConnection.Arguments parsedArgs)
        throws ZygoteInit.MethodAndArgsCaller {

    ......
    //获取SystemServer的类路径
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    ......
    if (parsedArgs.invokeWith != null) {
       
    } else {//我们是进入这个分支
        //获取SystemServer的类加载器
        ClassLoader cl = null;
        if (systemServerClasspath != null) {
            cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
            Thread.currentThread().setContextClassLoader(cl);
        }

        //调用RuntimeInit的zygoteInit方法
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }


}

跟进RuntimeInit.java

代码语言:javascript
复制
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    ......
    //常规的初始化
    commonInit();
    //① native层的初始化
    nativeZygoteInit();
    //② java层的初始化
    applicationInit(targetSdkVersion, argv, classLoader);
}

SystemServer native层的初始化

zygoteInitNative,是一个native函数,实现在 AndroidRuntime.cpp中

[AndroidRuntime.cpp]

代码语言:javascript
复制
static AndroidRuntime* gCurRuntime = NULL;

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    
    gCurRuntime->onZygoteInit();
}

[app_main.cpp]

代码语言:javascript
复制
virtual void onZygoteInit()
{
    
    //这里看到了我们的ProcessState,我们在介绍Binder相关知识的时候经常看到它
    sp<ProcessState> proc = ProcessState::self();
    
    //看这个名字估计是启动线程池把
    proc->startThreadPool();
}
进程唯一的ProcessState

ProcessState self函数采用了单例模式,根据这个以及Process State的名字这很明确地告诉了我们一个信息:每个进程只有一个ProcessState对象

[ProcessState.cpp]

代码语言:javascript
复制
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    //gProcess是在Static.cpp中定义的一个全局变量。
    //程序刚开始执行,gProcess一定为空。
    if (gProcess != NULL) {
        return gProcess;
    }
    //创建一个ProcessState对象,并赋值给gProcess。
    gProcess = new ProcessState;
    return gProcess;
}

再来看ProcessState的构造函数。 这个函数非常重要,它悄悄 地打开了Binder设备,关于Binder更多知识可参看Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

[ProcessState.cpp]

代码语言:javascript
复制
ProcessState::ProcessState()
    : mDriverFD(open_driver())//这里的open_driver()函数
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        /*
        BIDNER_VM_SIZE定义为(1*1024*1024)-(4096*2)=1M-8K
        mmap的用法希望读者man一下,不过这个函数真正的实现和驱动有关系,而Binder驱
        动会分配一块内存来接收数据。
        */

       
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
    } 
}


static int open_driver()
{
    int fd=open("/dev/binder",O_RDWR);//打开/dev/binder设备。
    if(fd>=0){
        ......
        size_t maxThreads=15;
        //通过ioctl方式告诉binder驱动,这个fd支持的最大线程数是15个。
        result=ioctl(fd,BINDER_SET_MAX_THREADS,&maxThreads);
    }
    return fd;
    ......
}
SystemServer的Binder线程

我们再来看proc->startThreadPool();

[ProcessState.cpp]

代码语言:javascript
复制
void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    //如果已经startThreadPool的话,这个函数就没有什么实质作用了
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        //注意,传进去的参数是true。
        spawnPooledThread(true);
    }
}

void ProcessState::spawnPooledThread(bool isMain)
{
    //如果已经startThreadPool的话,这个函数就没有什么实质作用了
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        //这里创建PoolThread参数是true
        sp<Thread> t = new PoolThread(isMain);
        //run函数
        t->run(name.string());
    }
}

PoolThread是在ProcessState中定义的一个Thread子类, 它的实现如下所示

代码语言:javascript
复制
class PoolThread : public Thread
{
public:
    PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }
    
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }
    
    const bool mIsMain;
};

**在Thread类的run方法执行后,调用底层库创建线程,并执行回调方法_ threadLoop,_threadLoop内部有个while循环,循环调用threadLoop()函数处理数据, 并根据threadLoop()的返回值决定循环继续或者退出。当threadLoop()返回true时,如果requestExit没有被调用,则threadLoop会再次调用,当返回false时,线程退出。**

我们可以在PoolThread中看到threadLoop()方法,也就是说t->run(name.string());的运行会导致循环调用PoolThread的threadLoop()方法。

IPCThreadState

IPCThreadState也是一个单例,不过是线程单例,即每一个线程都有一个IPCThreadState

[IPCThreadState.cpp]

代码语言:javascript
复制
IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        /*
        TLS是Thread Local Storage(线程本地存储空间)的简称。这里只需知晓:这种空间每个线程都有,而且线程间不共享这些空间。
        通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间
        中的内容。
        从线程本地存储空间中获得保存在其中的IPCThreadState对象。
        有调用pthread_getspecific的地方,肯定也有调用pthread_setspecific的地
        方。
        */
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        //new一个对象,构造函数中会调用pthread_setspecific
        return new IPCThreadState;
    }
    
    if (gShutdown) return NULL;
    
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

接下来我们有必要看一下其构造函数了

代码语言:javascript
复制
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
  mMyThreadId(gettid()),
  mStrictModePolicy(0),
  mLastTransactionBinderFlags(0)
{
    //在构造函数中,把自己设置到线程本地存储中去。
    pthread_setspecific(gTLS, this);
    clearCaller();
    //mIn和mOut是两个Parcel。 把它看成是发送和接收命令的缓冲区即可
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

每个线程都有一个IPCThreadState,每个IPCThreadState中 都有一个mIn、 一个mOut,其中,mIn是用来接收来自Binder设 备的数据的,而mOut则是用来存储发往Binder设备的数据的。

接下来得来看看joinThreadPool了

代码语言:javascript
复制
void IPCThreadState::joinThreadPool(bool isMain)//此时isMain为true
{
    //向mOut中写入BC_ENTER_LOOPER
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
   //设置前台调度策略
    set_sched_policy(mMyThreadId, SP_FOREGROUND);
        
    status_t result;
    do {
        processPendingDerefs();
        //处理下一条指令
        result = getAndExecuteCommand();

        if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
            ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                  mProcess->mDriverFD, result);
            abort();
        }
        
        
        if(result == TIMED_OUT && !isMain) {
            break;//非主线程出现timeout则线程退出
        }
    } while (result != -ECONNREFUSED && result != -EBADF);

    
     //向mOut中写入BC_EXIT_LOOPER
    mOut.writeInt32(BC_EXIT_LOOPER);
    /false代表bwr数据的read_buffer为空
    talkWithDriver(false);
}

我们在joinThreadPool中又看到了一个do while循环,SystemServer进程创建了主线程之后便加入了Binder线程池,并且永不退出的线程

代码语言:javascript
复制
//这里创建PoolThread参数是true
sp<Thread> t = new PoolThread(isMain);
//run函数
t->run(name.string());

也就是说代码循环执行threadLoop()函数时

代码语言:javascript
复制
virtual bool threadLoop()
{
    //主线程被阻塞在这里了
    IPCThreadState::self()->joinThreadPool(mIsMain);
    
    return false;
}
SystemServer native层的初始化小结

SystemServer Native层的初始化主要是建立了与Binder设备的通信,完成这项工作的实际是SystemServer的主线程。也是说目前SystemServer进程已有一个线程与Binder通信。并且Binder驱动程序会根据一些条件来建立新的普通的Binder线程来减低交互压力。

SystemServer java层的初始化

分析的入口是 [RuntimeInit.java]

代码语言:javascript
复制
applicationInit(targetSdkVersion, argv, classLoader);

跟进

代码语言:javascript
复制
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    ......
    final Arguments args;
    try {
        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
       
        return;
    }
    ......
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

跟进invokeStaticMain

代码语言:javascript
复制
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
    //反射类,这里是SystemServer类
    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }
    //反射SystemServer类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);
    }

   //抛出一个异常
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

既然有抛出异常,肯定在哪里捕获了这个异常。我们一层层回顾,最终在最初调用startSystemServer函数的ZygoteInit的main函数中找到了

代码语言:javascript
复制
catch (MethodAndArgsCaller caller) {
        caller.run();
    } 

调用caller.run();反射调用SystemServer类的main方法

兜兜转转我们终于到了SystemServer。在其main方法中,我们开启了Android的重要系统服务,如ActivityManagerService等,并把服务注册入了ServiceManager大管家。

[SystemServer.java]

代码语言:javascript
复制
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    ......

    // 准备main looper
    Looper.prepareMainLooper();

    // 初始化native服务
    System.loadLibrary("android_servers");



    //初始化Context
    createSystemContext();

    //创建系统服务管家.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

    // 开启服务.
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }

    // For debug builds, log event loop stalls to dropbox for analysis.
    if (StrictMode.conditionallyEnableDebugLogging()) {
        Slog.i(TAG, "Enabled StrictMode for system server main thread.");
    }

    // 永远 loop
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

SystemServer小结

SystemServer的工作主要包含两部分

  1. Binder相关工作
  2. 开启各种系统服务

经历了上述过程,得到了如图所示的结构

我们的APP进程

我们用Android Studio编写一个Hello World程序,编译,安装到手机上。Android Studio 是通过adb 工具做到的。 我们也可以使用下面的安装apk

代码语言:javascript
复制
adb install HelloWorld.apk 

然后启动某个Activity

代码语言:javascript
复制
adb shell am start -n 包名/包名.活动名

上面的命令行最终会调用到AMS的startActivityAndWait函数来处理这次启动请求。具体过程我们这里不分析,我们这里只需要知道AMS的startActivityAndWait函数通过Socket与zygote进程交互,并最终导致zygote 也通过fork的方式繁殖一个进程,而我们之后的操作有了载体。

我们在上面的知识中说到zygote在分裂出SystemServer后,便陷入沉睡等待请求,那么谁会向它发请求,它又是如何处理请求呢。 我们知道在启动Activity的时候,如果这个Activity附属于一个尚未启动的进程,那么显然我们要先启动进程。启动进程的请求由AMS的startProcessLocked发起,先来看AMS的startProcessLocked函数 [ActivityManagerService.java]

代码语言:javascript
复制
private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        
        .....
        boolean isActivityProcess = (entryPoint == null);
        //这里传入的entryPoint==null所以entryPoint被赋值为android.app.ActivityThread
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        .....
        //调用Process.start
        Process.ProcessStartResult startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                app.info.dataDir, entryPointArgs);
        
        .....
}

跟进[Process.java]

代码语言:javascript
复制
public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String abi,
                              String instructionSet,
                              String appDataDir,
                              String[] zygoteArgs) {
    try {
        //processClass为android.app.ActivityThread
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}

继续跟进startViaZygote

代码语言:javascript
复制
private static ProcessStartResult startViaZygote(final String processClass,
                              final String niceName,
                              final int uid, final int gid,
                              final int[] gids,
                              int debugFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String abi,
                              String instructionSet,
                              String appDataDir,
                              String[] extraArgs)
                              throws ZygoteStartFailedEx {
    synchronized(Process.class) {
        ArrayList<String> argsForZygote = new ArrayList<String>();

        //一系列参数设置
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
            argsForZygote.add("--enable-jni-logging");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
            argsForZygote.add("--enable-safemode");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
            argsForZygote.add("--enable-debugger");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
            argsForZygote.add("--enable-checkjni");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) {
            argsForZygote.add("--enable-jit");
        }
        if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
            argsForZygote.add("--generate-debug-info");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
            argsForZygote.add("--enable-assert");
        }
        if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
            argsForZygote.add("--mount-external-default");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
            argsForZygote.add("--mount-external-read");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
            argsForZygote.add("--mount-external-write");
        }
        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

        if (gids != null && gids.length > 0) {
            StringBuilder sb = new StringBuilder();
            sb.append("--setgroups=");

            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);
        }

        argsForZygote.add(processClass);

        if (extraArgs != null) {
            for (String arg : extraArgs) {
                argsForZygote.add(arg);
            }
        }
        //调用zygoteSendArgsAndGetResult
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

继续

代码语言:javascript
复制
private static ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args)
        throws ZygoteStartFailedEx {
    try {
        //写入数据,发起请求
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;

        writer.write(Integer.toString(args.size()));
        writer.newLine();

        int sz = args.size();
        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            if (arg.indexOf('\n') >= 0) {
                throw new ZygoteStartFailedEx(
                        "embedded newlines not allowed");
            }
            writer.write(arg);
            writer.newLine();
        }

        writer.flush();

        // 等待结果
        ProcessStartResult result = new ProcessStartResult();
        result.pid = inputStream.readInt();
        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        result.usingWrapper = inputStream.readBoolean();
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

zygote收到请求后调用ZygoteConnection的runOnce方法

[ZygoteConnection.java]

代码语言:javascript
复制
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    
    String args[];
    Arguments parsedArgs = null;
    ......
    try{
        //读取SystemServer发送来的参数
        args = readArgumentList();
    }
    ......
    parsedArgs = new Arguments(args);
    ......
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
    ......
    if (pid == 0) {
        //子进程  
        handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

        return true;
    }
    ......
}

private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws ZygoteInit.MethodAndArgsCaller {
   

    if (parsedArgs.invokeWith != null) {
       
    } else {
        //这个函数我们上面已经分析了  

        //常规初始化
        //native层初始化,这是我们的App生来就能使用Binder的原因
        //java层初始化,这里我们像SystemServer一样反射调用android.app.ActivityThread的main函数
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
    }
}

我们的APP进程与SystemServer进程的异同

之所以比较这两者,是因为他们都是zygote的孩子。

相同点

我们的App与SystemServer相同,生来就支持Binder通信,这一步是通过native层初始化做到的,其内部打开了Binder设备,并创建了一个主线程与Binder通信。

不同点

SystemServerjava初始化反射调用了SystemServer的main方法,并在其中开启了Android的诸多重要系统服务,而我们的App的,则是反射调用了android.app.ActivityThread的main函数,在该函数中,与AMS所在SystemServer进程建立了联系,并初始化Looper等待消息,关于这部分内容可参看Android开发之漫漫长途 Ⅶ——Android消息机制(Looper Handler MessageQueue Message)

Activity Window View等概念

先有盘古后有天,三清更在盘古前。通过命令am start启动的Acitivty,Activity附属的进程已经启动了,那么Activity是什么时候创建的呢, AMS的startActivityAndWait最后会调用到ActivityStackSupervisor类的realStartActivityLocked函数,而该函数内部通过Binder方式调用了android.app.ActivityThread的scheduleLaunchActivity方法

[android.app.ActivityThread.java]

代码语言:javascript
复制
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

        updateProcessState(procState, false);

        ActivityClientRecord r = new ActivityClientRecord();

        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.referrer = referrer;
        r.voiceInteractor = voiceInteractor;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.persistentState = persistentState;

        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;

        r.startsNotResumed = notResumed;
        r.isForward = isForward;

        r.profilerInfo = profilerInfo;

        r.overrideConfig = overrideConfig;
        updatePendingConfiguration(curConfig);
        //sendMessage
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

sendMessage(H.LAUNCH_ACTIVITY, r);最终是由android.app.ActivityThread的内部类H的对象mH.sendMessage(msg);这个内部类H是继承自Handler的。所以一切也就明了了,我们来看H的handleMessage

代码语言:javascript
复制
public void handleMessage(Message msg) {
        ......
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                //调用handleLaunchActivity
                handleLaunchActivity(r, null);
            break;
            ......
        }
    ......
}

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    //调用performLaunchActivityy
    Activity a = performLaunchActivity(r, customIntent);
    ......
   
}

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        //创建activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ......
    } catch (Exception e) {
        ......
    }

    ......
    try {
        //创建Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (activity != null) {
            ......
            //回调activity的attach方法
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor);

    }
    return activity;
}

而在Activity的attach方法中我们可以看到

代码语言:javascript
复制
final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    .....
    //创建PhoneWindow
    mWindow = new PhoneWindow(this);
    mWindow.setCallback(this);
}

想知道关于Window更多的相关知识,可参看Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(1)以及Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(2)

小结


本篇总结

本篇是对前面博客的一个小总结,更多细节可参看前面几篇文章,下面给出链接

  1. 你想知道Activity的生命周期以及在Activity生命周期开始之前发生了什么吗?请参看Android开发之漫漫长途 Ⅰ——Android系统的创世之初以及Activity的生命周期
  2. 你想知道更多关于Window和View的知识吗?请参看Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(1)以及Android开发之漫漫长途 Ⅱ——Activity的显示之Window和View(2)
  3. 你对View的绘制体系有兴趣吗或者你还在迷惑onMeasure、onDraw、onLayout等方法吗?请参看Android开发之漫漫长途 Ⅳ——Activity的显示之ViewRootImpl初探以及Android开发之漫漫长途 Ⅴ——Activity的显示之ViewRootImpl的PreMeasure、WindowLayout、EndMeasure、Layout、Draw以及Android开发之漫漫长途 番外篇——自定义View的各种姿势1
  4. 你对View的事件体系有兴趣吗或者你还在头疼滑动冲突所带来的问题吗?请参看Android开发之漫漫长途 Ⅵ——图解Android事件分发机制(深入底层源码)以及Android开发之漫漫长途 番外篇——自定义View的各种姿势2
  5. 你对Binder机制有兴趣吗或者你还在呐喊到底什么是Binder吗?请参看Android开发之漫漫长途 VIII——Android Binder(也许是最容易理解的)以及Android开发之漫漫长途 IX——彻底掌握Binder
  6. 你对Android性能优化有兴趣吗或者你正在苦恼性能优化无从着手吗?请参看Android开发之漫漫长途 番外篇——内存泄漏分析与解决以及Android开发之漫漫长途 X——Android序列化

下篇预告

下篇我们来讲一下Fragment相关知识,读者如果有哪里不清楚,可以留言给我,有必要的话,单开一篇文章来共同交流。


此致,敬礼

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-01-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 奇点——init进程
    • 解析init.rc文件
      • 小结
      • zygote进程
        • AppRuntime
          • 小结
          • SystemServer
            • SystemServer的启动
              • SystemServer的重要使命
                • SystemServer native层的初始化
                • SystemServer java层的初始化
              • SystemServer小结
              • 我们的APP进程
                • 我们的APP进程与SystemServer进程的异同
                  • 相同点
                  • 不同点
                • Activity Window View等概念
                  • 小结
                  • 本篇总结
                  • 下篇预告
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档