AMS分析「 AMS启动流程 」

  ActivityManagerService服务是Android系统核心服务,负责Android管理系统Activity,Service,ContentProvider和BroadcastReceiver 四大组件,同时还负责Android系统中的进程管理。由此可见ActivityManagerService服务对于Android系统来讲非常重要,我们就从以下几个方面来了解下AMS服务。

  1. AMS服务的启动和初始化过程
  2. AMS如何启动和管理Activity
  3. AMS如何启动和管理Service
  4. AMS如何管理BroadCastReceiver
  5. AMS如何管理ContentProvider
    此篇文章就来总结下Ams服务的启动和初始化过程。

ActivityManagerService的启动和初始化过程

系统进程运行环境的初始化

在分析AMS服务之前我们先来了解下什么是Context.
Context是什么?
Context是一个抽象类,其通用实现在ContextImpl类中。是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关的类,其主要功能如下:

• 启动Activity
• 启动和停止Service
• 发送广播消息(Intent)
• 注册广播消息(Intent)接收者
• 可以访问APK中各种资源(如Resources和AssetManager等)
• 可以访问Package的相关信息
• APK的各种权限管理

对你的应用程序而言,Context就是一个无所不知的大管家,大家需要什么,直接问它就可以了。


Context实现

Context的类关系图可知,ContextImpl最终实现了Context相关方法,ContextWrapper只是一个代理类,Activity,Service,Application都是实现了ContextWrapper,所以在Activity,Service和Application中调用的context的相关方法,最终都有ContextImpl来实现。而ContextImpl最终是应用程序的大管家,管理着操作本应用的相关方法。

 Android系统中的进程分为两种,应用进程和系统进程。而ActivityThread就是应用进程的主线程,Android系统的应用进程启动后首先运行ActivityThread的main函数,ActivityThread和AMS进行通信,调度和执行应用进程的四大组件。

 SystemServer是Android的系统进程,由于系统进程中也有一些Activity和系统资源,为了保证调用方式统一,系统进程也需要ActivityThread和Context等Android运行环境。所以SystemServer也是一个特殊的应用进行。

对Android而言系统进程而言,SysrtemServer也是一个特别的应用程序,也有自己的Context上下文环境,而系统的Context又是怎么创建的呢?

它是SystemServer启动之后,在createSystemContext方法中创建的。

private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        ……
    }

第一步ActivityThread.systemMain方法,该方法生成了一个ActivityThread对象。

public static ActivityThread systemMain() {
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }

首先创建了一个ActivityThread对象,然后调用attach方法。
ActivityThread的构造方法很简单就是创建了一个ResourcesManager对象,用于管理应用程序中的资源文件
那就接着看ActivityThread的Attach方法。

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
    ……
        }else{
        //修改系统进程的名称为system_process
    android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                //创建一个该进程相关的context对象
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
 
}

 attach方法传进来的参数为true,代表该进程为系统进程,所以直接看else中的方法实现。
 首先调用setAppName将系统应用的名称改为system_process,调试的时候我们可以看到系统的进程名称为system_process.
 然后创建了一个Instrumentation类,该类是一个工具类,ActivityThread接收到AMS的指令创建和调度交互都由它来执行。
 然后调用createAppContext来创建一个系统的ContextImpl的大管家,传入的关键参数为系统进程的apk相关信息。后面再分析getSystemContext方法,然后创建了一个android,app.application,并调用了它的onCreate方法。
getSystemContext方法
systemContext最终由ContextImpl.createSystemContext方法来创建。

static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread,
                packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetricsLocked());
        return context;
    }

首先创建了一个LoadedApk对象,然后根据LoadedApk对象创建了一个ContextImpl对象。
LoadedApk代表一个加载到系统中的APK。 其中保存了apk的基本信息

