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, "[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创建的地方。实在想不出来,找了下度娘,才发现了真正启动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系统,源码是王道,但要深入理解系统背后的设计,还是需要从把基本的概念梳理清楚,才能更好的理解系统背后设计的逻辑。

时间: 2024-10-10 10:40:40

Android Phone进程启动过程详解的相关文章

Linux(RHEL6)启动过程详解

Linux(红帽RHEL6)启动过程详解: RHEL的一个重要和强大的方面是它是开源的,并且系统的启动过程是用户可配置的.用户可以自由的配置启动过程的许多方面,包括可以指定启动时运行的程序.同样的,系统关机时所要终止的进程也是可以进行组织和配置的,即使这个过程的自定义很少被需要. 理解系统的启动和关机过程是如何实现的不仅可以允许自定义,而且也可以更容易的处理与系统的启动或者关机相关的故障.  1.启动过程  以下是启动过程的几个基本阶段:   ① 系统加载并允许boot loader.此过程的细

solaris启动过程详解

在Sparc平台下,Solaris系统中有一个类似PC BIOS的芯片程序(EEPROM OpenBoot)负责识别分区.文 件系统和加载内核,在Solaris 2.6之后的版本中,默认的内核文件存放在/platform/`arch`/kernel/unix 位置,`arch`指令是指明系统的硬件体系,目前一般是i86pc(Intel IA32)或sun4u(Sun UntraSparc). 在Intel体系中,因为没有eeprom firmware,所以系统提供了一个模拟eeprom的引导程序

计算机启动过程详解

计算机启动过程详解打开电源启动机器几乎是电脑爱好者每天必做的事情,面对屏幕上出现的一幅幅启动画面,我们一点儿也不会感到陌生,但是,计算机在显示这些启动画面时都做了些什么工作呢?相信有的朋友还不是很清楚,本文就来介绍一下从打开电源到出现Windows的蓝天白云时,计算机到底都干了些什么事情.  首先让我们来了解一些基本概念.第一个是大家非常熟悉的BIOS(基本输入输出系统),BIOS是直接与硬件打交道的底层代码,它为操作系统提供了控制硬件设备的基本功能.BIOS包括有系统BIOS(即常说的主板BI

VxWorks启动过程详解(下)

上一节主要是从映像的分类和各种映像的大致加载流程上看VxWorks的启动过程,这一节让我们从函数级看一下VxWorks的启动过程: 1. Boot Image + Loadable Images: 下面是具体的流程图: 其中第一阶段的执行流程使用的是上图的左边的源文件中的那些函数(romInit->romStart->usrInit->sysHwinit->usrKernelinit->usrRoot);第二阶段执行流程使用的是上图中右边源文件中的那些函数(sysInit-&

VxWorks启动过程详解(上)

vxworks有三种映像: VxWorks Image的文件类型有三种 Loadable Images:由Boot-ROM引导通过网口或串口下载到RAM ROM-based Images(压缩/没有压缩):即将Image直接烧入ROM,运行时将Image拷入RAM中运行. ROM-Resident Images:Image的指令部分驻留在ROM中运行,仅将数据段部分拷入RAM. 注意这里说的三种映像都是包含真正操作系统VxWorks的映像,其中后两种可以直接启动并运行起来,但是第一种不行,它必须

cocos2dx 启动过程详解一:渲染

今天来看一下cocos2d-x的整体启动过程: cocos2d-x 在各个平台的实现代码是一样的,只要针对不同平台做相应的配置就可以了. 一.启动前奏 现在来看一下在ios平台下的相关结构: 打开源代码自带工程,你会看到一个main文件,这里main里面有一个main函数,这是程序的入口函数.在这里他回加载AppController,进入这个类,这里有ios平台华景初始化代码,但是最先执行的如下: // cocos2d application instance static AppDelegat

cocos2dx 启动过程详解二:内存管理和回调

在上一篇的第二部分中,我们有一句代码待解释的: // Draw the Scene void CCDirector::drawScene(void) { -- //tick before glClear: issue #533 if (! m_bPaused) //暂停 { m_pScheduler->update(m_fDeltaTime);   //待会会解释这里的内容 } -- } 这里是一个update函数,经常会写像this->schedule(schedule_selector(X

Fabric网络环境启动过程详解

这篇文章对fabric的网络环境启动过程进行讲解,也就是我们上节讲到的启动测试fabric网络环境时运行network_setup.sh这个文件的执行流程 fabric网络环境启动过程详解 上一节我们讲到 fabric网络环境的启动测试,主要是使用 ./network_setup.sh up 这个命令,所以fabric网络环境启动的重点就在network_setup.sh这个文件中.接下来我们就分析一下network_setup.sh这个文件network_setup.sh其中包括两个部分,一个

转-Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)

http://blog.chinaunix.net/space.php?uid=10167808&do=blog&id=26042 1)BIOS自检2)启动Grub/Lilo3)加载内核4)执行init进程5)通过/etc/inittab文件进行初始化6)登陆Linux 1)BIOS自检   a)POST(Power On Self Test),对硬件进行检测   计算机在通电后首先由BIOS进行自检,即所谓的POST(Power On Self Test),对硬件进行检测   依据BIO