APP进程启动流程

QuibblerQuibbler 2020-07-11 约 52 分钟 2589 次阅读

APP进程启动流程

当用户点击桌面上的APP图标打开一个应用,这中间发生了什么?桌面通过Intent启动APP之后系统做了哪些?Android系统做了非常复杂的操作。从全局流程上简化来看,在上次分析的Zyoget进程的启动流程中,了解到通过AMS发送启动应用的请求,Zygote服务端接收到请求后,fork自己创建应用程序进程。

1、启动APP

点击桌面上的图标启动应用的时候和通过Intent启动Activity一样,接着Activity启动流程源码分析一文执行到ActivityStackSupervisor类中startSpecificActivityLocked()方法继续分析,这里会判断应用是否已经有进程,新启动的应用没有进行需要创建APP进程。

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // 该活动的应用程序已经在运行吗?
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);
        boolean knownToBeDead = false;
        if (wpc != null && wpc.hasThread()) {
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
            // 如果抛出了死对象异常,请重新启动应用程序。
            knownToBeDead = true;
        }
        // 禁止过渡,直到新活动准备就绪为止,
        // 否则在新活动的新进程可以设置其showWhenLocked标志的能力之前,键盘锁可能会出现一小段时间。
        if (getKeyguardController().isKeyguardLocked()) {
            r.notifyUnknownVisibilityLaunched();
        }
        try {
            if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
                        + r.processName);
            }
            // 发布消息以启动过程,以避免在保持ATMS锁定的情况下呼叫AMS的死锁。
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                    r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
            mService.mH.sendMessage(msg);
        } finally {
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

2、需要创建进程

如果启动的APP进程不存在,则需要先启动应用进程。这里的方法和之前源码大不相同,基本上已经很难继续跟下去。并非直接调用mService的startProcessLocked()方法,而是通过Message和Handler间接触发:

...
            // 发布消息以启动过程,以避免在保持ATMS锁定的情况下呼叫AMS的死锁。
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                    r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
            mService.mH.sendMessage(msg);
            ...

com.android.internal.util.function.pooled.PooledLambda类的obtainMessage(...)方法有非常多的重载,主要是参数个数不同:第一个传入的参数function,后面这些参数都是作为调用function的参数。

static <A, B, C, D, E, F, G> Message obtainMessage(
            HeptConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
                    ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
        synchronized (Message.sPoolSync) {
            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                    function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
                    null);
            return Message.obtain().setCallback(callback.recycleOnUse());
        }
    }

不要怀疑为什么找不到调用的acquire(...)方法,是通过static关键字静态导入的方法,

import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquire;
    ...

定义在PooledLambdaImpl的acquire(...)方法。

/**
     * 内部非类型安全工厂方法
     */
    static <E extends PooledLambda> E acquire(Pool pool, Object func,
            int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
            Object d, Object e, Object f, Object g, Object h, Object i) {
        PooledLambdaImpl r = acquire(pool);
        ...
        r.mFunc = Preconditions.checkNotNull(func);
        r.setFlags(MASK_FUNC_TYPE, LambdaType.encode(fNumArgs, fReturnType));
        r.setFlags(MASK_EXPOSED_AS, LambdaType.encode(numPlaceholders, fReturnType));
        if (ArrayUtils.size(r.mArgs) < fNumArgs) r.mArgs = new Object[fNumArgs];
        setIfInBounds(r.mArgs, 0, a);
        setIfInBounds(r.mArgs, 1, b);
        setIfInBounds(r.mArgs, 2, c);
        setIfInBounds(r.mArgs, 3, d);
        setIfInBounds(r.mArgs, 4, e);
        setIfInBounds(r.mArgs, 5, f);
        setIfInBounds(r.mArgs, 6, g);
        setIfInBounds(r.mArgs, 7, h);
        setIfInBounds(r.mArgs, 8, i);
        return (E) r;
    }

返回的PooledRunnable接口类型:

public interface PooledRunnable extends PooledLambda, Runnable, ThrowingRunnable {
        /** @inheritDoc */
        PooledRunnable recycleOnUse();
    }

返回Runnable对象,设置给Message,这个Runnable在Message中的定义说明:callback Runnable that will execute when the message is handled。当Message被Handler处理的时候会执行。

