Android framework源码分析二 应用进程启动流程源码分析(Android8.0)

概述

首先附上我的几篇其它文章链接感兴趣的可以看看,如果文章有异议的地方欢迎指出,共同进步,顺便点赞谢谢!!!
Android studio编写第一个NDK工程的过程详解(附Demo下载地址)
面试必备1:HashMap(JDK1.8)原理以及源码分析
面试必备2:JDK1.8LinkedHashMap实现原理及源码分析
Android事件分发机制原理及源码分析
View事件的滑动冲突以及解决方案
Handler机制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源码
Android三级缓存原理及用LruCache、DiskLruCache实现一个三级缓存的ImageLoader

本文是在上文Android framework 源码分析之Activity启动流程(android 8.0)的基础上多应用进程创建、启动以及进程启动后启动activity过程分析。中间涉及Launcher、AMS、Binder、Process、LocalSocket、Zygote、fork等知识。

上一篇文章中对Activity的启动流程做了详细的分析,在第三部分的Step13ActivityStackSupervisor类的startSpecificActivityLocked方法中分析到如果activity所在进程已经启动的情况,今天就来分析一下进程未启动的情况,即App的启动流程。

其实app的启动最后也是通过调用Activity的startActivity方法,最终走到上图中AMSstartProcessLocked方法,在startProcessLocked先去启动App所在的进程,启动这个进程的过程牵扯了:Zygote进程和 system_server进程,在这个过程中所有跨进城都离不开Binder机制。

1:APP启动的入口Launcher的分析

Android 系统启动后已经启动了 Zygote,ServiceManager,SystemServer 等系统进程;ServiceManager 进程中完成了 Binder 初始化;SystemServer 进程中 ActivityManagerService,WindowManagerService,PackageManagerService 等系统服务在 ServiceManager 中已经注册;最后启动了 Launcher 桌面应用。

Launcher本神就是一个应用,被系统启动,这里不详细分析分析Launcher的源码,我们从点击桌面上的图标入手分析,即启动APP的入口
Step1: Launcher中条目的点击监听的onClick方法开始:

/**
     * Launches the intent referred by the clicked shortcut.
     * 启动被单击的快捷方式引用的意图
     */
    public void onClick(View v) {
          ....代码
        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            onClickAppShortcut(v);
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                onClickFolderIcon(v);
            }
        } else if ((v instanceof PageIndicator) ||
                (v == mAllAppsButton && mAllAppsButton != null)) {
            onClickAllAppsButton(v);
        } else if (tag instanceof AppInfo) {//如果属于AppInfo,里面包含了启动的APP的信息
            //交给startAppShortcutOrInfoActivity 去处理
            startAppShortcutOrInfoActivity(v);
        } else if (tag instanceof LauncherAppWidgetInfo) {
            if (v instanceof PendingAppWidgetHostView) {
                onClickPendingWidget((PendingAppWidgetHostView) v);
            }
        }
    }

经过一些简单校验交给交给startAppShortcutOrInfoActivity 去处理。

Step2: Launcher的startAppShortcutOrInfoActivity 方法启动APP:

 private void startAppShortcutOrInfoActivity(View v) {
        ...省略部分代码,主要是对intent进行校验
        //交给startActivitySafely去启动
        boolean success = startActivitySafely(v, intent, item);
        getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
        if (success && v instanceof BubbleTextView) {
            mWaitingForResume = (BubbleTextView) v;
            mWaitingForResume.setStayPressed(true);
        }
    }

首先对intent进行校验,最终将将启动任务交给了startActivitySafely方法

扫描二维码关注公众号,回复: 11401028 查看本文章

Step3: Launcher的startActivitySafely 方法启动APP:

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        ...省略部分代码
        try {
            if (Utilities.ATLEAST_MARSHMALLOW
                    && (item instanceof ShortcutInfo)
                    && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                    || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                    && !((ShortcutInfo) item).isPromise()) {
                //快捷启动需要进行一些校验
                startShortcutIntentSafely(intent, optsBundle, item);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                // 最终执行父类Activity的startActivity方法
                startActivity(intent, optsBundle);
            }
            ...省略代码
        return false;
    }

**小结:**这startActivitySafely方法中,最终将启动任务交给了父类Activity的startActivity方法去启动APP,自己在进入onPause状态。自此APP的的启动流程就进入了Activity的启动流程,如果没有看过请先阅读我的第一篇文章Android framework 源码分析之Activity启动流程(android 8.0)

2:APP的启动在Activity中启动过程

在Activity中启动过程在Android framework 源码分析之Activity启动流程(android 8.0)中已做了详细分析,都是从ActivitystartActivityForResult开始一直到上文Step12 都是一致的在此不做分析,接下来我们着重看一下Step13ActivityStackSupervisor类的startSpecificActivityLocked方法

