深入理解AMS之启动过程
阅读原文时间:2021年04月20日阅读:4

文章目录

概述

  ActivityManagerService(以下简称AMS)是系统服务的一部分,它在SystemServer中被启动,主要负责四大组件状态管理与查询、进程创建与状态管理、Task切换与调度、cpu或mem等辅助状态监听等工作。它是系统核心服务,也是日常我们使用得最频繁的系统服务之一。

  AMS是通过Binder机制在C/S端相互串联调用,就如上述所示那样,左半部分是service端,而有半部分主要是client端使用。

  客户端使用AMS一般是通过调用ActivityManagerNative的getDefault()方法获取ActivityManagerProxy实例,进而与服务端AMS进行通信。

// frameworks/base/core/java/android/app/ActivityManagerNative.java
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            IActivityManager am = asInterface(b);
            return am;
        }
    };

   static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ActivityManagerProxy(obj);
    }

  AMS继承自ActivityManagerNative类,它属于Binder服务端,也是业务处理的核心部分(如我们通过startActivity()启动一个Activity这个操作的核心部分都是由AMS来处理的)。下面我们就来介绍下AMS的启动过程。

AMS启动过程

  AMS服务依附于Zygote启动的system_server进程中,这个进程的主要启动类是SystemServer。SystemServer的main方法如下:

// frameworks/base/services/java/com/android/server/SystemServer.java
    public static void main(String[] args) {
        new SystemServer().run();
    }

  可见,main方法只是起到过渡作用,在main方法中创建了SystemServer实例并调用了其run()方法来处理具体的逻辑。

// frameworks/base/services/java/com/android/server/SystemServer.java
    private void run() {
        //...
        Looper.prepareMainLooper();

        //加载native服务
        System.loadLibrary("android_servers");
        nativeInit();//启动native sensor service

        //...
        createSystemContext();

        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            throw ex;
        }

        //...
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

  上述方法中,我们很容易的就看到SystemServer主线程使用了Handler机制,是基于消息驱动的。在进入实质轮询之前有关AMS的大概分为以下三个流程:

  • 启动环境的配置
  • AMS服务的创建
  • AMS服务的初始化

这三个流程我们将在下面分别介绍。

启动环境的配置

  AMS启动环境包括上下文环境与服务管理者环境,在run()方法中分别对应SystemContext的创建和SystemServiceManager的创建。

// frameworks/base/services/java/com/android/server/SystemServer.java#run
    // Initialize the system context.
    createSystemContext();

    // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
SystemContext的创建

  Context上下文环境在Android中随处可见,小到Activity、Service,大到此处的SystemServer,都需要有一个上下文执行环境,在这个环境中包含了当前进程所需要的资源等信息。而在SystemServer进程中这个上下文环境就是通过createSystemContext()方法创建的。

// frameworks/base/services/java/com/android/server/SystemServer.java
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

  在createSystemContext()中我们看到其调用了ActivityThread的静态方法systemMain()后从获取了系统上下文SystemContext,并设置当前上下文的theme主题。

  普通的应用进程的启动是由Zygote运行ActivityThread的main()方法完成的,这个main()方法使用Handler机制处于消息轮询状态使得这个被创建的应用进程持续运转。但是对于系统进程SystemServer来说,它的启动并不走ActivityThread的main()方法,而是如createSystemContext()所示,调用systemMain()的方式绑定系统进程。systemMain()方法如下:

// frameworks/base/core/java/android/app/ActivityThread.java
    public static ActivityThread systemMain() {
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(true);
        } else {
            HardwareRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();//初始化资源管理者
        thread.attach(true);//初始化Application、Context等
        return thread;
    }

  可以看见,systemMain()方法创建了一个ActivityThread实例并调用其attach()方法绑定了这个进程,这一调用逻辑在main()中也有,不同的是systemMain()方法依附于系统进程,是系统专用方法。

