首页 > 代码库 > Android Phone进程启动过程详解

Android Phone进程启动过程详解

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

RIL运行机制请参考: http://blog.csdn.net/jason_wzn/article/details/53232022

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, "!@Boot_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创建的地方。实在想不出来,找了下度娘,才发现了真正启动Phone进程的地方。

打开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应用是系统常驻进程,一旦起来后就会一直运行,不会被杀死。对于这类常驻进程,ActivityManagerService(以下简称AMS)会对其做特殊处理。在SystemServer初始化完系统的核心服务后,其会调用AMS的systemReady(Runnable r)函数:


    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
                // 正是在这里,PhoneApp被创建!
                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<ApplicationInfo> 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);
        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;

            if(userid>0 && (bbcId>0 && userid == bbcId) && app.info.bbcseinfo!=null){
                //启动进程                
                startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.bbcseinfo, app.info.bbccategory, app.info.accessInfo,
                requiredAbi, instructionSet,
                app.info.dataDir, mountKnoxPoint, entryPointArgs);
            }esle{
                ...
            }
    }

调用Process.start(),创建一个新的进程ActivityThread,Phone进程就运行在该进程当中:


    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<String> argsForZygote = new ArrayList<String>();

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

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

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    Android Phone进程启动过程详解