Android 7.0 ActivityManagerService(1) AMS的启动过程

一、概况
ActivityManagerService(AMS)是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。

AMS通信结构如下图所示:

从图中可以看出:
1、AMS继承自ActivityManagerNative(AMN),并实现了Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。

2、AMN继承Java的Binder类,同时实现了IActivityManager接口,即AMN将作为Binder通信的服务端为用户提供支持。

3、在ActivityManagerNative类中定义了内部类ActivityManagerProxy,该类同样实现了IActivityManager接口,将作为客户端使用的服务端代理。

4、其它进程将使用ActivityManager来使用AMS的服务。ActivityManager通过AMN提供的getDefault接口得到ActivityManagerProxy,然后再以Binder通信的方式调用AMS的接口。

对AMS的基本情况有一个大概的了解后,我们一起来分析一下AMS的启动过程。
由于AMS启动涉及的内容比较多,我们将分段进行分析。

二、createSystemContext
在进入到AMS相关的流程前,我们需要先了解一下相关的准备工作。

我们已经知道了,zygote创建出的第一个java进程是SystemServer。
在SystemServer的run函数中,在启动AMS之前,调用了createSystemContext函数。

其代码如下所示:

.............
//SystemServer在启动任何服务之前,就调用了createSystemContext
//创建出的Context保存在mSystemContext中
// Initialize the system context.
createSystemContext();

// Create the system service manager.
//SystemServiceManager负责启动所有的系统服务,使用的Context就是mSystemContext
mSystemServiceManager = new SystemServiceManager(mSystemContext);
.............

我们跟进一下createSystemContext:

private void createSystemContext() {
    //调用ActivityThread的systemMain函数,其中会创建出系统对应的Context对象
    ActivityThread activityThread = ActivityThread.systemMain();

    //取出上面函数创建的Context对象,保存在mSystemContext中
    mSystemContext = activityThread.getSystemContext();

    //设置系统主题
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}

以上函数中,最重要的就是ActivityThread.systemMain了,我们分析一下该函数。

1、ActivityThread.systemMain

public static ActivityThread systemMain() {
    // The system process on low-memory devices do not get to use hardware
    // accelerated drawing, since this can add too much overhead to the
    // process.
    if (!ActivityManager.isHighEndGfx()) {
        //虽然写着ActivityManager,但和AMS没有任何关系
        //就是利用系统属性和配置信息进行判断

        //关闭硬件渲染功能
        ThreadedRenderer.disable(true);
    } else {
        ThreadedRenderer.enableForegroundTrimming();
    }

    //创建ActivityThread
    ActivityThread thread = new ActivityThread();
    //调用attach函数,参数为true
    thread.attach(true);
    return thread;
}

从上面的代码可以看出,ActivityThread的systemMain函数中,除了进行是否开启硬件渲染的判断外,主要作用是:
创建出ActivityThread对象,然后调用该对象的attach函数。

ActivityThread的构造函数比较简单:

ActivityThread() {
    mResourcesManager = ResourcesManager.getInstance();
}

比较关键的是它的成员变量:

..........
//定义了AMS与应用通信的接口
final ApplicationThread mAppThread = new ApplicationThread();

//拥有自己的looper,说明ActivityThread确实可以代表事件处理线程
final Looper mLooper = Looper.myLooper();

//H继承Handler,ActivityThread中大量事件处理依赖此Handler
final H mH = new H();

//用于保存该进程的ActivityRecord
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>()
..........
//用于保存进程中的Service
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
...........
//用于保存进程中的Application
final ArrayList<Application> mAllApplications = new ArrayList<Application>();
...........

我们需要知道的是,ActivityThread是Android Framework中一个非常重要的类,它代表一个应用进程的主线程,其职责就是调度及执行在该线程中运行的四大组件。
在Android中,应用进程指那些运行APK的进程,它们由zygote fork出来,其中运行着独立的dalvik虚拟机。
与应用进程相对的就是系统进程,例如zygote和SystemServer。