// frameworks/base/core/java/android/app/ActivityThread.java
    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {//普通应用进程
            //...
        } else {//系统进程
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());//设置进程名
            try {
                mInstrumentation = new Instrumentation();
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }
        DropBox.setReporter(new DropBoxReporter());//dropbox日志输出
        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {/**省略callback内部代码*/);
    }

  attach()方法在systemMain()和main()中都有调用,不同的是传入的参数,它标识了是否为系统进程调用,在systemMain()中这个参数传入的是true。在上述方法中,大致完成了以下工作:

  • 标识当前线程及是否系统线程。sCurrentActivityThread标识了当前方法的调用线程,在本文中这个线程就是SystemServer主线程。

  • 设置当前进程名为system_process。

  • 创建Instrumentation方便之后系统组件初始化及监控组件与用户的交互。

  • 创建SystemContext与AppContext上下文环境。

  • 创建Application实例并调用其onCreate生命周期方法。

  • dropbox日志输出及ViewRootImpl配置变换监听。

      其他的都比较好理解,代码里边也有体现,唯独SystemContext我们需要把它拎出来说下。SystemContext在ActivityThread是单实例存在,它通过getSystemContext()方法创建的。

    // frameworks/base/core/java/android/app/ActivityThread.java
    public ContextImpl getSystemContext() {
    synchronized (this) {
    if (mSystemContext == null) {
    mSystemContext = ContextImpl.createSystemContext(this);
    }
    return mSystemContext;
    }
    }

      在getSystemContext()方法中,这个系统上下文是通过ContextImpl的createSystemContext()创建的。这里需要了解的是ContextImpl可以创建整个android需要的大部分上下文环境,如SystemContext、AppContext、ActivityContext、DisplayContext、PackageContext等。这几个上下文中,SystemContext的上下文创建时比较特殊的一个。

    // frameworks/base/core/java/android/app/ContextImpl.java
    static ContextImpl createSystemContext(ActivityThread mainThread) {
    LoadedApk packageInfo = new LoadedApk(mainThread);
    ContextImpl context = new ContextImpl(null, mainThread,
    packageInfo, null, null, false, null, null);
    context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
    context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
    return context;
    }

      在createSystemContext()中首先会创建一个LoadedApk对象。顾名思义,LoadedApk表示了一个加载到内存中的apk,此处使用的是一个参数的LoadedApk构造,这个构造方法如下:

    // frameworks/base/core/java/android/app/LoadedApk.java
    LoadedApk(ActivityThread activityThread) {
    mActivityThread = activityThread;
    mApplicationInfo = new ApplicationInfo();
    mApplicationInfo.packageName = "android";
    mPackageName = "android";
    //…
    mClassLoader = ClassLoader.getSystemClassLoader();
    mResources = Resources.getSystem();
    }

      创建的SystemContext中的LoadedApk对象(即mPackageInfo)指明了包名为android。这样我们的SystemContext就可以据此mPackageInfo访问其加载到内存的资源。当然了,为了使得LoadedApk的资源可用,还需要调用调用ContextImpl的installSystemApplicationInfo()方法,这个调用是在后续介绍的AMS类中。

      这个被加载到SystemServer中的apk其实就是framework-res.apk。其源码路径是frameworks/base/core/res。这个路径下的Android.mk文件也验证了这一点。

    // frameworks/base/core/res
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_NO_STANDARD_LIBRARIES := true
    LOCAL_PACKAGE_NAME := framework-res
    LOCAL_CERTIFICATE := platform
    //…
    LOCAL_EXPORT_PACKAGE_RESOURCES := true
    //…

      这个mk文件负责把当前路径下的文件打包成framework-res.apk,这个apk是使用了platform平台签名并且其资源可以被其他进程使用。

    // frameworks/base/core/res/AndroidManifest.xml
    //…

      当我们进入apk的清单文件中,我们可以看见其包名正是android,这也正是上面SystemContext中的LoadedApk所加载的资源。补充一下,application标签中的android:process="system"则标识了当前apk的进程名processName为system。

      经此之后,SystemContext就算初步准备完成(后边需要调用installSystemApplicationInfo()才算完全ok)。

SystemService管理者创建

  在SystemServer中需要启动诸多系统服务,如Installer、ActivityManagerService、DisplayManagerService、AlarmManagerService等等,这些服务相互影响、依赖,启动顺序也有先有后,为了方便管理这些服务的生命周期,故设计了SystemService基类,这些系统服务通过继承SystemService并以约定的方式启动起来,后期也统一由SystemServiceManager管理。

// frameworks/base/services/core/java/com/android/server/SystemService.java
public abstract class SystemService {
    //...
    private final Context mContext;
    public SystemService(Context context) {
        mContext = context;
    }
    //服务启动-当调用SystemServiceManager#startService时触发
    public abstract void onStart();
    //启动阶段回调
    public void onBootPhase(int phase) {}

    //多用户切换接口
    public void onStartUser(int userHandle) {}
    public void onSwitchUser(int userHandle) {}
    public void onStopUser(int userHandle) {}
    public void onCleanupUser(int userHandle) {}

  在SystemService中包含了一些多用户切换的回调接口,以及启动过程的回调接口。如上所述的那样系统服务通过继承SystemService并添加到SystemService管理者中,这样,如果用户状态、启动状态等发生改变就可由SystemServiceManager通知这些继承了SystemService的服务。

  正因此,SystemServiceManager必须在各项服务开始创建之前作为启动环境的一部分被启动起来。

// frameworks/base/services/java/com/android/server/SystemServer.java#run
        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

  从以上代码来看,SystemServiceManager实例的创建并不复杂,仅仅需要把系统上下文传入就可,当然,为了进程内可以方便的访问这个系统服务管理者,在其创建后就将其添加到LocalServices中去了。LocalSevices中维护了一个静态的、以服务名-服务实例作为K-V结构的ArrayMap,这样在进程任何地方我们都可以通过LocalServices的getService()方法获取对应服务。