回到ActivityStackSupervisor中的startSpecificActivityLocked()方法中,之后向mService的mH发送上面构造好的Message,mService是ActivityTaskManagerService,其中的成员变量mH是静态内部类:

final class H extends Handler {
        static final int REPORT_TIME_TRACKER_MSG = 1;
        static final int FIRST_ACTIVITY_STACK_MSG = 100;
        static final int FIRST_SUPERVISOR_STACK_MSG = 200;
        H(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case REPORT_TIME_TRACKER_MSG: {
                    AppTimeTracker tracker = (AppTimeTracker) msg.obj;
                    tracker.deliverResult(mContext);
                } break;
            }
        }
    }

还没有摸清楚怎么构造这个Runnable的,但是可以确定是执行传入的function,也就是抽象类ActivityManagerInternal的startProcess()抽象方法。ActivityManagerInternal类的实现在哪里呢?

错综复杂的Android源码,想找到一个抽象类的实现在哪里是非常的困难。千万不要自己摸索,太浪费时间,直接搜索博客资料,立马豁然开朗。



3、AMS发起创建进程请求

        ActivityManagerInternal类的实现就是熟悉的AMS:ActivityManagerService,关于AMS的启动见AMS服务的启动一文。

public final class LocalService extends ActivityManagerInternal {
        ...
    }

        内部LocalService类继承ActivityManagerInternal类并且实现所有的方法:  

@Override
        public void startProcess(String processName, ApplicationInfo info,
                boolean knownToBeDead, String hostingType, ComponentName hostingName) {
            try {
                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                            + processName);
                }
                synchronized (ActivityManagerService.this) {
                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                            new HostingRecord(hostingType, hostingName),
                            false /* allowWhileBooting */, false /* isolated */,
                            true /* keepIfLarge */);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
        }

        startProcess()方法实现中调用了startProcessLocked(...)方法

final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

        mProcessList是ProcessList类型对象,调用它的startProcessLocked(...)方法(注意该方法也有很多重载)

boolean startProcessLocked(HostingRecord hostingRecord,
            String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        app.pendingStart = true;
        app.killedByAm = false;
        app.removed = false;
        app.killed = false;
        ...
        if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
            ...
        } else {
                final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                        entryPoint, app,
                        uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
                        invokeWith, startTime);
                ...           
        }
    }

        调用startProcess(...)方法:

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        try {
            ...
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, app.info.packageName,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
            ...
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

4、Zygote机制请求

        最后调用Process的start(...)方法,进入新的一个阶段:

public static ProcessStartResult start(@NonNull final String processClass,
                                           @Nullable final String niceName,
                                           int uid, int gid, @Nullable int[] gids,
                                           int runtimeFlags,
                                           int mountExternal,
                                           int targetSdkVersion,
                                           @Nullable String seInfo,
                                           @NonNull String abi,
                                           @Nullable String instructionSet,
                                           @Nullable String appDataDir,
                                           @Nullable String invokeWith,
                                           @Nullable String packageName,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ true, zygoteArgs);
    }

ZYGOTE_PROCESS是定义在Process类中ZygoteProcess类型的的成员变量:

/**
     * State associated with the zygote process.
     * @hide
     */
    public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();

调用ZygoteProcess的start(...)方法:

/**
     * Start a new process.
     */
    public final Process.ProcessStartResult start(...) {
        ...
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, useUsapPool, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            ...
        }
    }

调用startViaZygote(...)方法:

/**
     * Starts a new process via the zygote mechanism.
     */
    private Process.ProcessStartResult startViaZygote(...) throws ZygoteStartFailedEx {
        ...
        synchronized(mLock) {
            // 如果应用程序不使用系统图形驱动程序,则不能使用USAP池。
            // 如果要求该驱动程序,请使用Zygote应用程序启动路径。
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              useUsapPool,
                                              argsForZygote);
        }
    }

参数中调用了openZygoteSocketIfNeeded(abi)方法:

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        try {
            attemptConnectionToPrimaryZygote();
            if (primaryZygoteState.matches(abi)) {
                return primaryZygoteState;
            }
            if (mZygoteSecondarySocketAddress != null) {
                // The primary zygote didn't match. Try the secondary.
                attemptConnectionToSecondaryZygote();
                if (secondaryZygoteState.matches(abi)) {
                    return secondaryZygoteState;
                }
            }
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
        }
        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }

原来的代码是一个方法,现在进行了拆分:该方法中调用了两个方法attemptConnectionToPrimaryZygote()和attemptConnectionToSecondaryZygote(),都是尝试连接Zygote主模式/辅模式。

回到主流程,继续调用zygoteSendArgsAndGetResult(...)方法,原来的代码是一个方法,现在进行了拆分:

private Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args)
            throws ZygoteStartFailedEx {
        ...
        return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
    }

继续调用attemptUsapSendArgsAndGetResult(...)或者attemptZygoteSendArgsAndGetResult(...)方法

private Process.ProcessStartResult attemptUsapSendArgsAndGetResult(
            ZygoteState zygoteState, String msgStr)
            throws ZygoteStartFailedEx, IOException {
            ...
            Process.ProcessStartResult result = new Process.ProcessStartResult();
            ...
            if (result.pid >= 0) {
                return result;
            } else {
                throw new ZygoteStartFailedEx("USAP specialization failed");
            }
    }

获取Zygote中创建的结果ProcessStartResult。

5、Zygote接收并创建进程

接着上次Zygote进程的启动,看看Zygote是如何处理AMS的请求并创建进程的。回到ZygoteInit的main方法

public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        ...
        try {
            ...
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
        } finally {
        }
        ...
    }

ZygoteServer类中的runSelectLoop()方法等待AMS请求创建新的APP进程,简化之后如下:

Runnable runSelectLoop(String abiList) {
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        ...
        while (true) {
            ...
                    try {
                        ZygoteConnection connection = peers.get(pollIndex);
                        final Runnable command = connection.processOneCommand(this);
                        ...
                    }
                } 
    }

调用ZygoteConnection的processOneCommand()方法:处理AMS的请求数据,fork当前进程创建应用程序进程。

Runnable processOneCommand(ZygoteServer zygoteServer) {
        ...
        try {
            args = Zygote.readArgumentList(mSocketReader);
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }
        ...
        //在这里创建APP进程
        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
        try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();
                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.mStartChildZygote);
            } else {
                // 在父进程中, pid <0表示失败,将在handleParentProc中进行处理。
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;
            }
        }
    }

其中返回了handleChildProc(),当pid为0的时候,代码运行在当前新创建的进程,调用该方法来处理APP:

private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        /**
         * 到我们到达这里时,本机代码已关闭两个实际的Zygote套接字连接,
         * 并在其位置替换了/ dev / null。 LocalSocket对象仍然需要正确关闭。
         */
        closeSocket();
        ...
        if (parsedArgs.mInvokeWith != null) {
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.mRemainingArgs);
            // Should not get here.
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
    }

方法结尾处调用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");
        RuntimeInit.redirectLogStreams();
        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

该方法主要做了两件事情:

①nativeZygoteInit():创建应用程序的Binder线程池。

private static final native void nativeZygoteInit();

②RuntimeInit.applicationInit(...):反射查找调用main()方法。

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        final Arguments args = new Arguments(argv);
        ...
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

找到main()方法调用并返回,之前的源码是封装成异常直接throw回到Zygote的mian()方法中(为了清除堆栈帧,现在不这样做了)

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        ...
        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }

回到ZygoteInit的main方法,这时候已经在APP进程并非原来的Zygote进程,将返回的Runnable对象调用并执行:

@UnsupportedAppUsage
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        ...
        // 我们在子进程中,已经退出选择循环。 继续执行命令。
        if (caller != null) {
            caller.run();
        }
    }

MethodAndArgsCaller是定义在RuntimeInit中的静态内部类:

/**
     * Helper class which holds a method and arguments and can call them. This is used as part of
     * a trampoline to get rid of the initial process setup stack frames.
     */
    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;
        /** argument array */
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }
        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

其中调用mMethod的invoke()反射方法,其实就是ActivityThread的main()静态方法,APP进程进入了ActivityThread的main方法开始执行,由ActivityThread管理APP进程。

相关博客:

        Android App 启动流程梳理(基于 Android 10)

        App的启动流程

        App启动流程:启动App进程

        理解Android进程创建流程


相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w