Step4: ActivityStackSupervisor的startSpecificActivityLocked 方法启动分析:

 void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
        r.getStack().setLaunchTime(r);
        if (app != null && app.thread != null) {
         //app进程已经在运行,直接去启动
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    //如果它是一个被标记为在多个进程中运行的平台组件,那么不要添加它,因为它实际上是框架的一部分,所以在进程中作为单独的apk进行跟踪是没有意义的
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //重点:将activity的启动工作转交给realStartActivityLocked方法
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e);
            }
            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }
        // 如果进程为app 为null或者有异常,则AMS重新fork一个进程来起来,点击桌面启动图标如果该应用进程未启动,走到这里
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

分析:
startSpecificActivityLocked方法逻辑比较简单,主要负责跟要启动的Activity进程相关的工作,首先由AMS根据参数通过getProcessRecordLocked方法获取当前APP进程的记录ProcessRecord ,如果获取到ProcessRecord即应用所在进程已经启动,则执行realStartActivityLocked方法,否则应用进程未启动,则交给AMSstartProcessLocked方法去启动该进程。
至于方法里if里面realStartActivityLocked方法的内容已经在上文中分析了,接下来我们继续分析else部分的逻辑,即APP的启动。

3:APP的启动在AMS中启动过程

Step5: ActivityManagerService的startProcessLocked 方法去启动进程的逻辑分析:

 final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags,
                                           String hostingType, ComponentName hostingName, boolean allowWhileBooting,
                                           boolean isolated, boolean keepIfLarge) {
         //调用它的重载方法,需要注意的是,加入一个参数叫做entryPoint,并且参数为null
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

继续分析重载方法

 final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
                                           boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
                                           boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
                                           String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        ProcessRecord app;
        // isolated表示当前需要启动的app是不是一个独立的进程,如果是独立的话那就重新
        // 创建一个ProcessRecord,如果不是的话那就从正在运行的进程列表中找。
        if (!isolated) {
            //根据进程名和进程uid获取进程对应的ProcessRecord,ProcessRecord封装了正在运行的进程的完整信息
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            ....省略部分代码
            //   这是一个独立的进程或者在正在运行的列表中没有找到相应的记录
        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            //创建ProcessRecord
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            //一堆赋值操作
            app.crashHandler = crashHandler;
            app.isolatedEntryPoint = entryPoint;
            app.isolatedEntryPointArgs = entryPointArgs;
            checkTime(startTime, "startProcess: done creating new process record");
        } else {
             // // 如果这是该进程中的一个新的package,那就添加到package列表
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: added package to existing proc");
        }
       // 如果系统还没有准备就绪,那就暂停该进程启动,将当前进程加入到mProcessesOnHold,直到准备就绪
        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            if (!mProcessesOnHold.contains(app)) {
                mProcessesOnHold.add(app);
            }
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                    "System not ready, putting on hold: " + app);
            checkTime(startTime, "startProcess: returning with proc on hold");
            return app;
        }

        checkTime(startTime, "startProcess: stepping in to startProcess");
        //重点,经过上面判断如果需要创建进程,最终交给    startProcessLocked方法去创建进程,注意这个方法的返回值boolean
        final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
        checkTime(startTime, "startProcess: done starting proc!");
        return success ? app : null;
    }

**分析:这里逻辑比较简单, 这里再次检查是否已经有以process + uid命名的进程存在,如果我们首次启动这个app,则app==null,因此,后面会创建一个ProcessRecord,并存保存在成员变量mProcessNames中,最终即进程的启动交给了startProcessLocked 方法,注意此方法的返回值是boolean

Step6: AMS的boolean startProcessLocked 方法分析:

 private final boolean startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr, String abiOverride) {
           //继续调用重载方法传入参数disableHiddenApiChecks    为false
        return startProcessLocked(app, hostingType, hostingNameStr,
                false /* disableHiddenApiChecks */, abiOverride);
    }

继续分析重载方法

  private final boolean startProcessLocked(ProcessRecord app, String hostingType,
                                             String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {

            ....省略部分代码,这着重看流程
             //重点: 这里给一开传进来的entryPoint赋值给"android.app.ActivityThread"后面通过它进行反射来调用ActivityThread 的main方法
            final String entryPoint = "android.app.ActivityThread";
            //最后交给重载方法startProcessLocked去完成启动进程的工作
            return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                    startTime);
        } catch (RuntimeException e) {
            Slog.e(TAG, "Failure starting process " + app.processName, e);
            //异常时强制停止启动
            forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
                    false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
            return false;
        }
    }

继续分析其重载方法:

private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
                                       ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
                                       String seInfo, String requiredAbi, String instructionSet, String invokeWith,
                                       long startTime) {
        //给ProcessRecord的一些属性进行一波赋值操作
        app.pendingStart = true;
        app.killedByAm = false;
        app.removed = false;
        app.killed = false;
        final long startSeq = app.startSeq = ++mProcStartSeqCounter;
        app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);
        if (mConstants.FLAG_PROCESS_START_ASYNC) {//异步时
            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                    "Posting procStart msg for " + app.toShortString());
            mProcStartHandler.post(() -> {
                try {
                      ...省略部分代码
                    }
                    //最终调用startProcess去启动
                    final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                            requiredAbi, instructionSet, invokeWith, app.startTime);
                    synchronized (ActivityManagerService.this) {
                        handleProcessStartedLocked(app, startResult, startSeq);
                    }
                } catch (RuntimeException e) {
                        //异常时强制停止启动
                }
            });
            return true;
        } else {
            try {
                //最终调用startProcess去启动
                final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
                        uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
                        invokeWith, startTime);
                handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                        startSeq, false);
            } catch (RuntimeException e) {
                //异常时强制停止启动
            }
            return app.pid > 0;
        }
    }