  SystemServiceManager主要关键方法有startService()方法和startBootPhase()方法。下边我们分别对这两个方法进行简析。

  1. startService():启动服务

    // frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
    public T startService(Class serviceClass) {
    final String name = serviceClass.getName();
    Slog.i(TAG, "Starting " + name);

        // Create the service.用于判断SystemService是否是class的父类
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
                    + ": service must extend " + SystemService.class.getName());
        }
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);
        } catch/***/}
    // Register it.
    mServices.add(service);
    
    // Start it.
    try {
        service.onStart();
    } catch (RuntimeException ex) {
        throw new RuntimeException("Failed to start service " + name
                + ": onStart threw an exception", ex);
    }
    return service;
    }

      startService负责创建以及启动一个系统服务,这个方法需要传入一个SystemService的子类class。其内部大概分为三个环节:

        创建服务。通过java反射将SystemContext作为构造参数以创建class对应服务。

        注册服务。把创建好的服务添加到mServices中去,这样后续的这个SystemService的生命周期的触发就交由SystemServiceManager了。

        调用服务的onStart()周期方法。onStart()是当前SystemService启动周期触发的方法。

  2. startBootPhase():不同的启动阶段触发

    // frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
    public void startBootPhase(final int phase) {
    if (phase <= mCurrentPhase) {
    throw new IllegalArgumentException("Next phase must be larger than previous");
    }
    mCurrentPhase = phase;//当前所处的启动阶段
    final int serviceLen = mServices.size();
    for (int i = 0; i < serviceLen; i++) {//分发所触发的启动阶段给各SystemService
    final SystemService service = mServices.get(i);
    try {
    service.onBootPhase(mCurrentPhase);
    } catch (Exception ex) {
    //…
    }
    }
    }

      启动阶段一般分为以下几个阶段:

启动阶段

含义

调用时机

PHASE_WAIT_FOR_DEFAULT_DISPLAY

100

默认display即主屏设备准备完成

当DisplayManagerService构建完毕时,这时候主屏已经构建完成,如AMS已经可以着手Stack信息的构建等

PHASE_LOCK_SETTINGS_READY

480

锁屏设置服务启动完成

LockSetttingsService已经完成准备工作,这时候可以获取诸如锁屏密码等相关数据

PHASE_SYSTEM_SERVICES_READY

500

关键系统服务已经启动完成

大部分系统服务已经完成准备工作,此阶段紧随着锁屏启动阶段被调用

PHASE_ACTIVITY_MANAGER_READY

550

AMS服务已完成准备工作,可以向外提供服务

在AMS的systemReady()中被调用,用于告诉系统服务AMS准备完成,到此阶段后,诸如广播等就可以发送了

PHASE_THIRD_PARTY_APPS_CAN_START

600

第三方应用已经可以启动

在AMS的systemReady()中,当网络服务、存储服务、音频服务、systemui等准备完成后被调用,以告诉系统服务第三方应用可以启动了

PHASE_BOOT_COMPLETED

1000

开机启动完成

当任意Activity启动完成即onResume之后会通过completeResumeLocked()通知AMS当前处于ActivityIdle状态,这时AMS就会尝试在activityIdleInternalLocked()调用链中通知开机启动完成。显然开机启动完成发生在Launcher启动完成时

  当SystemServer到了上述某一启动阶段时,可以通过SystemServiceManager的startBootPhase()方法通知各系统服务,各系统服务触发onBootPhase()以处理当前启动阶段的任务。

