ActivityManagerService的学习笔记

2017-09-13 20:36:47来源:CSDN作者:mingtiannihao623人点击

分享

参考地址:http://blog.csdn.net/innost/article/details/47254381

一、ActivityManagerService基本概述

ActivityManagerService(以后简称AMS)是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似。

这里写图片描述

  • AMS由ActivityManagerNative(以后简称AMN)类派生,并实现Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。而AMN由Binder派生,实现了IActivityManager接口。
  • 客户端使用ActivityManager类。由于AMS是系统核心服务,很多API不能开放供客户端使用,所以设计者没有让ActivityManager直接加入AMS家族。在ActivityManager类内部通过调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信。

二、ActivityManagerService被的调用轨迹

  • 1.SystemServer的ServerThread线程的 run() 方法调用ActivityManagerService.main 创建ActivityManagerServiceContext对象
  • 2.ActivityManagerService.setSystemProcess();//SystemServer进程可加 到AMS中,并被ActivityManagerService管理;
  • 3.ActivityManagerService.installSystemProviders();//将SettingsProvider放到SystemServer进程中来运行
  • 4.ActivityManagerService.self().setWindowManager(wm);//保存WindowManagerService(WMS)
  • 5.与WMS交互,弹出“启动进度“对话框;
  • 6.ActivityManagerService.self().systemReady;//启动启动systemUi,AMS是系统的核心,只有它准备好后,才能调用其他服务的systemReady

2.1 ActivityManagerService main分析

AMS的main函数将返回一个Context类型的对象,该对象在SystemServer中被其他服务大量使用,如获取该环境中的资源、Java类信息等;
在main函数中,我们又列出了4个关键函数:
1⃣️创建AThread线程;
2⃣️ActivityThread的systemMain函数;
3⃣️ ActivityThread.getSystemContext函数(System的上下文环境)
4⃣️AMS的startRunning函数

2.1.1 AThread分析
  • AThread线程
    AThread线程名就叫“ActivityManager”,将支持消息循环及处理功能,且创建AMS,然后通知AMS的main函数;
  • AMS的构造函数分析:
    • 创建BatteryStatsService(BSS)、UsageStatsService(USS)、mProcessStats (ProcessStats类型)、mProcessStatsThread线程,这些都与系统运行状况统计相关
    • 创建/data/system目录,为mCompatModePackages(CompatModePackages类型)和mConfiguration(Configuration类型)等成员变量赋值。