LoadedApk(ActivityThread activityThread) {
        mActivityThread = activityThread;
        mApplicationInfo = new ApplicationInfo();
        mApplicationInfo.packageName = "android";
        mPackageName = "android";
        mAppDir = null;
        mResDir = null;
        mSplitAppDirs = null;
        mSplitResDirs = null;
        mOverlayDirs = null;
        mSharedLibraries = null;
        mDataDir = null;
        mDataDirFile = null;
        mLibDir = null;
        mBaseClassLoader = null;
        mSecurityViolation = false;
        mIncludeCode = true;
        mRegisterPackage = false;
        mClassLoader = ClassLoader.getSystemClassLoader();
        mResources = Resources.getSystem();
    }

LoadedAPK的这个构造方法只有系统进程创建的时候可以调用。它代表一个系统进程的apk,它里面存储着资源文件的位置,jni包的位置等信息,包名为android。其实代表的就是就是framework-res.apk。该apk仅供systemServer使用。

private ContextImpl(ContextImpl container, ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
            Display display, Configuration overrideConfiguration, int createDisplayWithId) {
        mOuterContext = this;
        //framework-res.apk的主进程为当前的ActivityThread
        mMainThread = mainThread;
        mActivityToken = activityToken;
        mRestricted = restricted;
 
        if (user == null) {
            user = Process.myUserHandle();
        }
        mUser = user;
        //packageinfo的信息
        mPackageInfo = packageInfo;
        //初始化资源管理器
        mResourcesManager = ResourcesManager.getInstance();
 
      ……
ResourcesManager.getInstance().getAdjustedDisplay(displayId, mDisplayAdjustments);
 
        Resources resources = packageInfo.getResources(mainThread);
        if (resources != null) {
            if (displayId != Display.DEFAULT_DISPLAY
                    || overrideConfiguration != null
                    || (compatInfo != null && compatInfo.applicationScale
                            != resources.getCompatibilityInfo().applicationScale)) {
                resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
                        packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
                        packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
                        overrideConfiguration, compatInfo);
            }
        }
        mResources = resources;
……
        //初始化系统的contentResolver
        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
    }

 调用ContextImpl的构造方法生成了一个ContextImpl。该构造方法主要就是初始化了ContextImpl中的一些信息,如ResourManager等。同时将刚才创建的LoadAPK的package信息保存到的Context中,最终生成了一个和系统进程相关的Context。因为它保存了系统相关的信息

 调用systemMain函数结束后,首先生成了一个ActivityThread对象,它代表应用进程的主线程。得到一个Context对象,它背后所指向的Application环境与framework-res.apk有关。

 这两样东西就构成了Android程序的运行环境。我们自己写的apk的代码最终在ActivityThread线程上运行,通过Context应用程序的大管家,可以调用进程所用到的资源和方法。

 为什么要为系统进程设置应用的运行环境呢,因为系统进程中包含了一个framewrok-res.apk的应用进程,这个apk也需要一个运行环境。

 在SystemServer进程中也创建了一个Android运行环境,说明SystemServer系统进程也被看做一个特殊的应用程序。因为系统进程中也会有Activity界面和资源,所以也为他创建了一个运行环境,这样做它就可以和普通应用进程一样使用统一的接口和系统交互了。

了解了系统Context的创建步骤及系统运行环境的概念,我们就一步一步的来分析AMS启动和初始化的过程,首先分析启动AMS服务。
AMS服务的启动过程和其他系统服务的启动过程一样,也是在SystemServer服务中启动起来的。首先来看SystemServer中关于ActivityManagerService的一些相关的方法。

AMS服务的启动过程