AMS服务的创建

  在SystemServer进程的系统运行环境初始化完毕之后,接下来就是各个系统服务的创建于初始化,这些系统服务分为了三类:

  • bootstrap类型-引导服务

  • core类型-核心服务

  • other类型-其他服务

      我们的AMS的创建就是在startBootStrapServices()方法中完成的。

    // frameworks/base/services/java/com/android/server/SystemServer.java
    private void startBootstrapServices() {
    mInstaller = mSystemServiceManager.startService(Installer.class);

        //startService调用构造与其onStart方法,其最终调用了ActivityManagerService的start方法
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);//给AMS设置SSM
        //...
    }

      与诸如Installer、PowerManagerService等系统服务不同的是,AMS因为binder通信的需要,其继承了ActivityManagerNative而非继承于SystemService。基于系统服务管理的需要,AMS.LifeCycle类就应运而生了。在上述代码中,SystemServiceManager通过startService()方法创建AMS.LifeCycle实例并调用其onStart()方法。

    // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    public static final class Lifecycle extends SystemService {
    private final ActivityManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }
    @Override
    public void onStart() {
        mService.start();
    }
    
    public ActivityManagerService getService() {
        return mService;
    }
    }

      在AMS.LifeCycle首先通过其构造方法创建了AMS实例,并通过onStart()回调调用了AMS的start()方法。且为了方便其它SystemService使用AMS,向外提供了getService()方法获取。另外我们需要注意的是AMS.LifeCycle并没有实现onBootPhase()方法。

      到了此处,我们安卓中非常重要的组件管理者AMS也将登场。

    // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    public ActivityManagerService(Context systemContext) {
    mContext = systemContext;//系统上下文
    mFactoryTest = FactoryTest.getMode();//工程模式
    mSystemThread = ActivityThread.currentActivityThread();//标记当前进程的ActivityThread,当前进程也为AMS需要管理的一部分。

        Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
    mHandlerThread = new ServiceThread(TAG,
            android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    mHandlerThread.start();//AMS专用的线程,用于处理组件启动超时事件(ANR)、GC等
    mHandler = new MainHandler(mHandlerThread.getLooper());
    
    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;//两者用于管理广播组件
    
    mServices = new ActiveServices(this);//管理Service组件
    mProviderMap = new ProviderMap(this);//管理ContentProvider组件
    
    //创建/data/system 目录
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    systemDir.mkdirs();
    mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);//电池状态统计服务的初始化
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
    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);//app权限管理
    mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));//uri授权文件
    
    // User 0 is the first and only user that runs at boot.
    mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));//添加user 0用户
    mUserLru.add(Integer.valueOf(0));
    updateStartedUserArrayLocked();
    
    GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);//获取opengl版本号
    
    mConfiguration.setToDefaults();//设置默认配置
    mConfiguration.setLocale(Locale.getDefault());
    
    mConfigurationSeq = mConfiguration.seq = 1;
    mProcessCpuTracker.init();//cpu使用记录跟踪者初始化。
    
    mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
    mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);//防火墙初始化
    mStackSupervisor = new ActivityStackSupervisor(this);//Activity管理者
    mTaskPersister = new TaskPersister(systemDir, mStackSupervisor);//Task持久化存储器
    
    mProcessCpuThread = new Thread("CpuTracker") {/**cpu统计的执行*/};
    
    mLockToAppRequest = new LockToAppRequestDialog(mContext, this);
    
    Watchdog.getInstance().addMonitor(this);//监测AMS的运行状态,如死锁、阻塞等
    Watchdog.getInstance().addThread(mHandler);
    }

在AMS构造方法中进行的操作非常多,大概可以分为以下几类:

  • 组件管理。Activity管理依赖ActivityStackSuoervisor、TaskPersister,Service管理依赖ActiveServices,广播的管理依赖BroadcastQueue,内容提供者管理依赖ProviderMap。

  • 监测统计。ProcessCpuTracker用于跟踪各进程cpu,Watchdog监测AMS运行状态,还有诸如电池状态、进程状态、app权限状态、uri授权状态等管理与监测。

  • 配置初始化。Configuration系统配置初始化,UserStartedState用户初始化等。

      在AMS构造方法完成对各个实例的初始化之后,接下来就是AMS.LifeCycle的onStart()回调了。这个回调直接调用了AMS的start()方法,这个方法比之构造方法要简约的多,主要是负责AMS构建的扫尾工作。

    // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    private void start() {
    Process.removeAllProcessGroups();//移除进程组
    mProcessCpuThread.start();//启动cpu使用率线程

        mBatteryStatsService.publish(mContext);//通过ServiceManager添加为实名binder
        mAppOpsService.publish(mContext);//添加为实名binder
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());//添加内部交互service,可通过LocalServices获取
    }

      上述电池统计服务与app权限管理服务继承自AIDL的Stub类(Binder子类)。其publish()方法内部则是通过ServiceManager把这两服务变为实名Binder服务,外界可通过服务名batterystats和appops访问。

AMS服务的初始化

  AMS的方法调用链如下所示。

  AMS的初始化过程依赖很多系统服务的构建,这也导致了上图所示的那样,在三类系统服务启动过程中AMS都有需要初始化的内容。这些初始化过程中有以下几个过程较为重要:

  • initPowerManagement()。
  • setSystemProcess()。
  • installSystemProviders()。
  • setWindowManager()。
  • systemReady()。
initPowerManagement

  此过程在SystemServer完成对PowerManagerService的初始化后执行,主要对AMS所需要的电源管理组件的初始化操作。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    public void initPowerManagement() {
        mStackSupervisor.initPowerManagement();//电源锁,防止AMS启动时进入休眠
        mBatteryStatsService.initPowerManagement();
    }

上述代码段实质上分为两个部分:

  1. ActivityStackSuoervisor初始化电源唤醒锁,在这个唤醒锁被持有的情况下系统是不能被锁屏休眠的,例如有Activity正处于启动过程中的时候。
  2. 电池统计服务注册低电量(低功耗)模式观察者,用于观察用户是否打开了低电量省电模式。