2.1.2调用ActivityThread的systemMain函数
public static final ActivityThread systemMain() {……   //创建一个ActivityThread对象,其构造函数非常简单  ActivityThread thread = new ActivityThread();  thread.attach(true);//调用它的attach函数,注意传递的参数为true   returnthread; }
  • ActivityThread是Android Framework中一个非常重要的类,它代表一个应用进程的主线程(对于应用进程来说,ActivityThread的main函数确实是由该进程的主线程执行),其职责就是调度及执行在该线程中运行的四大组件。
  • 注意应用进程指那些运行APK的进程,它们由Zygote 派生(fork)而来,上面运行了dalvik虚拟机。与应用进程相对的就是系统进程(包括Zygote和SystemServer);
  • apk文件在/data/app目录下,则为应用APK
(1)ActivityThread.java::systemMain调用thread.attach(true);
private void attach(boolean system) {    sThreadLocal.set(this);    mSystemThread= system;//判断是否为系统进程    if(!system) {        ......//应用进程的处理流程     } else {//系统进程的处理流程,该情况只在SystemServer中处理       //设置DDMS时看到的systemserver进程名为system_process       android.ddm.DdmHandleAppName.setAppName("system_process");       try {            //ActivityThread的几员大将出场,见后文的分析            **mInstrumentation** = new Instrumentation();            ContextImpl context = new ContextImpl();            //初始化context,注意第一个参数值为getSystemContext            context.init(**getSystemContext()**.mPackageInfo, null, this);            **Application** app = //利用Instrumentation创建一个Application对象                    Instrumentation.newApplication(Application.class,context);             //一个进程支持多个Application,mAllApplications用于保存该进程中            //的Application对象            mAllApplications.add(app);             mInitialApplication = app;//设置mInitialApplication            app.onCreate();//调用Application的onCreate函数           }......//try/catch结束      }//if(!system)判断结束     //注册Configuration变化的回调通知     ViewRootImpl.addConfigCallback(newComponentCallbacks2() {          publicvoid onConfigurationChanged(Configuration newConfig) {            ......//当系统配置发生变化(如语言切换等)时,需要调用该回调          }           public void onLowMemory() {}           public void onTrimMemory(int level) {}        }); }
  • 应用进程
  • 系统进程:SystemServer是一个特殊的应用进程
    设置DDMS时看到的systemserver进程名为system_process,创建Instrumentation类(传递系统和组件之间的交互)、Application类(保存了一个全局的application状态,可理解为一种容器,内部包含四大组件,一个进程可以运行多个Application。)及Context类
    这里写图片描述
2.1.3 ActivityThread中的getSystemContext函数分析
public ContextImpl getSystemContext() {  synchronized(this) {   if(mSystemContext == null) {//单例模式       ContextImplcontext =  ContextImpl.createSystemContext(this);       //LoadedApk是2.3引入的一个新类,代表一个加载到系统中的APK,“android”,其实就是framework-res.apk       LoadedApkinfo = new LoadedApk(this, "android", context, null,                       CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);       //初始化该ContextImpl对象      context.init(info, null, this);      //初始化资源信息      context.getResources().updateConfiguration(                        getConfiguration(),getDisplayMetricsLocked(                       CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));       mSystemContext = context;//保存这个特殊的ContextImpl对象      }   }    returnmSystemContext;}

systemMain函数将为SystemServer进程搭建一个和应用进程一样的Android运行环境。
SystemServer希望它内部的那些Service也通过Android运行环境交互,因此也需为它创建一个运行环境。由于SystemServer的特殊性,此处调用了systemMain函数,而普通的应用进程将在主线程中调用ActivityThread的main函数来创建Android运行环境。
ActivityThread虽然本意是代表进程的主线程,但是作为一个Java类,它的实例到底由什么线程创建,不是ActivityThread自己能做主的,所以在SystemServer中可以发现,ActivityThread对象由其他线程创建,而在应用进程中,ActivityThread将由主线程来创建。
这里写图片描述
* Instrumentaion是一个工具类。当它被启用时,系统先创建它,再通过它来创建其他组件。另外,系统和组件之间的交互也将通过Instrumentation来传递
* Application类保存了一个全局的application状态。
* Context是一个接口,通过它可以获取并操作Application对应的资源、类,甚至包含于Application中的四大组件。

2.1.4 AMS的startRunning函数分析
public final void startRunning(String pkg, Stringcls, String action,                                    String data) {  synchronized(this) {     if (mStartRunning) return;  //如果已经调用过该函数,则直接返回    mStartRunning = true;     //mTopComponent最终赋值为null    mTopComponent = pkg != null && cls != null                   ? new ComponentName(pkg, cls) : null;    mTopAction = action != null ? action : Intent.ACTION_MAIN;    mTopData = data; //mTopData最终为null     if(!mSystemReady) return; //此时mSystemReady为false,所以直接返回    }   systemReady(null);//这个函数很重要,可惜不在本次startRunning中调用}
2.1.5 ActivityManagerService的main函数总结

AMS的main函数的目的有两个:
· 首先也是最容易想到的目的是创建AMS对象。
· 另外一个目的比较隐晦,但是非常重要,那就是创建一个供SystemServer进程使用的Android运行环境。
· ActivityThread中有一个mLooper成员,它代表一个消息循环
· 对于ContextImpl,其成员变量表明它和资源、APK文件有关。

2.2 AMS的setSystemProcess分析

public static void setSystemProcess() {  try {      ActivityManagerService m = mSelf;       //向ServiceManager注册几个服务       ServiceManager.addService("activity",m);       //用于打印内存信息      ServiceManager.addService("meminfo", new MemBinder(m));       /*        Android4.0新增的,用于打印应用进程使用硬件显示加速方面的信息(Applications         Graphics Acceleration Info)。读者通过adb shell dumpsys gfxinfo看看具体的         输出       */      ServiceManager.addService("gfxinfo", new GraphicsBinder(m));        if(MONITOR_CPU_USAGE)//该值默认为true,添加cpuinfo服务            ServiceManager.addService("cpuinfo", new CpuBinder(m));        //向SM注册权限管理服务PermissionController       ServiceManager.addService("permission", newPermissionController(m));      /*    重要说明:        向PackageManagerService查询package名为"android"的ApplicationInfo。        注意这句调用:虽然PKMS和AMS同属一个进程,但是二者交互仍然借助Context。        其实,此处完全可以直接调用PKMS的函数。为什么要费如此周折呢        AMS将通过Binder发送请求给PKMS来完成查询功能,Android希望SystemServer中的服务也通过Android运行环境来交互。这更多是从设计上来考虑的,比如组件之间交互接口的统一及未来系统的可扩展性。      */      ApplicationInfo info = //使用AMS的mContext对象               mSelf.mContext.getPackageManager().getApplicationInfo(                        "android",STOCK_PM_FLAGS);          //①调用ActivityThread的installSystemApplicationInfo函数            mSystemThread.**installSystemApplicationInfo**(info);           synchronized (mSelf) {               //②此处涉及AMS对进程的管理,见下文分析               **ProcessRecord** app = mSelf.newProcessRecordLocked(                       mSystemThread.getApplicationThread(), info,                        info.processName);//注意,最后一个参数为字符串,值为“system”               app.persistent = true;               app.pid = MY_PID;               app.maxAdj = ProcessList.SYSTEM_ADJ;               //③保存该ProcessRecord对象               mSelf.mProcessNames.put(app.processName, app.info.uid, app);               synchronized (mSelf.mPidsSelfLocked) {                   mSelf.mPidsSelfLocked.put(app.pid, app);               }               //根据系统当前状态,调整进程的调度优先级和OOM_Adj,后续将详细分析该函数                mSelf.updateLruProcessLocked(app, true,true);           }        } ......//抛异常    }
2.2.1 ActivityThread的installSystemApplicationInfo函数分析
public voidinstallSystemApplicationInfo(ApplicationInfo info) { synchronized (this) {   //返回的ContextImpl对象即之前在AMS的main函数一节中创建的那个对象   ContextImpl context = getSystemContext();    //又调用init初始化该Context,是不是重复调用init了?   context.init(new LoadedApk(this, "android", context, info,              CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);     //创建一个Profiler对象,用于性能统计     mProfiler = new Profiler();     } }

· 第一次执行init时,在LoadedApk构造函数中第四个表示ApplicationInfo的参数为null。
· 第二次执行init时,LoadedApk构造函数的第四个参数不为空,即该参数将真正指向一个实际的ApplicationInfo,该ApplicationInfo来源于framework-res.apk。
基于上面的信息,某些读者可能马上能想到:Context第一次执行init的目的仅仅是为了创建一个Android运行环境,而该Context并没有和实际的ApplicationInfo绑定。而第二次执行init前,先利用Context和PKMS交互得到一个实际的ApplicationInfo,然后再通过init将此Context和ApplicationInfo绑定。因为framework-res.apk(包括后面将介绍的SettingsProvider.apk)运行在SystemServer中。和其他所有apk一样,它的运行需要一个正确初始化的Android运行环境。

由于framework-res.apk是一个APK文件,和其他APK文件一样,它应该运行在一个进程中。而AMS是专门用于进程管理和调度的,所以运行APK的进程应该在AMS中有对应的管理结构。因此AMS下一步工作就是将这个运行环境和一个进程管理结构对应起来并交由AMS统一管理。
AMS中的进程管理结构是ProcessRecord。

2.2.2 关于ProcessRecord和IApplicationThread的介绍

AMS启动一个位于其他进程的Activity,由于该Activity运行在另外一进程中,因此AMS势必要和该进程进行跨进程通信。答案自然是通过Binder进行通信。
Android提供了一个IApplicationThread接口,该接口定义了AMS和应用进程之间的交互函数
这里写图片描述

AMS通过它可以和应用进程进行交互,例如,AMS启动一个Activity的时候会调用该接口的scheduleLaunchActivity函数。
IApplicationThread的Binder服务端在应用进程中,因为AMS需要监听应用进程的死亡通知。

public final void scheduleStopActivity(IBindertoken, boolean showWindow,                                     intconfigChanges) {  queueOrSendMessage(//该函数内部将给一个Handler发送对应的消息               showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,               token, 0, configChanges); }

IApplicationThread仅仅是AMS和另外一个进程交互的接口,除此之外,AMS还需要更多的有关该进程的信息。在AMS中,进程的信息都保存在ProcessRecord数据结构中。那么,ProcessRecord是什么呢?先来看setSystemProcess的第二个关键点,即newProcessRecordLocked函数,其代码如下:
[–>ActivityManagerService.java::newProcessRecordLocked]

final ProcessRecordnewProcessRecordLocked(IApplicationThread thread,                ApplicationInfo info, String customProcess) {   Stringproc = customProcess != null ? customProcess : info.processName;  BatteryStatsImpl.Uid.Proc ps = null;  BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();  synchronized (stats) {        //BSImpl将为该进程创建一个耗电量统计项        ps =stats.getProcessStatsLocked(info.uid, proc);   }   //创建一个ProcessRecord对象,用于和其他进程通信的thread作为第一个参数   returnnew ProcessRecord(ps, thread, info, proc); }

2.3 AMS的installSystemProviders函数分析

2.4 ASM的systemReady分析

三、startActivity分析

3.1 am 脚本

3.2 AMS的startActivityAndWait函数分析

3.3 startActivityLocked分析

四、Broadcast和BroadcastReceiver分析

4.1 registerReceiver流程分析

4.2 sendBroadcast流程分析

4.3 BROADCAST_INTENT_MSG消息处理函数

4.4 应用进程处理广播分析

五、startService

5.1 Service知识介绍

5.2 startService流程图

六、AMS中的进程管理

6.1 Linux进程管理介绍

6.2 关于Android中的进程管理的介绍

6.3 AMS进程管理函数分析

七、App的 Crash处理

7.1 应用进程的Crash处理

7.2 AMS的handleApplicationCrash分析

7.3 AppDeathRecipient binderDied分析

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台