private void startBootstrapServices() {
        // Activity manager runs the show.
     mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
 
 
     mActivityManagerService.setSystemProcess();
……
     mActivityManagerService.installSystemProviders();
 
……
     mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                Slog.i(TAG, "Making services ready");
                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
 
                try {
                    mActivityManagerService.startObservingNativeCrashes();
                } catch (Throwable e) {
                    reportWtf("observing native crashes", e);
                }

上面的的几个方法就是SystemServer中关于AMS启动时的几个关键方法,主要分为4个步骤

1:创建AMS对象,并启动服务
2:将AMS所在的系统进程,添加到进程管理中去
3:为系统进程安装ContentProvider对象
4:在systemReady方法中做善后操作

一个一个的来看先这些方法的作用,这些方法就是AMS的启动和初始化过程。

启动ActivityManagerService的方法

mActivityManagerService = mSystemServiceManager.startService(
          ActivityManagerService.Lifecycle.class).getService();

AMS服务同样是通过SystemServiceManager来启动的。那我们首先来看ActivityManagerService.Lifecycle的构造方法,然后在来看它的Start函数。
Lifecycle的构造方法中很简单就是构造一个AMS的对象

mService = new ActivityManagerService(context);

创建AMS对象的时候需要传递一个Context作为参数,那这个mSystemContext是就是上面创建的系统Context。
接着看AMS的构造方法。

public ActivityManagerService(Context systemContext) {
//系统的context        
mContext = systemContext;
    //获得系统的ActivityThread
        mSystemThread = ActivityThread.currentActivityThread();
    //创建一个HandlerThread用来处理AMS接收的命令
        mHandlerThread = new ServiceThread(TAG,
                android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
        mHandlerThread.start();
        mHandler = new MainHandler(mHandlerThread.getLooper());
        mUiHandler = new UiHandler();
    //初始化广播的队列
        mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", BROADCAST_FG_TIMEOUT, false);
        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", BROADCAST_BG_TIMEOUT, true);
        mBroadcastQueues[0] = mFgBroadcastQueue;
        mBroadcastQueues[1] = mBgBroadcastQueue;
    //初始化Service相关的容器
        mServices = new ActiveServices(this);
    //初始化Provider相关的Map,里面保存了注册的ContentProvider
        mProviderMap = new ProviderMap(this);
 
        //初始化并创建data/system/目录
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        systemDir.mkdirs();
    //初始化电量统计服务相关的信息
        mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
        mBatteryStatsService.getActiveStatistics().readLocked();
        mBatteryStatsService.scheduleWriteToDisk();
        mOnBattery = DEBUG_POWER ? true
                : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
        mBatteryStatsService.getActiveStatistics().setCallback(this);
    //初始化系统统计服务,用于统计系统的运行信息
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
 
        mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
 
        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
 
        //创建系统的第一个user,userID为0,该用户具有管理员权限
        mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
        mUserLru.add(UserHandle.USER_OWNER);
        updateStartedUserArrayLocked();
    //获取opengle的版本
        GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
            ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
        //初始化字体语言等配置信息
        mConfiguration.setToDefaults();
        mConfiguration.setLocale(Locale.getDefault());
 
     ……;
        mRecentTasks = new RecentTasks(this);
    //初始化StackSupervisor,该类是Activity启动和调度的核心类
        mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);
        mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);

从代码中可以看出,AMS的构造方法主要是在做一些初始化的先关操作。先保存了自己的运行环境的Context和ActivityThread。AMS负责调度四大组件,所以会初始化broadcast,service和contentProvider相关的变量,接着初始化了电量统计服务,创建了系统的第一个用户,初始化了基本的配置信息,还创建了Activity调度的核心类,因为Activity调度比较复杂,Activity相关的信息初始化会在ActivityStackSupervisor中。

AMS的start方法。

    private void start() {
        mProcessCpuThread.start();
        mBatteryStatsService.publish(mContext);
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
    }

AMS的start方法很简单,只是启动了几个服务,并把AMS服务自己保存到localService中供程序内部调用。

AMS的构造方法和start方法中做了AMS服务一些变量的初始化和相关服务的初始化。接着看下一个重要的方法setSystemProcess

ActivityManagerService的setSystemProcess方法

public void setSystemProcess() {
        try {
    //将AMS注册到ServiceManager中
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
    //注册其他服务到ServiceMananger中
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
    //注册权限服务到ServiceMananger中
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));
    //从PMS中查询包名为android的application,即framework-res的Application信息
            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS);
        //将application信息配置到开始创建的activityThread中
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
 
            synchronized (this) {
        //创建了一个ProcessRecord对象,该对象中保存着系统ongoing服务的进程信息
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.persistent = true;
                app.pid = MY_PID;
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                synchronized (mPidsSelfLocked) {
        然后将系统进程的processRecord对象也添加到mPidsSelfLocked集合中,和普通应用的进程一样,接收AMS的管理调度
                    mPidsSelfLocked.put(app.pid, app);
                }
        //更细进程管理的调度信息
                updateLruProcessLocked(app, false, null);
                updateOomAdjLocked();
            }

 在setSystemProcess方法中,首先将自己AMS服务注册到了ServiceManager中,然后又注册了权限服务等其他的系统服务。通过先前创建的Context,得到PMS服务,检索framework-res的Application信息,然后将它配置到系统的ActivityThread中。