setSystemProcess

  当PackageManagerService完成初始化之后,接着就调用了AMS的setSystemProcess()方法,顾名思义,此方法把当前进程设置为系统进程。这个方法里边内容大致可分为三个部分阅读。

辅助功能的Binder实名化

  此方法内部首先将一些AMS辅助功能通过ServiceManager实名化为binder服务。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#setSystemProcess
    public void setSystemProcess() {//启动AMS辅助服务,并标识system_process的进程记录
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);//把当前AMS注册为实名服务
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);//进程状态管理的binder实名化
            ServiceManager.addService("meminfo", new MemBinder(this));//各进程内存状态的binder实名化
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));//各进程UI性能状态的binder实名化
            ServiceManager.addService("dbinfo", new DbBinder(this));//各进程数据库debug信息的binder实名化
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));//各进程cpu数据的binder实名化
            }
            ServiceManager.addService("permission", new PermissionController(this));
    }

  上述方法分段中,首先将AMS本身设为了binder服务,经此之后当前进程或其他应用进程就可通过getSystemService()或ActivityManagerNative访问这个AMS了。之后则添加了一些辅助binder服务如MemBinder、GraphicsBinder等,这些辅助服务依赖于AMS,利用了binder的dump功能完成对AMS中各个状态的监测。

  上述的辅助服务基本上都实现了binder的dump()方法,当我们调用adb shell dumpsys命令时,实质上就是通过binder机制调用到这些binder服务的dump()方法。在dump()中开发者可以打印想要监测的内容。例如上述的MemBinder就在dump()方法中调用AMS.dumpApplicationMemoryUsage()打印了各个应用的内存使用情况。

初始化系统包信息

  其次,设置当前进程所使用到的系统包信息.这个系统包的包名是android,正如本章之前讨论LoadedApk所说的那样,在framework-res.apk这个系统apk加载完成之后,需要调用其installSystemApplicationInfo()完成初始化工作这部分工作就是在这里完成的。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#setSystemProcess
            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS);
            //系统LoadedApk构造需要调用installSystemApplicationInfo方法,把正确的ApplicationInfo与classloader加进去
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
加入进程管理

  最后,在setSystemProcess()方法完成了前两项任务之后,接下来就是将当前进程设置为系统进程并纳入AMS的进程管理。在AMS中进程管理是通过把每个进程标记为一个个ProcessRecord完成的。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#setSystemProcess
            synchronized (this) {//标识当前进程
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.persistent = true;//常驻系统
                app.pid = MY_PID;//进程id
                app.maxAdj = ProcessList.SYSTEM_ADJ;//优先级
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                mProcessNames.put(app.processName, app.uid, app);//存放至map管理
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.put(app.pid, app);//pid为key-ProcessRecord为value的映射关系
                }
                updateLruProcessLocked(app, false, null);//更新进程的lru关系,与lmk相关
                updateOomAdjLocked();//更新进程优先级关系
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }

  在上述setSystemProcess()方法片段中,当前进程的ProcessRecord通过newProcessRecordLocked()方法创建,并接着修改了比较重要的几个属性及方法:

  • persistent:标识SystemServer进程为常驻内存类型的进程。一般情况下,系统应用可在清单文件的application标签中使用persistent属性将这个应用标识为常驻内存,这样如果应用crash,则可以不断重启。

  • pid:当前进程id,进程id可通过如下方式获取:

    // frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    static final int MY_PID = Process.myPid();

  • maxAdj:当前进程的优先级。这个属性主要是安卓进程回收机制LMK的回收依据,maxAdj值范围-17~16,其值越小,越不容易被回收,正常情况下,前台进程的adj值为0。而此处的maxAdj值为SYSTEM_ADJ=-16,可以说已经非常低了。

  • makeAlive():激活当前进程。也就是将应用程序用于进程间binder通信的IApplicationThread绑定到ProcessRecord中,这样,我们就可以通过ProcessRecord来调度进程(ActivityThread)了。

      在修改完这些属性之后,就把当前进程记录存入AMS全局变量mProcessNames和mPidsSelfLocked中并更新进程的LRU关系与oomAdj优先级关系。

installSystemProviders

  在完成把当前SystemServer进程设置为系统进程后,接着在SystemServer的startOtherServices()对系统的内容提供者进程初始化操作,这个过程是通过AMS.installSystemProviders()方法完成的。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    public final void installSystemProviders() {
        List<ProviderInfo> providers;
        synchronized (this) {
            //要查询的目标进程 进程名:system,所属uid为system
            ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
            providers = generateApplicationProvidersLocked(app);//使用PMS查询所有符合条件的内容提供者
            if (providers != null) {//过滤掉非系统提供者
                for (int i=providers.size()-1; i>=0; i--) {
                    ProviderInfo pi = (ProviderInfo)providers.get(i);
                    if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
                        providers.remove(i);
                    }
                }
            }
        }
        if (providers != null) {//在client端使用ProviderClientRecord记录,通过AMSpublish内容提供者(在AMS中使用ContentProviderRecord记录)
            mSystemThread.installSystemProviders(providers);
        }
        //初始化核心设置观察者
        mCoreSettingsObserver = new CoreSettingsObserver(this);
    }

