转https://www.jianshu.com/p/17b2844b2a27

ActivityManagerService是Android提供了管理Activity运行状态的系统进程,其实大家别被名字迷惑了,AMS(接下来都称ActivityManagerService为AMS)其实也兼任管理其他组件运行状态。

一、AMS概述

1.1 AMS启动流程

init进程是Android系统中的初始化进程,init生成Zygote进程,Android中大多数应用进程和系统进程都是通过Zygote进程生成的。

AMS触发流程.jpg

  AMS这种系统级别的服务,一般都是在启动的时候触发,上面的流程详细地阐述了AMS的代码执行流程。由于本文并不是介绍Zygote的,所以这儿不作详细描述,可以参考一下我其他详述Zygote的文章。
  AMS启动时的代码:

SystemServer.java
private void startBootstrapServices() {
//......mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);
//......mActivityManagerService.setSystemProcess();
//......
}

其中获取AMS的地方有一点改动,去掉了AMS中的main(...)方法,将其中的工作移到AMS构造函数中。

ActivityManagerService.java
public static final class Lifecycle extends SystemService {private final ActivityManagerService mService;public Lifecycle(Context context) {super(context);mService = new ActivityManagerService(context);}@Overridepublic void onStart() {mService.start();}@Overridepublic void onCleanupUser(int userId) {mService.mBatteryStatsService.onCleanupUser(userId);}public ActivityManagerService getService() {return mService;}}

1.2 AMS初始化工作

从上面AMS启动流程来看,AMS在在setSystemProcess()中注册的,注册的函数就是ServiceManager. addService(Context.ACTIVITY_SERVICE, this, true);从代码中看出来,AMS是一个实名的binder server,并且在AMS还注册了很多其他的服务,例如meminfo(这是内存使用情况的server)、cpuinfo(这是CPU使用情况的server)等等,这些服务在AMS中注册启用,说明这些服务会和AMS有很多交互。

ActivityManagerService.java
public void setSystemProcess() {
//......ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);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));}ServiceManager.addService("permission", new PermissionController(this));ServiceManager.addService("processinfo", new ProcessInfoService(this));
//......
}

  我们查看一下AMS的构造做了什么事情,从代码中分段讲解AMS构造中要做的事情。

