Android10 Framework—Zygote-5.USAP

51 阅读1分钟

在runSelectLoop和processOneCommand有个usap的功能在前面的讲解中直接跳过,因为它不是主要流程所以未重点分析,这里提出来有兴趣的读者可以自行分析。

传统的应用启动模式由system_server中的AMS接收请求,之后通过socket告知zygote,让其完成fork动作,这样新进程便创建出来。不过从Android Q(10)开始,Google引入了一种新的机制:USAP(Unspecialized App Process)。通过prefork的方式提前创建好一批进程,当有应用启动时,直接将已经创建好的进程分配给它,从而省去了fork的动作,因此可以提升性能。

这种机制在AOSP的源码中默认是关闭的,但估计很多手机厂家已经提前尝鲜了。

参考文章:
blog.csdn.net/mafei852213… www.jianshu.com/p/ee0b5baa4… www.mo4tech.com/android-fra…

Runnable runSelectLoop(String abiList) {
    

    while (true) {
        
        if (mUsapPoolEnabled) {
            usapPipeFDs = Zygote.getUsapPipeFDs();
            pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
        } else {
            pollFDs = new StructPollfd[socketFDs.size()];
        }

        /*
         * For reasons of correctness the USAP pool pipe and event FDs
         * must be processed before the session and server sockets.  This
         * is to ensure that the USAP pool accounting information is
         * accurate when handling other requests like API blacklist
         * exemptions.
         */

        int pollIndex = 0;
        for (FileDescriptor socketFD : socketFDs) {
            pollFDs[pollIndex] = new StructPollfd();
            pollFDs[pollIndex].fd = socketFD;
            pollFDs[pollIndex].events = (short) POLLIN;
            ++pollIndex;
        }

        final int usapPoolEventFDIndex = pollIndex;

        if (mUsapPoolEnabled) {
            pollFDs[pollIndex] = new StructPollfd();
            pollFDs[pollIndex].fd = mUsapPoolEventFD;
            pollFDs[pollIndex].events = (short) POLLIN;
            ++pollIndex;

            for (int usapPipeFD : usapPipeFDs) {
                FileDescriptor managedFd = new FileDescriptor();
                managedFd.setInt$(usapPipeFD);

                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = managedFd;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            }
        }

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

            if (pollIndex == 0) {
                // Zygote server socket

                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                socketFDs.add(newPeer.getFileDescriptor());

            } else if (pollIndex < usapPoolEventFDIndex) {
                
            } else {
                

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