在installSystemProviders()方法中,对内容提供者的操作过程如下:

  • ContentProvider查询条件的设置。因为是通过PMS来查询,首先规定了要查询的进程名为system且其shareUid应为android.uid.system。在系统中符合此条件的package有framework-res.apk、SettingsProvider.apk、FusedLocation.apk等,在这几者当中SettingsProvider中包含了系统核心设置的数据。
  • 使用PMS查询所有符合条件的Provider。查询过程是通过PMS的queryContentProviders()完成的,在查询完之后得到的Provider信息以ContentProviderRecord的形式添加到AMS中成员变量ProviderMap中去,这样系统内容提供者就可以被AMS管理起来了。
  • 过滤非系统内容提供者。
  • 向Client端及AMS公布合法的ContentProvider。对于SystemServer进程来说,这个client就是之前创建SystemContext时出现的用于标识当前主线程的ActivityThread(即上述的mSystemThread变量)。这些系统内容提供者以ProviderClientRecord的形式被记录到ActivityThread中。
  • 初始化核心设置观察者。
setWindowManager

  在startOtherServices()中当WindowManagerService完成初始化创建后,需要把WMS设置给AMS。AMS中需要对Activity的管理,这里涉及到WMS也是必然。

// frameworks/base/services/java/com/android/server/SystemServer.java#startOtherServices
        //WMS初始化
        wm = WindowManagerService.main(context, inputManager,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                !mFirstBoot, mOnlyCore);
        ServiceManager.addService(Context.WINDOW_SERVICE, wm);
        ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
        //给AMS设置窗口管理者
        mActivityManagerService.setWindowManager(wm);//主要是给ActivityStaskSupervisor设置主屏幕stack管理者

  在上述代码中,我们可以看见WMS的初始化是通过其自身的main()方法完成的,并在初始化完成后被加入到ServiceManager实名binder服务中去(可以想象到的是WMS必然是Binder的子类)。然后,AMS通过调用setWindowManager()方法把自己同WMS关联起来。

  在这个AMS.setWindowManager()方法中,除了把WMS保存作为成员变量外,重要的是把WMS设置给了Activity管理者ActivityStackSupervisor。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    public void setWindowManager(WindowManagerService wm) {
        mWindowManager = wm;
        //把WMS设置给Activity管理者
        mStackSupervisor.setWindowManager(wm);
    }

  ActivityStackSupervisor(以下简称为ASS)直观上的翻译就是ActivityStack管理者,AMS通过这个ASS管理着系统中所有的Activity。在此处的AMS初始化过程中ASS也通过setWindowManager()方法与WMS建立起了联系。当然,ASS.setWindowManager()方法不止于此,它还进行了一些其它的操作,我们先来看下方法内容。

// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    void setWindowManager(WindowManagerService wm) {
        synchronized (mService) {
            mWindowManager = wm;//保存WMS

            mDisplayManager =
                    (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
            mDisplayManager.registerDisplayListener(this, null);//注册Display改变监听
            //获取当前屏幕数并遍历这些Display
            Display[] displays = mDisplayManager.getDisplays();
            for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
                final int displayId = displays[displayNdx].getDisplayId();
                //每个屏幕由ActivityDisplay进行描述标识,它拥有多个stack
                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
                if (activityDisplay.mDisplay == null) {
                    throw new IllegalStateException("Default Display does not exist");
                }
                //把display描述者加入到mActivityDisplays中进行管理
                mActivityDisplays.put(displayId, activityDisplay);
            }
            //根据stackId,每个stackId由一个ActivityContainer管理,这个ActivityContainer包含了一个stack
            createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
            //默认情况下,创建出来的home stack是拥有focus的stack
            mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
            //输入/触摸事件管理者
            mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
            //leanback为tv支持库,这里判断系统是否为android tv系统
            mLeanbackOnlyDevice = isLeanbackOnlyDevice();
        }
    }