为了能让AMS同样可以管理调度系统进程,也创建了一个关于系统进程的ProcessRecord对象,ProcessRecord对象保存一个进程的相关信息。然后将它保存到mPidsSelfLocked集合中方便管理。
 但是AMS具体是如何将检索到的framework-res的application信息,配置到ActivityThread中的,需要继续分析ActivityThread的installSystemApplicationInfo方法。
接着看installSystemApplicationInfo方法

public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        synchronized (this) {
            getSystemContext().installSystemApplicationInfo(info, classLoader);
        }
    }

这个方法中最终调用上面创建的SystemContext的installSystemApplication方法,那就接着看ConxtextImpl的installSystemApplication方法。

void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        mPackageInfo.installSystemApplicationInfo(info, classLoader);
    }

它有最终调用了mPackageInfo的installSystemApplication方法,mPackageInfo就是在创建Context对象的时候传进来的LoadedApk,里面保存了一个应用程序的基本信息。

void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        assert info.packageName.equals("android");
        mApplicationInfo = info;
        mClassLoader = classLoader;
    }

 将framework-res.apk的application信息保存到了mApplication变量中。
 我们返回去看下第一次创建LoadedApk的时候,使用了一个参数的构造方法,该构造方法中mApplication变量是直接new了一个ApplicationInfo的对象,该applicationInfo并没有指向任何一个应用,为什么开始的时候不直接指定,反而到现在再来重新做一次呢?
 这个是因为创建系统进程的context的时候AMS和PMS都还没有起来,那时候没有办法指定它的application,现在AMS,PMS都起来之后再来赋值就可以了。

 setSystemProcess做了些什么工作呢?顾名思义,主要就是设置系统集成的一些信息,在这里设置了系统进程的Application信息,创建了系统进程的ProcessRecord对象将其保存在进程集合中,方便AMS管理调度。

ActivityManagerService的installSystemProvider方法

 Android系统中有很多配置信息都需要保存,这些信息是保存在SettingsProvider中,而这个SettingsProvider也是运行在SystemServer进程中的,由于SystemServer进程依赖SettingsProvider,放在一个进程中可以减少进程间通信的效率损失。

下面就来分析下如何将SettingsProvider.apk也加载到SystemServer进程中。

public final void installSystemProviders() {
        List<ProviderInfo> providers;
        synchronized (this) {
            //找到名称为”System”的进程,就是上一步创建的processRecord对象
            ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
            //找到所有和system进程相关的ContentProvider
            providers = generateApplicationProvidersLocked(app);
            if (providers != null) {
                for (int i=providers.size()-1; i>=0; i--) {
                    ProviderInfo pi = (ProviderInfo)providers.get(i);
                    //再次确认进程为system的provider,把不是该进程provider移除
                    if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
                        Slog.w(TAG, "Not installing system proc provider " + pi.name
                                + ": not system .apk");
                        providers.remove(i);
                    }
                }
            }
        }
        if (providers != null) {
            //把provider安装到系统的ActivityThread中
            mSystemThread.installSystemProviders(providers);
        }
 
        mCoreSettingsObserver = new CoreSettingsObserver(this);
    }