分析:经过上面无论if还是else,最终将启动进程的工作转移到startProcess方法上

Step7: AMS的startProcess 方法启动分析:

  private ProcessStartResult startProcess(String hostingType, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            final ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
            //在最初ActivityStackSupervisor的startSpecificActivityLocked方法那可以看出传入的hostingType  等于activity,所以if语句不执行
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
            } else {
                 //最终执行到这  这里主要是调用Process.start接口来创建一个新的进程,成功后会返回进程的pid         foui 否则就会抛出异常,  需要注意的是这个过程是一个阻塞过程, 还有传入的entryPoint值就是上面传入的android.app.ActivityThread
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
            }
            checkTime(startTime, "startProcess: returned from zygote!");
            return startResult;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

分析:
最后是通过Process.start来创建应用进程;原理是通过socketZygote进程发送创建新进程的请求;Zygote进程启动后有一个runSelectLoop循环,当收到客户端请求便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程,创建新进程后将ActivityThread类加载到新进程,并反射调用ActivityThread.main()方法,就这样创建进程的启动app的任务就转移到Processstart方法中。接下来我就来详细分析这个流程。

4:Process、ZygoteProcess的启动过程

Step8: **Process的star 方法分析:

/**
 *  需要注意processClass参数就是上文提到entryPoint的值   android.app.ActivityThread
 */
public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int runtimeFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String invokeWith,
                                  String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }

这个方法的逻辑比较简单主要是通过 ZygoteProcessstart方法创建新进程。

Step9: ZygoteProcess的startProcess 方法分析:

public final Process.ProcessStartResult start(final String processClass,
                                                  final String niceName,
                                                  int uid, int gid, int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  String seInfo,
                                                  String abi,
                                                  String instructionSet,
                                                  String appDataDir,
                                                  String invokeWith,
                                                  String[] zygoteArgs) {
        try {
            //最后交给startViaZygote方法去创建新进程
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
                    zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

Step10: ZygoteProcess的startViaZygote 方法创建进程的过程分析:
先大致说明一下接下来的工作流程:在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。接下来我们将详细分析这一过程。

 private Process.ProcessStartResult startViaZygote(final String processClass,
                                                      final String niceName,
                                                      final int uid, final int gid,
                                                      final int[] gids,
                                                      int runtimeFlags, int mountExternal,
                                                      int targetSdkVersion,
                                                      String seInfo,
                                                      String abi,
                                                      String instructionSet,
                                                      String appDataDir,
                                                      String invokeWith,
                                                      boolean startChildZygote,
                                                      String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<String>();
         ...省略部分代码   主要是将进程相关的uid、gid等一系列信息保存到argsForZygote集合中
        synchronized(mLock) {
            //最终将创建进程的工作交过zygoteSendArgsAndGetResult方法
           //需要注意的是第一个参数是通过openZygoteSocketIfNeeded方法去构建的,几下来就依次分析这两个方法
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

分析:这个方法逻辑比较简单,首先是将进程相关的信息保存到argsForZygote集合中,并将该集合作为参数,交给zygoteSendArgsAndGetResult方法去创建进程,需要注意的是第一个参数是通过openZygoteSocketIfNeeded方法去构建的。

Step11: ZygoteProcess的openZygoteSocketIfNeeded 方法分析:

 private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
        //   调用该方法时传入的参数就是上面我们说 的abi了,也就是我们要启动的目标进程到底是调用Zygote32来fork,还是调用Zygote64来fork
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        //primaryZygoteState是否为空或者已经关闭
            try {   
            //调用ZygoteState.connect(mSocket),尝试与Zygote进程建立socket连接
                primaryZygoteState = ZygoteState.connect(mSocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
        }
        //然后去匹配abi
        if (primaryZygoteState.matches(abi)) {
        	//如果成功则返回ZygoteState来启动目标进程
            return primaryZygoteState;
        }
          
        // The primary zygote didn't match. Try the secondary.
        //  //当主zygote没能匹配成功,则采用第二个zygote,发起connect()操作,逻辑和上面一样
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
        }
        //根据abi去匹配
        if (secondaryZygoteState.matches(abi)) {
            return secondaryZygoteState;
        }
        //如果都匹配失败则直接抛出ABI
        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }

分析:简单总结一下openZygoteSocketIfNeeded,通过ZygoteState.connect方法尝试与Zygote进程建立socket连接,返回一个ZygoteStatee连接状态,拿到这个ZygoteState连接状态后就可以进行写操作,而与之建立连接的Zygote进程会读取到这个信息。

Step12: ZygoteProcess的静态内部类ZygoteState的connect 方法分析:

public static class ZygoteState {
        final LocalSocket socket;
        final DataInputStream inputStream;
        final BufferedWriter writer;
        final List<String> abiList;
        boolean mClosed;
        private ZygoteState(LocalSocket socket, DataInputStream inputStream,
                            BufferedWriter writer, List<String> abiList) {
            this.socket = socket;
            this.inputStream = inputStream;
            this.writer = writer;
            this.abiList = abiList;
        }
        
       //重点:传进来本地Socket的地址
        public static ZygoteState connect(LocalSocketAddress address) throws IOException {
            DataInputStream zygoteInputStream = null;
            BufferedWriter zygoteWriter = null;
            //传说中的Socket
            final LocalSocket zygoteSocket = new LocalSocket();
            try {
                //建立LocalSocket 连接,根据地址LocalSocketAddress 
                zygoteSocket.connect(address);
                //指向zygoteSocket输入
                zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
                //指向zygoteSocket输出
                zygoteWriter = new BufferedWriter(new OutputStreamWriter(zygoteSocket.getOutputStream()), 256);
            } catch (IOException ex) {
                try {
                    zygoteSocket.close();
                } catch (IOException ignore) {
                }
                throw ex;
            }
            //获取zygote 进程支持的 ABI类标Application Binary Interface
            String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
            Log.i("Zygote", "Process: zygote socket " + address.getNamespace() + "/"
                    + address.getName() + " opened, supported ABIS: " + abiListString);
            //通过socket  输入  输出   abi 列表创建 ZygoteState
            return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
                    Arrays.asList(abiListString.split(",")));
        }
        boolean matches(String abi) {
            return abiList.contains(abi);
        }
        public void close() {
            try {
                socket.close();
            } catch (IOException ex) {
                Log.e(LOG_TAG,"I/O exception on routine close", ex);
            }
            mClosed = true;
        }
        boolean isClosed() {
            return mClosed;
        }
    }

分析:ZygoteState内部类的主要作:表示和Zygote进程的连接状态,里面有几个成员变量存储LocalSocket ,以及指向LocalSocket的输入、输出流等。而里面的connect方法就是初始化这些变量,创建并返回ZygoteState。这里需要简单分析一下LocalSocketconnect方法的参数LocalSocketAddress

小插曲LocalSocket、LocalSocketAddress 和LocalServerSocket的关系

这里只是简单看一下远离流程以及它们之间的关系,至于他们的详细源码就不一一贴出分析了。

LocalSocketAddress 就是LocalSocket的地址看看它的初始化过程:
1: public static ZygoteState connect(LocalSocketAddress address) 方法中传进来的LocalSocketAddress 就是ZygotePrecess的成员变量,初始化是在构造器中,如下图:
在这里插入图片描述

2:接下来再看看ZygotePrecess构造器中的参数是什么:ZygotePrecess构造器在Precess中调用
在这里插入图片描述

接下来再说说LocalSocket和LocalServerSocket的关系:他门俩个之间的关系类似于Socket编程中:Socekt和ServerSocket的关系

平时用到的Socket,Socket通常是为了方便**两台不同的机器之间的通信,**它封装了TCP/IP协议,向外提供一些API简化了网络通信过程,可以实现不同层面,不同应用,跨进程跨网络的通信;一般由Socket(client)和ServerSocket(Server)组成通信双方。

而Android中的LocalSocket是基于UNIX-domain Socket的,UNIX-domain Socket是在Socket的基础上衍生出来的一种IPC通信机制,**因此LocalSocket解决的是同一台主机上不同进程间互相通信的问题。其相对于网络通信使用的socket不需要经过网络协议栈,不需要打包拆包、计算校验,自然的执行效率也高。**与binder机制作用一样,都在Android系统中作为IPC通信手段被广泛使用;一般由LocalSocket(Client)和LocalServerSocket(Server)组成通信双方。

那么在本文中AMS所在的system-server进程就充当了Client,zygote进程充当Server,因为zygote进程在创建的时候会在ZygoteInit.main方法中调用ZygoteInit.registerZygoteSocket方法,会实例化一个LocalServerSocket,并且在ZygoteInit.runSelectLoop方法中不停的获取客户端的请求。

关于LocalSocket、LocalSocketAddress 和LocalServerSocket分析先到这里,详细源码我就不在这里粘出了,接下我们继续回到ZygoteProcess的zygoteSendArgsAndGetResult 方法,通过LocalSocket发送参数给Zygote进程。

Step13: ZygoteProcess的zygoteSendArgsAndGetResult 方法分析:

  private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            //首先校验上一步传递过来的参数格式,如果参数不合法,抛出异常
            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                if (args.get(i).indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx("embedded newlines not allowed");
                }
            }

            /**
             * See com.android.internal.os.SystemZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure, followed by boolean to
             * indicate whether a wrapper process was used.
             */
             //通过连接状态 获取输入输出流
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;
			//将参数通过Socket写出去,至于从哪里读,请看上面的英文注解,至于读取将在ZygoteInit类中找
            writer.write(Integer.toString(args.size()));
            writer.newLine();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                writer.write(arg);
                writer.newLine();
            }
            writer.flush();
            // Should there be a timeout on this?
            // 新建进程启动结果类,把新建的结果例如进程pid等赋值给这个结果类,用来返回
            Process.ProcessStartResult result = new Process.ProcessStartResult();

            // Always read the entire result from the input stream to avoid leaving
            // bytes in the stream for future process starts to accidentally stumble
            // upon.
            result.pid = inputStream.readInt();
            result.usingWrapper = inputStream.readBoolean();

            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            //将启动结果返回
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