上述ASS.setWindowManager()方法大概可以分为以下几个部分来解读:

  • ASS关联WMS。因为WMS涉及到Activity返回栈的操作,所以在此处初始化过程中对WMS进行关联,方便后期调用。

  • 从DMS获取当前显示设备(Display)数量并封装为ASS能识别的ActivityDisplay。在通常情况下,DMS只有默认主屏设备,但不排除会有副屏甚至多屏显示需求,那么此时可能初始化多个ActivityDisplay用于描述这些Display设备。

  • 在默认显示设备创建HomeStack。默认显示设备一般是displayId为0的主屏设备。它在AMS中由ActivityDisplay负责描述,在此处初始化时为这个主屏设备添加了HomeStack,并把这个HomeStack标记为拥有当前焦点的Stack。进一步来说,这个HomeStack其实是ActivityStack类型,它被容器ActivityContainer持有,并通过attachToDisplayLocked()方法被添加到ActivityDisplay中去。

    // frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    private int createStackOnDisplay(int stackId, int displayId) {
    ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
    if (activityDisplay == null) {
    return -1;
    }
    //根据stackId创建容器Container,在容器中持有一个ActivityStack
    ActivityContainer activityContainer = new ActivityContainer(stackId);
    mActivityContainers.put(stackId, activityContainer);
    //把容器添加到ActivityDisplay中去,需要注意的是,一个显示设备可能拥有多个ActivityStack
    activityContainer.attachToDisplayLocked(activityDisplay);
    return stackId;
    }

  • 获取触摸事件管理者并判断当前是否仅支持TV显示。

systemReady

  systemReady()方法时AMS在启动过程中最晚执行的方法,该方法较为庞大,同上述setSystemProcess()方法一样,下边我们分段进行解析。

重构最近任务列表

  因AMS.systemReady()方法可能多次被调用到,此处我们仅先分析首次调用的流程。在进入此方法后,其首先恢复了最近任务列表。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part1
            if (mRecentTasks == null) {
                mRecentTasks = mTaskPersister.restoreTasksLocked();//从本地重新拉取task数据
                if (!mRecentTasks.isEmpty()) {//创建单独的Stack来存放拉取的Task数据
                    mStackSupervisor.createStackForRestoredTaskHistory(mRecentTasks);
                }
                cleanupRecentTasksLocked(UserHandle.USER_ALL);
                mTaskPersister.startPersisting();//开启write线程实时把mRecentTasks中的数据本地化
            }

  mRecentTasks是用于记录最近启动的TaskRecord集合(最近任务列表),在AMS启动时需要从TaskPersister中把之前保存的启动记录(如果有的话)从本地拉取到内存中。

PRE_BOOT_COMPLETED广播

  接下来处理PRE_BOOT_COMPLETED广播,顾名思义,该广播先于BOOT_COMPLETED广播发送出来。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part2
            // Check to see if there are any update receivers to run.
            if (!mDidUpdate) {
                if (mWaitingUpdate) {
                    return;
                }
                final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
                mWaitingUpdate = deliverPreBootCompleted(new Runnable() {
                    public void run() {
                        synchronized (ActivityManagerService.this) {
                            mDidUpdate = true;
                        }
                        writeLastDonePreBootReceivers(doneReceivers);//把广播到的组件名本地化
                        showBootMessage(mContext.getText(
                                R.string.android_upgrading_complete),
                                false);//即将完成启动。
                        systemReady(goingCallback);//重新执行方法
                    }
                }, doneReceivers, UserHandle.USER_OWNER);

                if (mWaitingUpdate) {
                    return;
                }
                mDidUpdate = true;
            }

  广播的发送逻辑主要通过deliverPreBootCompleted()方法完成,在这个方法中,首先通过PMS查询所有静态注册了PRE_BOOT_COMPLETED广播接收者的组件(仅系统应用有效),并通过方法broadcastIntentLocked()发送此广播。在发送完成时会调用deliverPreBootCompleted()方法的callback回调,就是在上述part分段中就是那个匿名Runnable。

  此处由变量mDidUpdate和mWaitingUpdate来控制PRE_BOOT_COMPLETED的发送过程。

  • mDidUpdate:默认为false,在广播发送完毕后调用callback回调时被置为true。
  • mWaitingUpdate:默认为false,当查询到有组件还未处理PRE_BOOT_COMPLETED广播时会被置为true,后续直到广播处理完毕才被置为false。

  需要注意的是systemReady()方法时可能在多线程调用的,deliverPreBootCompleted()的Runnable中执行的systemReady()是在AMS构造方法中创建的服务线程中执行,而此处我们的systemReady()则是在SystemServer主线程中执行。

非persistent进程清理

  接下来则进入下一部分处理逻辑,在这部分中则对非persistent应用做了清理。