找到名称为system的进程对象,就是SystemServer进程,然后根据进程对象去查询所有有关的ContentProvider,调用系统进程的主线程ActivityThread安装所有相关的ContentProvider,

具体是如何查找相关的contentProvider和如何安装ContentProvider到系统主线程的,接着分析下面两个方法。

private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
        List<ProviderInfo> providers = null;
        try {
            //调用PMS根据进程ID和进程名称来查询Provider
            ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager().
                queryContentProviders(app.processName, app.uid,
                        STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
            providers = slice != null ? slice.getList() : null;
        } catch (RemoteException ex) {
        }
        int userId = app.userId;
        if (providers != null) {
            int N = providers.size();
            for (int i=0; i<N; i++) {
                ProviderInfo cpi =
                    (ProviderInfo)providers.get(i);
               ……
                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
           //从AMS管理的contentProvider列表中查询对应的provider     
ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
                if (cpr == null) {
                    //如果AMS的Provider列表中没有对应的Provider实例,就根据查询的provider信息,创建一个对象保存到队列中
                    cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
                    mProviderMap.putProviderByClass(comp, cpr);
                }
               //同时将provider保存到processRecord对象的pubProviders列表中
                app.pubProviders.put(cpi.name, cpr);
                ……
            }
        }
        return providers;
    }

这个方法就是从PMS中查询和SystemServer进程相关的Provider,也就是SettingsProvder,然后将它保存到AMS的contentProvider列表中,同时也将它保存到系统进程对象ProcessRecord的变量pubProviders列表中,保存到AMS的provider列表中是因为AMS需要管理所有的ContentProvder,保存到进程对象的pubProviders列表中是因为,每个ContentProvider都需要对应到一个进程中去。

接着看如何将SettingsProvider安装到系统的主进程中去。

private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
         ……
        for (ProviderInfo cpi : providers) {
            //通过installProvider方法把provider封装成一个ContentProviderHolder对象,有利于进程间传输
            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }
 
        try {
            //将上面得到的contentProviderHolder对象发布到AMS服务,getApplicationThread代表本地进程的一个binder对象,binder对象可跨进程传输,它在AMS中对应一个ProcessRecord.
            ActivityManagerNative.getDefault().publishContentProviders(
                getApplicationThread(), results);
       ……
    }

该方法将得到的contentProvider对象封装成了contentProviderHolder对象,其实就是Binder对象,这样就可以进程间传输了,然后跨进程调用AMS服务注册Provider。AMS负责管理ContentProvider,只有将ContentProvider注册到AMS服务其他进程才能访问。

接着看AMS如何注册Provider。