注意到此处的ActivityThread创建于SystemServer进程中。
由于SystemServer中也运行着一些系统APK,例如framework-res.apk、SettingsProvider.apk等,因此也可以认为SystemServer是一个特殊的应用进程。

对于上面提到的ActivityThread的成员变量,其用途基本上可以从名称中得知,这里仅说明一下ApplicationThread。

AMS负责管理和调度进程,因此AMS需要通过Binder机制和应用进程通信。
为此,Android提供了一个IApplicationThread接口,该接口定义了AMS和应用进程之间的交互函数。

如上图所示,ActivityThread作为应用进程的主线程代表,在其中持有ApplicationThread。ApplicationThread继承ApplicationThreadNative。
当AMS与应用进程通信时,ApplicationThread将作为Binder通信的服务端。

AMS与应用进程通信时,通过ApplicationThreadNative获取应用进程对应的ApplicationThreadProxy对象。
通过ApplicationThreadProxy对象,将调用信息通过Binder传递到ActivityThread中的ApplicationThread。
这个调用过程,今后还会遇到,碰到的时候再详细分析。

2、ActivityThread.attach
我们看看ActivityThread的attach函数:

//此时,我们传入的参数为true,表示该ActivityThread是系统进程的ActivityThread
private void attach(boolean system) {
    //创建出的ActivityThread保存在类的静态变量sCurrentActivityThread
    //AMS中的大量操作将会依赖于这个ActivityThread
    sCurrentActivityThread = this;
    mSystemThread = system;

    if (!system) {
        //应用进程的处理流程
        ..........
    } else { 
        //系统进程的处理流程,该情况只在SystemServer中处理

        // Don't set application object here -- if the system crashes,
        // we can't display an alert, we just want to die die die.
        //设置DDMS(Dalvik Debug Monitor Service)中看到的SystemServer进程的名称为“system_process”
        android.ddm.DdmHandleAppName.setAppName("system_process",
                UserHandle.myUserId());

        try {
            //创建ActivityThread中的重要成员:Instrumentation、Application和Context
            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);
        }
    }

    //以下系统进程和非系统进程均会执行
    ................
    //注册Configuration变化的回调通知
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            //当系统配置发生变化时(例如系统语言发生变化),回调该接口
            ...............
        }
        .............
    });
}

从上面的代码可以看出,对于系统进程而言,ActivityThread的attach函数最重要的工作就是创建了Instrumentation、Application和Context。

2.1 Instrumentation
Instrumentation是Android中的一个工具类,当该类被启用时,它将优先于应用中其它的类被初始化。
此时,系统先创建它,再通过它创建其它组件。

此外,系统和应用组件之间的交互也将通过Instrumentation来传递。
因此,Instrumentation就能监控系统和组件的交互情况了。

实际使用时,可以创建该类的派生类进行相应的操作。
这个类在介绍启动Activity的过程时还会碰到,此处不作展开。

2.2 Context
Context是Android中的一个抽象类,用于维护应用运行环境的全局信息。
通过Context可以访问应用的资源和类,甚至进行系统级的操作,例如启动Activity、发送广播等。

ActivityThread的attach函数中,通过下面的代码创建出系统应用对应的Context:

.......
//ContextImpl是Context的实现类
ContextImpl context = ContextImpl.createAppContext(
        this, getSystemContext().mPackageInfo);
.......

2.2.1 getSystemContext
我们先看看ActivityThread中getSystemContext的内容:

public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            //调用ContextImpl的静态函数createSystemContext
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}

进入ContextImpl的createSystemContext函数:

static ContextImpl createSystemContext(ActivityThread mainThread) {
    //创建LoadedApk类,代表一个加载到系统中的APK
    //注意此时的LoadedApk只是一个空壳
    //PKMS还没有启动,估无法得到有效的ApplicationInfo
    LoadedApk packageInfo = new LoadedApk(mainThread);

    //调用ContextImpl的构造函数
    ContextImpl context = new ContextImpl(null, mainThread,
            packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);

    //初始化资源信息
    context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
            context.mResourcesManager.getDisplayMetrics());
    return context;
}