ActivityManagerService.java
public ActivityManagerService(Context systemContext) {
//......
//step1:mSystemThread = ActivityThread.currentActivityThread();mUiContext = mSystemThread.getSystemUiContext();mPermissionReviewRequired = mContext.getResources().getBoolean(com.android.internal.R.bool.config_permissionReviewRequired);mHandlerThread = new ServiceThread(TAG,THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);mHandlerThread.start();mHandler = new MainHandler(mHandlerThread.getLooper());mUiHandler = mInjector.getUiHandler(this);mConstants = new ActivityManagerConstants(this, mHandler);
//......
//step2: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;
//step3:mServices = new ActiveServices(this);mProviderMap = new ProviderMap(this);mAppErrors = new AppErrors(mUiContext, this);//step4:// TODO: Move creation of battery stats service outside of activity manager service.File dataDir = Environment.getDataDirectory();File systemDir = new File(dataDir, "system");systemDir.mkdirs();mBatteryStatsService = new BatteryStatsService(systemContext, 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 = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null,new IAppOpsCallback.Stub() {@Override public void opChanged(int op, int uid, String packageName) {if (op == AppOpsManager.OP_RUN_IN_BACKGROUND && packageName != null) {if (mAppOpsService.checkOperation(op, uid, packageName)!= AppOpsManager.MODE_ALLOWED) {runInBackgroundDisabled(uid);}}}});mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));mUserController = new UserController(this);mVrController = new VrController(this);GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",ConfigurationInfo.GL_ES_VERSION_UNDEFINED);if (SystemProperties.getInt("sys.use_fifo_ui", 0) != 0) {mUseFifoUiScheduling = true;}
//......
//step5:mStackSupervisor = createStackSupervisor();mStackSupervisor.onConfigurationChanged(mTempConfig);mKeyguardController = mStackSupervisor.mKeyguardController;mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);mTaskChangeNotificationController =new TaskChangeNotificationController(this, mStackSupervisor, mHandler);mActivityStarter = new ActivityStarter(this, mStackSupervisor);mRecentTasks = new RecentTasks(this, mStackSupervisor);//step6:mProcessCpuThread = new Thread("CpuTracker") {@Overridepublic void run() {synchronized (mProcessCpuTracker) {mProcessCpuInitLatch.countDown();mProcessCpuTracker.init();}while (true) {try {try {synchronized(this) {final long now = SystemClock.uptimeMillis();long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;//Slog.i(TAG, "Cpu delay=" + nextCpuDelay//        + ", write delay=" + nextWriteDelay);if (nextWriteDelay < nextCpuDelay) {nextCpuDelay = nextWriteDelay;}if (nextCpuDelay > 0) {mProcessCpuMutexFree.set(true);this.wait(nextCpuDelay);}}} catch (InterruptedException e) {}updateCpuStatsNow();} catch (Exception e) {Slog.e(TAG, "Unexpected exception collecting process stats", e);}}}};mHiddenApiBlacklist = new HiddenApiBlacklist(mHandler, mContext);Watchdog.getInstance().addMonitor(this);Watchdog.getInstance().addThread(mHandler);}

  通过分析上面的代码,将AMS的构造分为6个重要的步骤:
  1.初始化构造AMS要用到的一些context和handler,例如mUiContext和mUiHandler配合使用,用于处理和UI显示相关的工作,mHandler是AMS中定义的用于分发AMS相关信息的处理器。
  2.定义了容纳前台和后台的广播队列,这也说明了AMS不仅仅关注Activity,也负责其他组件状态的管理。
  3.管理Service和Provider的对象数组。
  4.初始化system下面需要的一系列文件目录。例如权限文件、进程状态信息文件等等。
  5.这儿比较重要了,几个重要的变量需要关注一下,ActivityStackSupervisor(管理ActivityStack的重要类,这里面记录着activity状态信息,是AMS中的核心类), ActivityStarter(这是activity启动的处理类,这里管理者activity启动中用到的intent信息和flag标识,也和stack和task有重要的联系,下面会重点阐述)。
  6.启动一个线程专门跟进cpu当前状态信息,AMS对当前cpu状态了如指掌,可以更加高效的安排其他工作。

二、Activity状态

2.1 Activity生命周期

  Android入门必学的就是Android的四大组件,我们开发第一个app的时候,都会用到Activity,对于Activity的生命周期,大家应该已经烂熟于心了。下面是Activity生命周期状态图。

Activity生命周期.jpg

  在这里我就不展开对生命周期的讨论了,这方面的文章还是很多的,我说一个比较重要的知识点吧,也是比较容易错的一个点,Android面试的时候,都会问这样一个问题:什么时候Activity对用户可见?这个问题相信大家都遇到过,之前看过的一些书都说是在执行onResume()的时候表明当前Activity已经可见了,这个回答可以说对,也可以说不对。因为执行onResume()的时候Activity确实可见了,但是只是这样回答不能让人满意,说明没有深入思考,也没有仔细查看源码。下面带大家看一下这一部分的源码:

ActivityThread.java
final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
//......// TODO Push resumeArgs into the activity for considerationr = performResumeActivity(token, clearHide, reason);if (r != null) {
//......boolean willBeVisible = !a.mStartedActivity;if (!willBeVisible) {try {willBeVisible = ActivityManager.getService().willActivityBeVisible(a.getActivityToken());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;
//......if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;wm.addView(decor, l);}
//......}// If the window has already been added, but during resume// we started another activity, then don't yet make the// window visible.} else if (!willBeVisible) {if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");r.hideForNow = true;}// Get rid of anything left hanging around.cleanUpPendingRemoveWindows(r, false /* force */);// The window is now visible if it has been added, we are not// simply finishing, and we are not starting another activity.if (!r.activity.mFinished && willBeVisible&& r.activity.mDecor != null && !r.hideForNow) {
//......if (r.activity.mVisibleFromClient) {r.activity.makeVisible();}}
//......}
//......}

  此函数是handleResumeActivity(...),从字面上看应该是和onResume相关,在此函数中有执行activity.makeVisible(),这个makeVisible就是当前Activity可见的执行函数,所以严格来讲,不能说onResume是让Activity可见的,这点关系要搞清楚。下面Activity处理流程中详细画出了当前的Activity状态的时序图,里面也写明了Activity可见的调用时机。
  Android生命周期都是在UI线程中运行的,所以在这里面执行的代码都不能有过分耗时的情况,否则会发生ANR等问题,这个需要平时开发的时候养成良好的习惯。Android的生命周期是系统给开发者提供的一个体现当前Activity所处状态的外在体现,掌握这些生命周期,不能仅仅停留在表面的认识上,还应该知道深层的调用规律和调用逻辑。

2.2 Activity状态管理

  Android是如何管理Activity状态的,我们平时在Android开发中用到的intent flags taskAffinity launchMode是如何管理的,一个Task包含一个或者多个Activity,一个Stack包含一个或者多个Task,这儿引入ActivityStack,还有ActivityStackSupervisor负责管理所有的Stack。那么Activity是如何创建并且如何管理的?

2.2.1 ActivityStack创建

ActivityStack创建过程.jpg

  从ActivityStack创建的过程中也能看出来,ActivityStackSupervisor是管理ActivityStack的重要类,操作ActivityStack,都通过ActivityStackSupervisor衍生一个接口来执行。

ActivityStackSupervisor.java
void setWindowManager(WindowManagerService wm) {synchronized (mService) {
//......mHomeStack = mFocusedStack = mLastFocusedStack =getStack(HOME_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
//......}}protected <T extends ActivityStack> T getStack(int stackId, boolean createStaticStackIfNeeded,boolean createOnTop) {final ActivityStack stack = mStacks.get(stackId);if (stack != null) {return (T) stack;}if (!createStaticStackIfNeeded || !StackId.isStaticStack(stackId)) {return null;}if (stackId == DOCKED_STACK_ID) {// Make sure recents stack exist when creating a dock stack as it normally need to be on// the other side of the docked stack and we make visibility decisions based on that.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, createOnTop);}return (T) createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);}ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);if (activityDisplay == null) {return null;}return createStack(stackId, activityDisplay, onTop);}ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) {switch (stackId) {case PINNED_STACK_ID:return new PinnedActivityStack(display, stackId, this, mRecentTasks, onTop);default:return new ActivityStack(display, stackId, this, mRecentTasks, onTop);}}

  初始化创建了mHomeStack(包含launcher app)、mFocusStack(接收当前即将启动的Activity)、mLastFocusedStack(接收上次启动的Activity),从代码中更好理解这些概念,下面ActivityStack分析会详细讨论这3个stack的调用时机。

2.2.1 ActivityStack概述

ActivityStack详细分析会在下一张讲解。本文只是简单介绍一下ActivityStack中常用的变量,这些变量对理解ActivityStack的功能有很大的帮助。
  1.定义ActivityState

ActivityStack.java
enum ActivityState {INITIALIZING,RESUMED,PAUSING,PAUSED,STOPPING,STOPPED,FINISHING,DESTROYING,DESTROYED}

  2.特殊状态下的Activity

ActivityStackActivityRecord mPausingActivity = null;ActivityRecord mLastPausedActivity = null;ActivityRecord mLastNoHistoryActivity = null;ActivityRecord mResumedActivity = null;

  mPausingActivity表示正在被暂停的Activity
  mLastPausedActivity 表示上一个被暂停的Activity
  mLastNoHistoryActivity 表示上一个设置为FLAG_ACTIVITY_NO_HISTORY的Activity
  mResumedActivity 表示当前处于恢复状态的Activity
  3.全局的ArrayList

ActivityStack.javaprivate final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();

  mTaskHistory 记录所有的Activity信息
  mLRUActivities 按照最近最少使用排序的Activity集合
  mNoAnimActivities 不考虑状态迁移动画的Activity集合

三、Activity处理流程

3.1 startActivity流程

  启动一个Activity之后经历的流程如图所示,这儿写明了回调各个流程的时机,其中包含这对Activity状态的处理,这一点非常重要,Android系统处理的Activity很多,我们准确指示当前Activity的状态,可以保证Activity调用的正确性。由于onPause()触发条件比较多,这边没有列出onPause()的回调流程,感兴趣的同学可以自己查看一下源码,学习一下具体的流程,但是Activity生命周期的核心要点都在onCreate() onStart() onResume()上面,其他的生命周期其实就是对Activity状态的维护。

Activity处理流程.jpg

应用程序的入口在什么地方?这也是面试中经常问到的问题,别告诉我你想回答是Activity.onCreate(...),那显然大错特错,所谓应用程序的入口,就是当前的应用程序所在的进程是什么时候被启动的,这才是关键。解答这个问题,不看源码,很难问答,如果只是对Activity生命周期有一个表象的认识,显然不太够。这里列出关键的地方,抛砖引玉。

ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {// Is this activity's application already running?ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);r.getStack().setLaunchTime(r);
//step1:if (app != null && app.thread != null) {try {if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0|| !"android".equals(r.info.packageName)) {// Don't add this if it is a platform component that is marked// to run in multiple processes, because this is actually// part of the framework so doesn't make sense to track as a// separate apk in the process.app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,mService.mProcessStats);}realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}// If a dead object exception was thrown -- fall through to// restart the application.}
//step2:mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);}

上面标注了step1和step2,从step1的判断来看if (app != null && app.thread != null),说明当前的Activity所在的进程存在的话,执行realStartActivityLocked(...),那么step2执行的条件显然就是当前Activity所在的进程不存在的情况了。继续看下去。

Activity启动入口.jpg

很显然,ActivityThread->main(...)才是应用程序真正的启动入口。仔细阅读源码能帮助我们什么?能帮助我们透过现象看本质。

ActivityManagerService架构剖析开篇相关推荐

  1. 【免费福利】零AI基础,如何搭建聊天机器人:技术架构剖析

    作为人工智能领域最为重要的技术,自然语言处理的应用在工业界无处不在.从网页公开数据的分析和抽取.情感分析.机器翻译.智能客服.问答系统到聊天机器人,它的重要性不言而喻. 今天我们来探讨一下自然语言处理 ...

  2. 重磅公开课推荐 | 如何搭建聊天机器人:技术架构剖析

    作为人工智能领域最为重要的技术,自然语言处理的应用在工业界无处不在.从网页公开数据的分析和抽取.情感分析.机器翻译.智能客服.问答系统到聊天机器人,它的重要性不言而喻. 在本次公开课中我们来探讨自然语 ...

  3. 青云SDN/NFV2.0架构剖析

    编者按:在ArchSummit北京2015大会上,来自青云的工程师陈海泉分享了<SDN/NFV 2.0架构剖析>的议题.对于青云来说,SDN/NFV2.0是一个新的突破.早在2013年,青 ...

  4. 网易云信自研大规模传输网核心系统架构剖析

    随着边缘计算及RTC技术的兴起,业务服务器的边缘化可以带来大量收益:一方面就近接入可以优化客户端上下行质量,另一方面边缘节点可以大幅降低带宽成本.但如何保证相隔千山万水的边缘服务器之间的网络传输质量成 ...

  5. 微信、QQ都在用的腾讯云EB级对象存储架构剖析

    背景:5月23-24日,以"焕启"为主题的腾讯"云+未来"峰会在广州召开,广东省各级政府机构领导.海内外业内学术专家.行业大咖及技术大牛等在现场共议云计算与数字 ...

  6. 第十二期:常用的几种大数据架构剖析

    常用的几种大数据架构剖析 随着大数据技术的发展,数据挖掘.数据探索等专有名词曝光度越来越高,但是在类似于Hadoop系列的大数据分析系统大行其道之前,数据分析工作已经经历了长足的发展,尤其是以BI系统 ...

  7. 《帝国时代》应用架构剖析

    <帝国时代>应用架构剖析 本人非游戏开发者,本人也没有做过任何游戏.调试过任何游戏代码.阅读过任何游戏代码.本次只是黑盒子从外围分析,做门外汉总结罢了.各位做游戏的朋友请勿多嘲笑,毕竟我不 ...

  8. 尖峰日96万订单,59校园狂欢节技术架构剖析

    59store是一家专注校园市场的互联网企业,以校园消费类O2O及金融作为核心业务,自成立以为每年都会举办一次59校园狂欢节,在2016年5月9号的59校园狂欢节创下了单日96万订单,近3500万交易 ...

  9. 大数据智慧出行开发第一周:智慧出行底层数据架构剖析纵览全局

    第一周:智慧出行底层数据架构剖析纵览全局 0.大数据环境前置准备 一.文档说明 为了统一我们的操作系统与软件环境,我们统一课前基本软件环境,实现全程学习当中的软件版本都是一致的 二.VmWare与li ...

最新文章

  1. 63.死锁和死锁的原因
  2. Linux 2.4调度系统分析--转
  3. jvm性能调优实战 - 46堆区OOM解析
  4. linux docker查看容器状态,Docker容器状态命令行工具——Ctop
  5. iOS 数据库操作(使用FMDB)
  6. ORACLE EBS FORM 二次开发常用小技巧
  7. HDOJ水题集合2:最短路(Dijkstra)
  8. 怎么配置宝塔linux环境,宝塔面板linux怎么安装
  9. DevOps技术学习路线图 初阶+中阶+高阶
  10. 安卓初级开发教程 ppt+视频+案例源码
  11. qt5.14(vc2015 x64位)的安装配置和vc2015上qobjectdefs的c2134和QColor的c2661编译问题解决
  12. 尚硅谷 模拟w3school首页导航条练习
  13. java spring pdf下载_Spring5高级编程(第5版)PDF 下载
  14. Lync 2013正式版评估及2013版独立客户端下载
  15. 自己用java写一个http和https代理服务器
  16. ArcGIS小知识(八)——坡降、流动方向、剖面线、弯曲系数、河系密度、补给长度比
  17. 挖掘Dark Sky Maps(热的要死后,疯传的一个气温地图网站)
  18. java-斗地主无界面有序版
  19. FPGA图像处理HLS实现RGB转灰度,提供HLS工程和vivado工程源码
  20. 相对熵(KL散度)计算过程

热门文章

  1. dnf修改服务器制裁24,DNF关于对非法第三方软件封号制裁的重申
  2. 京东方校园招聘项目总结
  3. Markdown文本目录生成、页内跳转(附详细示例)
  4. 数据库审计是什么意思?作用是什么?
  5. SmartTier、SmartQos
  6. spring源码分析03-spring依赖注入源码解析
  7. iptables icmp-host-prohibited引起的No route to host
  8. 在寒冬“激流勇进”的BlockTower与其它基金有何不同?
  9. python自然语言处理-学习笔记(一)之nltk入门
  10. 7亿美元,京东上市前的最后一块踏板?