persistent意为持久化,指代android中的常驻内存应用,persistent类型的进程拥有极高优先级而不会被LMK机制杀死,且这种常驻进程在crash之后会由AMS重新启动(即保活效果)。这种应用一般在清单文件中有android:sharedUserId="android.uid.system"和android:persistent="true"两个属性修饰,这就意味着,persistent应用一定只能是系统应用。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part3

        //将非persistent应用添加到待kill进程中
        ArrayList<ProcessRecord> procsToKill = null;
        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);
                }
            }
        }
        //将非persistent应用清掉(杀死这些进程)
        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");
                }
            }
            mProcessesReady = true;
        }

  mPidsSelfLocked集合保存了AMS管理的所有系统进程及应用进程,即所有已启动的进程在mPidsSelfLocked都已有记录。在上述代码中,首先遍历这个集合来查找出所有已启动的非persistent进程并存放入procsToKill集合中,这个查找条件通过方法isAllowedWhileBooting()完成,其内部就是判断ApplicationInfo的persistent属性是否为true。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    boolean isAllowedWhileBooting(ApplicationInfo ai) {
        return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
    }

  查询出的所有非persistent进程都被放入procsToKill集合中,并马上通过removeProcessLocked()方法遍历清理掉这些进程。

启动信息加载

  在清理完提前启动的非persistent进程后,则加载了启动过程中需要的信息。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part4
        retrieveSettings();//从Settings中获取核心设置项
        loadResourcesOnSystemReady();//加载Recents UI所需资源

        synchronized (this) {
            readGrantedUriPermissionsLocked();//读取uri权限信息
        }

如上所示,加载的启动信息可区分为:

  • 获取核心设置项。
  • 加载Recents UI资源。Recents即SystemUI中的多任务列表,如果AMS允许显示多任务列表(即根据此处加载的mHasRecents判断),则需要在Activity处于pause阶段时获取截图。
  • 读取uri权限信息。这些uri权限信息是从系统文件/data/system/urigrants.xml中获取,并以UriPermission的形式保存在mGrantedUriPermissions中。
传参调用与用户启动通知

  在完成了启动信息加载之后,接下来的代码如下所示:

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part5
        if (goingCallback != null) goingCallback.run();//作为参数传进来的Runnable被调用,内部启动了systemui
                mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
                Integer.toString(mCurrentUserId), mCurrentUserId);通知电量统计服务当前用户启动
        mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
                Integer.toString(mCurrentUserId), mCurrentUserId);
        mSystemServiceManager.startUser(mCurrentUserId);//通知所有系统服务当前用户启动

在上述分段中有两个操作:

  1. 调用systemReady()方法的传参即Runnable。在这个Runnable的run()方法中,首先通过SystemServiceManager通知系统服务AMS准备完成,并启动了负责显示系统窗口如状态栏、导航栏等的SystemUI应用。当然,其后也包含了一些其他与AMS相关的辅助服务的ready工作,基于这样的服务很多,以下代码就不展开了。

    // frameworks/base/services/java/com/android/server/SystemServer.java#startOtherServices
    mActivityManagerService.systemReady(new Runnable() {
    @Override
    public void run() {
    //启动阶段设置为AMS准备完成
    mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
    try {
    //开启本地crash上报
    mActivityManagerService.startObservingNativeCrashes();
    } catch (Throwable e) {
    reportWtf("observing native crashes", e);
    }
    WebViewFactory.prepareWebViewInSystemServer();
    try {
    startSystemUi(context);//启动systemui,此处进行系统控件初始化,如状态栏、导航栏等
    } catch (Throwable e) {
    reportWtf("starting System UI", e);
    }
    //… 后续是其他辅助功能的systemReady
    }
    });
    }

  2. 通知电池统计服务和所有SystemService当前用户启动。

启动persistent应用
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part6
            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                //启动persistent应用
                try {
                    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 */);
                            }
                        }
                    }
                } catch (RemoteException ex) {
                    // pm is in same process, this will never happen.
                }
            }

  persistent应用的获取是通过PMS完成的,在PMS.getPersistentApplications()方法对于persistent应用的判断标准有两个:

  1. 是persistent应用,即清单文件的application标签中包含persistent属性且申明为true。

  2. 是系统应用,应用的清单文件中申明了uid所属为system。

      通过PMS获取到这些persistent应用后,就调用addAppLocked()方法启动它们。addAppLocked()方法就不贴出来了,我们只需要知道,其最终调用了Process.start()方法通知Zygote进程新建一个进程。

Launcher启动

  在完成了系统persistent应用的启动之后,紧接着就是安卓桌面也就是Launcher进程的启动。Launcher进程运行于默认显示设备的HomeStack中,正因为AMS在启动完成之际需要启动Launcher,所以之前的setWindowManager()方法中关于焦点Stack等设置就不难理解了。

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady  part7
            mBooting = true;
            startHomeActivityLocked(mCurrentUserId);//启动Launcher
            //...省略多用户启动广播的发送内容
            mStackSupervisor.resumeTopActivitiesLocked();
            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);//以广播形式通知用户发生切换

  Launcher桌面启动通过方法startHomeActivityLocked()完成,且为了保证Launcher进程的桌面Activity可见还调用了ASS.resumeTopActivitiesLocked()进行配合。

  至此,整个安卓桌面上的UI系统就已经启动成功,AMS启动过程也已告一段落。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章