分析 :这里zygoteSendArgsAndGetResult方法,通过上一步中的连接状态获取输出流,将创建进程的参数通过Socket发送给给Zygote进程,通知Zygote去创建进程,并返回结果。Zygote进程是在系统启动初始化的,Zygote在启动之后开启了socket 监听功能,监听需要创建 Process 的请求,关于zygote进程什么时候开启这个socket的需要去看Zygote的源码。
这里为止,创建APP进程的工作交给了Zygote进程去完成。

5:Zygote完成创建APP进程的过程:ZygoteInit、ZygoteServer和ZygoteConnection

Zygote进程是在Android系统启动时就会完成Zygote的启动,在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,关于Zygote的启动以后我会单独写一篇文章去分析,在这里我将详细分析一下Zygote进程作为服务端什么时候开启的Socket监听,完成进程的创建过并将进程pid返回的过程,而这个过程与ZygoteInit、ZygoteServer和ZygoteConnection三个类密切相关。

Zygote进程启动的时候会调用ZygoteInit的main方法接下我将从它入手。

Step14: ZygoteInit的main 方法分析:

   public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        //...省略部分代码
        try {
            //...省略部分代码
            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }
            //为Zygote注册socket监听 :LocalServerSocket,具源码很简单,就不在下面粘贴了,感兴趣和可以自己查阅
            zygoteServer.registerServerSocketFromEnv(socketName);
            //...省略部分代码
            //初始化Zygote进程 非重点
            Zygote.nativeSecurityInit();

            //...省略部分代码

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            //进入循环模式,通过zygoteServer获取客户端Socket连接并处理
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }
        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

分析:在 ZygoteInit的main 方法中为通过zygoteServer.registerServerSocketFromEnv方法为Zygote注册socket监听LocalServerSocket;并开启循环,通过zygoteServerrunSelectLoop(abiList)方法获取客户端Socket连接并处理。至于注册socket监听LocalServerSocket的过程比较简单就不在这里分析了,接下来着重分析runSelectLoop(abiList)获取客户端Socket连接并处理的过程。

Step15: ZygoteServer的runSelectLoop 方法分析:

Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        // sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);
        //开启循环
        while (true) {
            // ...省略部分源码
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
                Os.poll(pollFds, -1);
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                // 即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
                // 则创建ZygoteConnection对象,并添加到peers
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    //i>0,则代表通过socket接收来自对端的数据,并执行相应操作
                    try {
                        //通过processOneCommand去处理客户端发来的Socket请求
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);

                        if (mIsForkChild) {
                            //Set by the child process, immediately after a call to {@code Zygote.forkAndSpecialize}.
                            //由子进程设置,后立即调用Zygote.forkAndSpecialize
                            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(i);
                                fds.remove(i);
                            }
                        }
                    } catch (Exception 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;
                    }
                }
            }
        }
    }

继续分析ZygoteConnectionconnection.processOneCommand(this)方法如何处理客户端发送来的请求