public final void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) {
           ……
            //根据调用者的进程得到相应的processRecord对象,就是系统进程的ProcessRecord
            final ProcessRecord r = getRecordForAppLocked(caller);
           ……
 
            final int N = providers.size();
            for (int i = 0; i < N; i++) {
                //ActivityThread客户端传过来的provider src
                ContentProviderHolder src = providers.get(i);
                //根据src provider name得到一开始保存的进程中保存的ProciderRecord
                ContentProviderRecord dst = r.pubProviders.get(src.info.name);
               
                if (dst != null) {
                    ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                    //按类将它保存在mProviderMap中
                    mProviderMap.putProviderByClass(comp, dst);
                    String names[] = dst.info.authority.split(";");
                    for (int j = 0; j < names.length; j++) {
                        //按authority保存在mProviderMap中
                        mProviderMap.putProviderByName(names[j], dst);
                    }
 
                   ……
                    }

AMS的注册服务就是根据参数传过来的provider信息,找到原先进程中pubProviders列表中保存的ContentProviderRecord,然后将它分别以类为key保存在mProviderMap中,和以authority为key保存在mProviderMap中。即AMS提供了多种方案来查找一个ContentProvider,一种是通过authority来查找,一种是指明CompomentName来查找。

此刻位置一个SettingsProvider就正式注册到SystemServer进程中了,所以可以看出installSystemProvider方法的主要工作就是按照普通进程类似的方式,将SettingsProvider注册到系统进程中,方便系统进程对settings的配置数据进行调用。

ActivityManagerService的systemReady方法

public void systemReady(final Runnable goingCallback) {
        synchronized(this) {
            //初始化Doze模式的controller
            mLocalDeviceIdleController
                    = LocalServices.getService(DeviceIdleController.LocalService.class);
 
                
        //重置RecentTasks
            mRecentTasks.clear();
            mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
            mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
            mTaskPersister.startPersisting();
 
            ……
            //设置systemReady为true
            mSystemReady = true;
        }
 
        ArrayList<ProcessRecord> procsToKill = null;
        //收集那些在AMS之前启动的进程
        synchronized(mPidsSelfLocked) {
            for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
                ProcessRecord proc = mPidsSelfLocked.valueAt(i);
                if (!isAllowedWhileBooting(proc.info)){
                    if (procsToKill == null) {
                        procsToKill = new ArrayList<ProcessRecord>();
                    }
                    procsToKill.add(proc);
                }
            }
        }
       //将那些在AMS之前启动的进程杀死,有的进程不能再AMS之前启动
        synchronized(this) {
            if (procsToKill != null) {
                for (int i=procsToKill.size()-1; i>=0; i--) {
                    ProcessRecord proc = procsToKill.get(i);
                    Slog.i(TAG, "Removing system update proc: " + proc);
                    removeProcessLocked(proc, true, false, "system update done");
                }
            }
 
 
        }
 
        //从settingsProvider的设置总初始化部分变量
        retrieveSettings();
        //调用callback方法,该方法在systemServer代码中实现
        if (goingCallback != null) goingCallback.run();
 
             
                    //查询那些persistent为1的application,并启动他们所在的进程
                    List apps = AppGlobals.getPackageManager().
                        getPersistentApplications(STOCK_PM_FLAGS);
                    if (apps != null) {
                        int N = apps.size();
                        int i;
                        for (i=0; i<N; i++) {
                            ApplicationInfo info
                                = (ApplicationInfo)apps.get(i);
                            if (info != null &&
                                    !info.packageName.equals("android")) {
                                addAppLocked(info, false, null /* ABI override */);
                            }
             
            }
 
            //启动HomeActivity,也就是launcher程序
            mBooting = true;
            startHomeActivityLocked(mCurrentUserId, "systemReady");
           ……
        }
    }

SystemReady方法也是比较长,大致可以分为四个部分

第一:在systemReady的时候初始化了deviceIdleController等对象
第二:移除并杀死了那些不该在AMS之前启动的进程
第三:执行了参数传入的回调函数
第四:启动了Launcer界面
第五:启动那些persistent配置为1的进程。

再来看些systemReady参数的回调函数做了什么工作.

  try {
                    //ams开始监听native层的crash信息
                    mActivityManagerService.startObservingNativeCrashes();
                } catch (Throwable e) {
                    reportWtf("observing native crashes", e);
                }
                //初始化webVew
                WebViewFactory.prepareWebViewInSystemServer();
 
                try {
                    //启动systemUI
                    startSystemUi(context);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
                try {
                    //调用其他服务的systemready方法
                    if (networkScoreF != null) networkScoreF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Score Service ready", e);
                }
……

 这个回调函数中主要工作就是启动systemUI并调用其他服务的systemReady方法,SystemReady函数完成了系统就绪的必要的工作,启动了HomeActivity和SystemUI,然后Android系统就全部启动了。
AMS服务启动主要分为几个步骤。

1. 创建了SystemServer进程的运行环境,包括一个ActivityThread主线程,一个和系统进程相关的Context对象。
2. 调用AMS的构造方法和start方法,对AMS必要的内容进行初始化
3. 将函数AMS注册到ServiceManager中,同时对systemServer进程也创建了一个ProcessRecord对象,并设置Context的appliation为framework-res的application对象
4. 将settingsProvider加载到系统进程systemServer中
5. 调用systemReady方法做一些启动前的就绪工作,并启动了HomeActivity和SystemUI

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342