之前解决一个开机搜网慢的问题时,发现由于Phone进程起来以后才会主动连接RILD,因而在一定程度上Phone进程启动的时间会影响网络状态注册的快慢。适当的将Phone进程提前,可以将网络注册时间提前一点,让状态栏中信号显示的时间提前。那么,Android中作为系统的核心进程之一,Phone进程是如何启动的了?

本文参考代码为Android NN7.0, RIL运行机制请参考: Android RIL概述

Telephony最开始创建的是PhoneFactory对象,直接搜索源码,可以看到在PhoneGlobals.java创建时,会调用PhoneFactory对Telephony进行初始化操作:

    /**     * Global state for the telephony subsystem when running in the primary     * phone process.     */    public class PhoneGlobals extends ContextWrapper {        public void onCreate() {            Log.v(LOG_TAG, "[email protected]_SVC : PhoneApp OnCrate");            // CallManager为空            if (mCM == null) {                // Initialize the telephony framework                PhoneFactory.makeDefaultPhones(this);                // 创建CallManager实例                mCM = CallManager.getInstance();                for (Phone phone : PhoneFactory.getPhones()) {                    mCM.registerPhone(phone);                }                ....            }    }

那么,PhoneGlobals又是在哪里创建的了?再次搜索代码,可以看到在同一文件目录下,有一个PhoneApp.java文件:

       @Override        public void onCreate() {            Log.d("PhoneApp", "onCreate");            if (UserHandle.myUserId() == 0) {                // 创建PhoneGlobals实例                mPhoneGlobals = new PhoneGlobals(this);                mPhoneGlobals.onCreate();                mTelephonyGlobals = new TelephonyGlobals(this);                mTelephonyGlobals.onCreate();            } else {                Log.d("PhoneApp", "Phone app is created as userid not 0, there's no PhoneApp() Instance");            }            ....        }

那么,PhoneApp这个类又是什么时候创建的?我们知道,每一个Android应用都有一个Application与之对应,它是在应用启动过程中创建的,但是在这里搜索所有的源码,也无法看到PhoneApp创建的地方。联想到应用的启动过程,APP的启动的入口是ActivityThread,那么对于任何PhoneApp这样的系统应用来说,启动的入口也应该是ActivityThread。不妨继续看看代码。

打开Phone进程所在的源码路径: /android/applications/sources/services/Telephony/,查看应用对应的AndroidManefest.xml文件:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"            xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"            package="com.android.phone"            android:versionCode="1"            android:versionName="1.0.0"            coreApp="true"            android:sharedUserId="android.uid.phone"            android:sharedUserLabel="@string/phoneAppLabel" >            .....        <application android:name="PhoneApp"            android:persistent="true"            android:hardwareAccelerated="true"            android:label="@string/phoneAppLabel"            android:icon="@mipmap/ic_launcher_phone"            android:allowBackup="false"            android:supportsRtl="true"            android:usesCleartextTraffic="true"            android:defaultToDeviceProtectedStorage="true"            android:directBootAware="true">            ....        application>    manifest>

application标签下面,可以看到android:persistent="true"这个属性值,看一看官方的文档怎么解释的:

android:persistent

Whether or not the application should remain running at all times — “true” if it should, and “false” if not. The default value is “false”. Applications should not normally set this flag; persistence mode is intended only for certain system applications.

由此可见,Phone应用是系统常驻进程,一旦起来后就会一直运行,不会被杀死(除非Phone进程自己发生了的运行时错误而崩溃)。对于这类常驻进程,ActivityManagerService(以下简称AMS)会在初始化完成后,主动启动。在SystemServer初始化完系统的核心服务后,会调用AMS的systemReady(Runnable r)函数。

ActivityManagerService.java

    public void systemReady(final Runnable goingCallback) {        synchronized (this) {                 // Only start up encryption-aware persistent apps; once user is                // unlocked we'll come back around and start unaware apps                // 正是在这里,phone进程被创建                startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);                // Start up initial activity.                mBooting = true;                // Enable home activity for system user, so that the system can always boot                if (UserManager.isSplitSystemUser()) {                    ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);                    try {                        AppGlobals.getPackageManager().setComponentEnabledSetting(cName,                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,                                UserHandle.USER_SYSTEM);                    } catch (RemoteException e) {                        throw e.rethrowAsRuntimeException();                    }                }                startHomeActivityLocked(currentUserId, "systemReady");        }    }

启动所有PackageManager.MATCH_DIRECT_BOOT_AWARE标志为true的应用:

    private void startPersistentApps(int matchFlags) {        synchronized (this) {            try {                //获取系统所有常驻应用程序信息                final List apps = AppGlobals.getPackageManager()                        .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();                for (ApplicationInfo app : apps) {                    if (!"android".equals(app.packageName)) {                        //加载应用                        addAppLocked(app, false, null /* ABI override */);                    }                }            } catch (RemoteException ex) {            }        }    }    //添加应用程序进程到LRU列表中,并创建进程    final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,            String abiOverride) {        ProcessRecord app;        if (!isolated) {            app = getProcessRecordLocked(info.processName, info.uid, true);        } else {            app = null;        }        // 没有进程记录,因此创建一个进程记录        if (app == null) {            app = newProcessRecordLocked(info, null, isolated, 0);            updateLruProcessLocked(app, false, null);            updateOomAdjLocked();        }        ....        if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {            app.persistent = true;            app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;        }        // Start the process.  It will either succeed and return a result containing        // the PID of the new process, or else throw a RuntimeException.        boolean isActivityProcess = (entryPoint == null);        // 进程入口为ActivityThread        if (entryPoint == null) entryPoint = "android.app.ActivityThread";                //启动应用进程        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {            mPersistentStartingProcesses.add(app);            startProcessLocked(app, "added application", app.processName, abiOverride,                    null /* entryPoint */, null /* entryPointArgs */);        }        return app;    }

准备创建应用进程:

    private final void startProcessLocked(ProcessRecord app, String hostingType,            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {            Process.ProcessStartResult startResult = null;            ....            startResult = Process.start(entryPoint,            app.processName, uid, uid, gids, debugFlags, mountExternal,            app.info.targetSdkVersion, aasaSeInfo != null ? new String(aasaSeInfo) : app.info.seinfo, //AASA--4 : changed orginal : only "app.info.seinfo"            app.info.category, app.info.accessInfo,            requiredAbi, instructionSet,            app.info.dataDir, mountKnoxPoint, entryPointArgs);            ....    }

Process.java

调用Process.start(),创建一个新的进程, Telephony服务以及RIL相关代码都运行在此进程中:

    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,                                  int category,                                  int accessInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  boolean mountKnoxPoint,                                  String[] zygoteArgs) {        try {            return startViaZygote(processClass, niceName, uid, gid, gids,                    debugFlags, mountExternal, targetSdkVersion, seInfo, category, accessInfo,                    abi, instructionSet, appDataDir, mountKnoxPoint, zygoteArgs);        } catch (ZygoteStartFailedEx ex) {            Log.e(LOG_TAG,                    "Starting VM process through Zygote failed");            throw new RuntimeException(                    "Starting VM process through Zygote failed", ex);        }    }

发送消息到zygote服务进程的socket端口,请求创建新的进程:

 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,                                  int category,                                  int accessInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  boolean mountKnoxPoint,                                  String[] extraArgs)                                  throws ZygoteStartFailedEx {        synchronized(Process.class) {            ArrayList argsForZygote = new ArrayList();            // --runtime-args, --setuid=, --setgid=,            // and --setgroups= must go first            argsForZygote.add("--runtime-args");            argsForZygote.add("--setuid=" + uid);            argsForZygote.add("--setgid=" + gid);            ....            if (appDataDir != null) {                argsForZygote.add("--app-data-dir=" + appDataDir);            }            ....            argsForZygote.add(processClass);            if (extraArgs != null) {                for (String arg : extraArgs) {                    argsForZygote.add(arg);                }            }            //发送消息到zygote的socket端口,请求创建新的进程            if (Zygote.isEnhancedZygoteASLREnabled) {                ....                return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);                // End of isEnhancedZygoteASLREnabled case            } else {                // Original case                return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);            }        }    }

ZygoteConnection.java

zygote进程接收到AMS的请求后,由ZygoteConnection负责处理请求:

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {        String args[];        Arguments parsedArgs = null;        FileDescriptor[] descriptors;        try {            // 从socket中读取参数            args = readArgumentList();            descriptors = mSocket.getAncillaryFileDescriptors();        } catch (IOException ex) {            Log.w(TAG, "IOException on command socket " + ex.getMessage());            closeSocket();            return true;        }        if (args == null) {            // EOF reached.            closeSocket();            return true;        }        int pid = -1;        FileDescriptor childPipeFd = null;        FileDescriptor serverPipeFd = null;        ...        try {            parsedArgs = new Arguments(args);            //Zygote调用本地方法创建进程            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.category, parsedArgs.accessInfo,                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,                    parsedArgs.appDataDir, parsedArgs.mountKnoxPoint);        } catch (ErrnoException ex) {            logAndPrintError(newStderr, "Exception creating pipe", ex);        } catch (IllegalArgumentException ex) {            logAndPrintError(newStderr, "Invalid zygote arguments", ex);        } catch (ZygoteSecurityException ex) {            logAndPrintError(newStderr,                    "Zygote security policy prevents request: ", ex);        }        try {            if (pid == 0) {                // in child                IoUtils.closeQuietly(serverPipeFd);                serverPipeFd = null;                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);                // should never get here, the child is expected to either                // throw ZygoteInit.MethodAndArgsCaller or exec().                return true;            } else {                // in parent...pid of < 0 means failure                IoUtils.closeQuietly(childPipeFd);                childPipeFd = null;                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);            }        } finally {            IoUtils.closeQuietly(childPipeFd);            IoUtils.closeQuietly(serverPipeFd);        }    }

ZygoteInit.java

至此phone进程已经创建完成了,但实际上PhoneApp的代码还没有加载。继续看,在启动的进程里,调用ZygoteInit.zygoteInit来加载phoneApp的代码:

private void handleChildProc(Arguments parsedArgs,            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)            throws Zygote.MethodAndArgsCaller {        /**         * 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.         */        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);                }                newStderr = System.err;            } 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);        // 这里没有指定invokewith参数        if (parsedArgs.invokeWith != null) {            WrapperInit.execApplication(parsedArgs.invokeWith,                    parsedArgs.niceName, parsedArgs.targetSdkVersion,                    VMRuntime.getCurrentInstructionSet(),                    pipeFd, parsedArgs.remainingArgs);        } else {            // 这里remaingArgs的第一参数是android.app.ActivityThread, 就是之前的entrypoint            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,                    parsedArgs.remainingArgs, null /* classLoader */);        }    }

RuntimeInit.java

通过RuntimeInit来加载phone APP的代码, zygoteInit函数主要做三件事:

  • 做一些通用的初始化,比如设置虚拟机中线程的exception handler;设置默认时区;
  • 完成VM本地的初始化操作;
  • 加载APP代码,也就是调用ActivityThread.main函数来加载整个phone APP;
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");        redirectLogStreams();        commonInit();        nativeZygoteInit();        // 初始化应用代码        applicationInit(targetSdkVersion, argv, classLoader);    }

函数applicationInit通过方法invokeStaticMain反射调用ActivityThread.main:

    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)                throws Zygote.MethodAndArgsCaller {            // If the application calls System.exit(), terminate the process            // immediately without running any shutdown hooks.  It is not possible to            // shutdown an Android application gracefully.  Among other things, the            // Android runtime shutdown hooks close the Binder driver, which can cause            // leftover running threads to crash before the process actually exits.            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);            final Arguments args;            try {                args = new Arguments(argv);            } catch (IllegalArgumentException ex) {                Slog.e(TAG, ex.getMessage());                // let the process exit                return;            }            // Remaining arguments are passed to the start class's static main            invokeStaticMain(args.startClass, args.startArgs, classLoader);        }

invokeStaticMain通过抛出一个MethodAndArgsCaller的异常,被ZygoteInit.main方法捕获后,调用MethodAndArgsCaller.run,至此就调用了ActivityThread.main方法了,还真是有点绕。

| 有关zygote进程可以参考http://sniffer.site/2017/05/27/Zygote%E8%BF%9B%E7%A8%8B%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)                throws Zygote.MethodAndArgsCaller {            Class<?> cl;            try {                cl = Class.forName(className, true, classLoader);            } catch (ClassNotFoundException ex) {                throw new RuntimeException(                        "Missing class when invoking static main " + className,                        ex);            }            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);            }            /*            * 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.            */            throw new Zygote.MethodAndArgsCaller(m, argv);        }

MethodAndArgsCaller异常的作用是清除父进程中的一些调用堆栈,这样子进程就从ActivityThread.main开始了自己的堆栈调用。

        public static class MethodAndArgsCaller extends Exception            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);                }            }    }

ActivityThread.java

到这里,ActivityThread.main会启动一个主线程,接着创建一个ActivityThread用于Phone APP与AMS进行交互。最重要的是,接着在thread.attach(false);这个函数里,ActivityThread会去创建Phone进程入口类PhoneApp。后续就是Phone整个框架代码的加载与初始化了。

    public static void main(String[] args) {        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");        SamplingProfilerIntegration.start();        // 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("");        // 启动主线程Looper        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        thread.attach(false);        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");    }

这样Phone进程就创建启动完成了。整个流程看下来,研究Android系统,源码是王道,但要深入理解系统背后的设计,还是需要从把基本的概念梳理清楚,才能更好的理解系统背后设计的逻辑。

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  3. Android(安卓)SurfaceView入门学习
  4. android应用创建子进程的方法探究
  5. [置顶] Android(安卓)Binder跨进程与非跨进程的传输异同源码分析
  6. android xml解析生成探讨
  7. 一个android文本比对APP的实现(三)-设计模式在文件选择模块中的运用
  8. Android(安卓)Training - 管理应用的内存
  9. Android之fragment点击切换和滑动切换结合

随机推荐

  1. Android应用程序进程启动过程的源代码分
  2. Android(安卓)事件捕捉和处理流程分析
  3. android support v4、v7、v13的区别及作
  4. 【安卓开发】Facebook工程师是如何改进他
  5. 接入新浪、腾讯微博和人人网的Android客
  6. Google Android内核编译教程
  7. Android(安卓)Vitamio 直播视频播放功能
  8. Eclipse同时附加javadoc和android文档
  9. [置顶] Android的Activity屏幕切换动画(
  10. 【Android】android中Invalidate和postIn