Step16: ZygoteConnection的processOneCommand 方法分析:

   /**
     * Reads one start command from the command socket. If successful, a child is  and a
     * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
     * process. {@code null} is always returned in the parent process (the zygote).
     * If the client closes the socket, an {@code EOF} condition is set, which callers can test
     * for by calling {@code ZygoteConnection.isClosedByPeer}.
     */
    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;
        try {
            //读取上文提到client端发送来创建进程需要的参数列表
            args = readArgumentList();
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }
        // readArgumentList returns null only when it has reached EOF with no available
        // data to read. This will only happen when the remote socket has disconnected.
        //readArgumentList只有在到达EOF且没有可用数据可读时才返回null。这只会在客户端断开连接时发生。
        if (args == null) {
            isEof = true;
            return null;
        }
        int pid = -1;
        FileDescriptor childPipeFd = null;
        FileDescriptor serverPipeFd = null;
        //将从客户端读取来的参数封装成 Arguments对象
        parsedArgs = new Arguments(args);

        //... 省略部分代码

        fd = null;
        //通过Zygote进程的forkAndSpecialize方法去创建进程,并返回进程的pid
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
                parsedArgs.instructionSet, parsedArgs.appDataDir);
       //上面创建进程,下面负责启动
        try {
            //Zygote 创建进程完成后  将分成一下两种情况处理
            if (pid == 0) {
                // in child 当前返回的是子进程
                zygoteServer.setForkChild();
                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                //子进程处理流程
                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.startChildZygote);
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.   当前返回的是父进程 ,Zygote进程
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                //父进程处理
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

分析: processOneCommand方法首先读取客户端发送过来的参数列表,并将这些参数列表封装成Arguments对象,并交给Zygote.forkAndSpecialize去完成进程的创建工作,并返回目标进程的pid,再往下就是根据pid==0说明当前返回的是子进程,交给handleChildProc方法去处理;否则返回的是父进程交给handleParentProc去处理。

Step17: Zygote的forkAndSpecialize 方法分析:

public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
                                        int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
                                        int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
        //调用preFork方法做一些准备工作
        //这个方法的主要目的是停止zygote进程的四个daemon子线程,分别是ReferenceQueueDaemon,FinalizerDaemon,FinalizerWatchdogDaemon,HeapTaskDaemon;
        //直到zygote是是单线程,以便于提高fork效率;
        VM_HOOKS.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        //重点是调用这个native方法去创建进程返回进程的pid,这个过程经过JNI完成的
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir);
        // Enable tracing as soon as possible for the child process.
        if (pid == 0) {
            Trace.setTracingEnabled(true, runtimeFlags);

            // Note that this event ends at the end of handleChildProc,
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

    //nativie  接口 它的实现完成进程的创建工作
    native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags,int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir);

分析: forkAndSpecialize方法逻辑比较简单首先通过VM_HOOKS.preFork()为创建进程做一些准备工作,然后调用native方法nativeForkAndSpecialize去完成具体创建进程的工作。

Native层调用Linux系统fork函数完成创建进程的过程

接下来看看native方法nativeForkAndSpecialize的实现,此方法的实现是在com_android_internal_os_Zygote.cpp文件中,目录路径为:frameworks\base\core\jni\com_android_internal_os_Zygote.cpp

Step18: native的nativeForkAndSpecialize 方法:

static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring se_name,
        jintArray fdsToClose,
        jintArray fdsToIgnore,
        jstring instructionSet, jstring appDataDir) {
    jlong capabilities = 0;
    if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
      capabilities |= (1LL << CAP_WAKE_ALARM);
      capabilities |= (1LL << CAP_NET_RAW);
      capabilities |= (1LL << CAP_NET_BIND_SERVICE);
      capabilities |= (1LL << CAP_SYS_NICE);
    }
    // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
    bool gid_wakelock_found = false;
    if (gid == AID_WAKELOCK) {
      gid_wakelock_found = true;
    } else if (gids != NULL) {
      jsize gids_num = env->GetArrayLength(gids);
      ScopedIntArrayRO ar(env, gids);
      if (ar.get() == NULL) {
        RuntimeAbort(env, __LINE__, "Bad gids array");
      }
      for (int i = 0; i < gids_num; i++) {
        if (ar[i] == AID_WAKELOCK) {
          gid_wakelock_found = true;
          break;
        }
      }
    }
    if (gid_wakelock_found) {
      capabilities |= (1LL << CAP_BLOCK_SUSPEND);
    }
   //最终将创建进程的工作交给ForkAndSpecializeCommon方法去完成
    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
            rlimits, capabilities, capabilities, mount_external, se_info,
            se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
}

Step19: native的ForkAndSpecializeCommon 方法:

static pid_t ForkAndSpecializeCommon(JNIEnv*env, uid_t uid, gid_t gid, jintArray javaGids,
                                         jint debug_flags, jobjectArray javaRlimits,
                                         jlong permittedCapabilities, jlong effectiveCapabilities,
                                         jint mount_external,
                                         jstring java_se_info, jstring java_se_name,
                                         bool is_system_server, jintArray fdsToClose,
                                         jintArray fdsToIgnore,
                                         jstring instructionSet, jstring dataDir) {
        //设置子进程的signal信号处理函数
        SetSigChldHandler();
        sigset_t sigchld;
        sigemptyset( & sigchld);
        sigaddset( & sigchld, SIGCHLD);

        //...  省略部分代码

        // 重点:fork是Linux的系统函数,是真正执行复制进程的工作,因为Zygote进程的权限很高,
        // fork方法会一模一样的复制Zygote作为我们要创建的目标进程,这样的话就会导致目标应用进程也有很高的权限去操作各种文件
        // fork出来的进程就是我们要启动的进程,接下来我们要为目标进程设置一系列的属性
        pid_t pid = fork();

        if (pid == 0) {//进入子进程
            // The child process.
            gMallocLeakZygoteChild = 1;
            // Set the jemalloc decay time to 1.
            mallopt(M_DECAY_TIME, 1);
            // Clean up any descriptors which must be closed immediately
            //关闭并清除文件描述符
            DetachDescriptors(env, fdsToClose);

            //...  省略部分代码

            if (!is_system_server) {
                //对于非system_server子进程,则创建进程组
                int rc = createProcessGroup(uid, getpid());
                if (rc != 0) {
                    if (rc == -EROFS) {
                        ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
                    } else {
                        ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
                    }
                }
            }
            //下面为目标进程的属性赋值
            //设置group
            SetGids(env, javaGids);
            //设置调度策略
            SetRLimits(env, javaRlimits);

            if (use_native_bridge) {
                ScopedUtfChars isa_string (env, instructionSet);
                ScopedUtfChars data_dir (env, dataDir);
                android::PreInitializeNativeBridge (data_dir.c_str(), isa_string.c_str());
            }
            //设置目标进程的gid
            int rc = setresgid(gid, gid, gid);
            if (rc == -1) {
                ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
                RuntimeAbort(env, __LINE__, "setresgid failed");
            }
            //设置目标进程的uid
            rc = setresuid(uid, uid, uid);
            if (rc == -1) {
                ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
                RuntimeAbort(env, __LINE__, "setresuid failed");
            }

            if (NeedsNoRandomizeWorkaround()) {
                // Work around ARM kernel ASLR lossage (http://b/5817320).
                int old_personality = personality(0xffffffff);
                int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
                if (new_personality == -1) {
                    ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
                }
            }

            SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
            //为目标进程设置调度策略
            SetSchedulerPolicy(env);

            //...  省略部分代码
            //在Zygote子进程中,设置信号SIGCHLD的处理器恢复为默认行为
            UnsetSigChldHandler();
            // 等价于调用zygote.callPostForkChildHooks()
            env -> CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                    is_system_server, instructionSet);
            if (env -> ExceptionCheck()) {
                RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
            }
        } else if (pid > 0) {
            // the parent process 进入父进程,即Zygote进程
    
            // We blocked SIGCHLD prior to a fork, we unblock it here.
            if (sigprocmask(SIG_UNBLOCK, & sigchld,nullptr) ==-1){
                ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
                RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
            }
        }
        return pid;
    }

分析: ForkAndSpecializeCommon方法最核心的就是pid_t pid = fork()通过Linux的fork机制复制Zygote进程作为要启动的目标进程,接下来在为复制的目标进程的属性赋值,最后返回目标进程的pid。到这里就回到Step16: ZygoteConnectionprocessOneCommand方法创建进程后子进程(即目标进程)的处理流程,即handleChildProc方法;看下图:
在这里插入图片描述

Step20: ZygoteConnection的handleChildProc 方法:

private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
                                     FileDescriptor pipeFd, boolean isZygote) {
        /**
         * By the time we get here, the native code has closed the two actual Zygote
         * socket connections, and substituted /dev/null in their place.  The LocalSocket
         * objects still need to be closed properly.
         */
        //关闭Socket
        closeSocket();
        if (descriptors != null) {
            try {
                Os.dup2(descriptors[0], STDIN_FILENO);
                Os.dup2(descriptors[1], STDOUT_FILENO);
                Os.dup2(descriptors[2], STDERR_FILENO);

                for (FileDescriptor fd: descriptors) {
                    IoUtils.closeQuietly(fd);
                }
            } catch (ErrnoException ex) {
                Log.e(TAG, "Error reopening stdio", ex);
            }
        }

        if (parsedArgs.niceName != null) {
            //设置进程名
            Process.setArgV0(parsedArgs.niceName);
        }

        // End of the postFork event.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //应用进程首次启动时,parsedArgs.invokeWith参数为空,所以执行else
        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.remainingArgs);

            // Should not get here.
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            /**
             * isZygote  :whether this new child process is itself a new Zygote
             * isZygote来自上面的parsedArgs中的startChildZygote属性---》 parsedArgs = new Arguments(args);
             * args上面分析过是从客户端发来的参数---》去客户端发送参数那看:
             *     可以追踪到ZygotePrecess类的startViaZygote方法:再startViaZygote方法中的参数  boolean startChildZygote  
             *     传进来 是 false
             * 所以:这里  isZygote 为false  !isZygote 为true
             */
            if (!isZygote) {
                //所以会执行这里
                return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
                        null /* classLoader */);
            } else {
                //启动一个子的Zygote
                return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs, null /* classLoader */);
            }
        }
    }

分析: handleChildProc 这个方法逻辑比较简单,注释也标注的很清楚,最后交给了 ZygoteInit的zygoteInit方法去处理。

Step21: ZygoteInit的zygoteInit 方法分析:

   public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        ///把标准输出和标准错误重定向给log.i和log.e
        RuntimeInit.redirectLogStreams();
		//针对日志和异常处理进行初始化
        RuntimeInit.commonInit();
        //这里的作用是在新进程中引入Binder,也就说通过nativeZygoteInit以后,新的进程就可以使用Binder进程通信了。
        ZygoteInit.nativeZygoteInit();
        //初始化我们的应用进程。重点
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

**分析:**最后就是调用RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader)来初始化我们的应用程序。继续往下看。