可以看出createSystemContext的内容就是创建一个LoadedApk,然后初始化一个ContextImpl对象。
似乎没有什么特别的,那么为什么函数名被叫做create “System” Context?

为了回答这个问题,就要看看LoadedApk的构造函数了:

LoadedApk(ActivityThread activityThread) {
    mActivityThread = activityThread;
    mApplicationInfo = new ApplicationInfo();

    //packageName为"android"
    mApplicationInfo.packageName = "android";
    mPackageName = "android";
    //下面许多参数为null
    ................
}

注意到createSystemContext函数中,创建的LoadApk对应packageName为”android”,也就是framwork-res.apk。
由于该APK仅供SystemServer进程使用,因此创建的Context被定义为System Context。
现在该LoadedApk还没有得到framwork-res.apk实际的信息。

当PKMS启动,完成对应的解析后,AMS将重新设置这个LoadedApk。

2.2.2 ContextImpl.createAppContext

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    return new ContextImpl(null, mainThread,
            packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
}

相对而言,createAppContext的内容就比较简单了,就是利用ActivityThread和LoadedApk构造出ContextImpl。
ContextImpl的构造函数主要是完成一些变量的初始化,建立起ContextImpl与ActivityThread、LoadedApk、ContentResolver之间的关系。
代码简单但是冗长,此处不做展开。

2.3 Application
Android中Application类用于保存应用的全局状态。

我们经常使用的Activity和Service均必须和具体的Application绑定在一起。
通过上图的继承关系,每个具体的Activity和Service均被加入到Android运行环境中。

在ActivityThread中,针对系统进程,通过下面的代码创建了初始的Application:

..............
//调用LoadedApk的makeApplication函数
mInitialApplication = context.mPackageInfo.makeApplication(true, null);

//启动Application
mInitialApplication.onCreate();
.............. 

我们看一下LoadedApk.makeApplication:

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }
    .............
    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        //系统进程中,对应下面的appClass
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            ............
        }

        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        //实际上最后通过反射创建出Application
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ..........
    }

    //一个进程支持多个Application,mAllApplications用于保存该进程中的Application对象
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    ..............
}

从上面的代码不难看出,这部分主要是创建framework-res.apk对应的Application,然后调用它的onCreate函数,完成启动。

总结
至此,createSystemContext函数介绍完毕。

当SystemServer调用createSystemContext完毕后:
1、得到了一个ActivityThread对象,它代表当前进程 (此时为系统进程) 的主线程;
2、得到了一个Context对象,对于SystemServer而言,它包含的Application运行环境与framework-res.apk有关。

在继续分析AMS之前,我们先停下来思考一下,为什么在启动所有的服务前,SystemServer先要调用createSystemContext?

个人觉得《深入理解Android》对这个问题,解释的比较好,大致意思如下:
Android努力构筑了一个自己的运行环境。
在这个环境中,进程的概念被模糊化了。组件的运行及它们之间的交互均在该环境中实现。

createSystemContext函数就是为SystemServer进程搭建一个和应用进程一样的Android运行环境。

Android运行环境是构建在进程之上的,应用程序一般只和Android运行环境交互。
基于同样的道理,SystemServer进程希望它内部运行的应用,
也通过Android运行环境交互,因此才调用了createSystemContext函数。

创建Android运行环境时,
由于SystemServer的特殊性,调用了ActivityThread.systemMain函数;
对于普通的应用程序,将在自己的主线程中调用ActivityThread.main函数。

上图表示了进程的Android运行环境涉及的主要类之间的关系。
其中的核心类是ContextImpl,通过它可以得到ContentResolver、系统资源、应用信息等。

三、AMS初始化
创建完Android运行环境后,SystemServer调用startBootstrapServices,其中就创建并启动了AMS:

private void startBootstrapServices() {
    Installer installer = mSystemServiceManager.startService(Installer.class);

    // Activity manager runs the show.
    //启动AMS,然后获取AMS保存到变量中
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService()
  • 11
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值