Step22: RuntimeInit的applicationInit 方法分析:

 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
                                              ClassLoader classLoader) {
        //如果应用程序调用System.exit(),则终止进程
        nativeSetExitWithoutCleanup(true);
        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        //我们希望相当积极地处理堆利用率,以避免占用大量不需要的内存。
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        //传入的参数封装成一个Arguments对象
        final Arguments args = new Arguments(argv);
        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        // 会通过调用findStaticMain来调用args.startClass这个类的main()方法。
        // 在前面介绍socket的客户端代码时,在startProcessLocked()中传入的这个类为"android.app.ActivityThread"。
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

分析:applicationInit() 方法的最后,会通过调用findStaticMain来调用args.startClass这个类的main()方法。在前面介绍socket的客户端代码时,在startProcessLocked()中传入的这个类为"android.app.ActivityThread"。所以接下来findStaticMain()主要功能就是通过反射调用调用ActivityThread类的main()方法

Step23: RuntimeInit的findStaticMain 方法分析:

protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
        Class<?> cl;
        try {
            //通过类加载器获取 Activitythread 类对象
           cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }
        Method m;
        try {
            //获取反射获取Activitythread  main方法
            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);
        }
        //交给 MethodAndArgsCaller去处理 ,8.0之前是通过抛出异常的形式反射调用main方法
        return new MethodAndArgsCaller(m, argv);
    }

再往下看,就是反射调用main

  static class MethodAndArgsCaller implements Runnable {
        private final Method mMethod;
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }
        public void run() {
            try {
                //反射调用 ActivityThread的main方法启动应用程序
                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);
            }
        }
    }

Step24: ActivityThread的Main 方法分析:

   public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");
        //初始化主线成的looper
        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        //重点  attach方法:
        thread.attach(false, startSeq);
        //初始化主线成的handler
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //开启消息循环
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

分析: ActivityThradmain方法就是应用程序的入口,main方法执行表示应用程序的启动,再往后面的的几步分析主要是讲应用进程启动后,启动Activity 和关联Context等操作过程。下面简单过一下启动Activity的过程,至于详细过程以及关联Context操作以后将会专门写一篇ActivityThrad的工作流程源码分析中详细介绍。

6:应用的进程启动后,启动Activity 和关联Context的过程。

Step25: ActivityThread的attach 方法分析:

 private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            //mgr 就是ActivityManagerService对象.   
            final IActivityManager mgr = ActivityManager.getService();
            try {
                 // 重点
                //通过Binder机制调用ActivityManagerService的attachApplication方法
                mgr.attachApplication(mAppThread, startSeq);

            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            //...省略部分代码
            ViewRootImpl.addConfigCallback(configChangedCallback);
        }
    }

分析: attach方法中, mgr.attachApplication(mAppThread, startSeq) 是通过Binder机制回掉AMS的attachApplication方法,这一过程在上一篇文章Android framework 源码分析之Activity启动流程(android 8.0)中详细分析过,如果不明白的可以查阅一下,这里不在赘述。

Step26: AMS的attachApplication 方法分析:

private final boolean attachApplicationLocked(IApplicationThread thread,
                                                  int pid, int callingUid, long startSeq) {

        ProcessRecord app;
        //...省略部分代码

        //初始化数据
        app.makeActive(thread, mProcessStats);
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.forcingToImportant = null;
        updateProcessForegroundLocked(app, false, false);
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;
        app.killed = false;
 
        //....代码

        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                //重点: 调用mStackSupervisor.attachApplicationLocked(app)) 
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        //...代码
        return true;
    }

分析:
在AMS的attachApplication中,重点看这一句mStackSupervisor.attachApplicationLocked,将启动和绑定工作交给了ActivityStackSupervisorattachApplicationLocked方法去完成。

Step27: ActivityStackSupervisor的attachApplicationLocked 方法分析:

 boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                if (!isFocusedStack(stack)) {
                    continue;
                }
                stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
                final ActivityRecord top = stack.topRunningActivityLocked();
                final int size = mTmpActivityList.size();
                for (int i = 0; i < size; i++) {
                    final ActivityRecord activity = mTmpActivityList.get(i);
                    if (activity.app == null && app.uid == activity.info.applicationInfo.uid
                            && processName.equals(activity.processName)) {
                        try {
                            //重点 ;realStartActivityLocked启动acrivity
                            if (realStartActivityLocked(activity, app,
                                    top == activity /* andResume */, true /* checkConfig */)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                    + top.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
        }
        return didSomething;
    }

分析:attachApplicationLocked方法中调用了realStartActivityLocked方法去完成启动Activity工作,至于realStartActivityLocked的工作流程请阅读上文Android framework 源码分析之Activity启动流程(android 8.0)Step14-Step18

7:总结

到此应用进程的启动流程也分析完毕,如果文中有不对的地方欢迎请大家留言指出,共同进步,稍后根据这两篇文章整理一张app启动以及activity启动流程总图以便理解记忆。顺便给点个赞谢谢祝,大家周末愉快!!!。

猜你喜欢

转载自blog.csdn.net/weixin_37639900/article/details/89959023