Android的AMS相关知识

2024-01-08 22:59
文章标签 android 知识 相关 ams

本文主要是介绍Android的AMS相关知识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android7.0的AMS相关信息

  ActivityManager是一个和AMS相关联的类,它主要对运行中的Activity进行管理,这些管理工作并不是由ActivityManager来处理的,而是交由AMS来处理的。ActivityManager中的方法会通过ActivityManagerNative(AMN)的getDefault方法来得到ActivityManagerProxy(AMP),通过AMP就可以和AMN进行通信,而AMN是一个抽象类,它将功能交由它的子类AMS来处理,因此AMP就是AMS的代理类,AMS作为系统服务,很多API是不会暴露给ActivityManager的。
  在Activity的启动过程中,会调用Instrumentation的execStartActivity放,此方法中会调用AMN的getDefault来获取AMS的代理类AMP,接着调用AMP的startActivity方法。在getDefault方法中调用了gDefault的get方法,gDefault是一个Singleton类,先获取名为“activity”的Service引用,也就是IBinder类型的AMS的引用,接着将它封装成AMP类型对象,并将它保存到gDefault中,此后调用AMN的getDefault方法就会直接返回AMS的代理对象AMP。
  在asInterface方法中,descriptor值为android.app.IActivityManager类型,queryLocalInterface主要用来查询本地进程是否又IActivityManager接口的实现,有则返回,没有就将IBinder类型的AMS引用封装成AMP。在AMP的构造方法中将AMS的引用赋值给变量mRemote,这样在AMP中就可以使用AMS了。
  其中IActivityManager是一个接口,AMN和AMP都实现了这个接口,用于实现代理模式和Binder通信。AMP是AMN的内部类,在AMP的startActivity方法中,首先将传入的参数写入到Parcel类型的data中,通过IBinder类型对象mRemote(AMS的引用)向服务端的AMS发送了一个START_ACTIVITY_TRANSACTION类型的进程间通信请求,服务端的AMS就会从Binder线程池中读取客户端发来的数据,最终会调用AMN的onTransact方法,此方法会调用AMS的startActivity方法,最终调用startActivityAsUser,返回ActivityStarter的startActivityMayWait方法。
  AMP是AMN的内部类,它们都实现了IActivityManager接口,这样它们就可以实现代理模式,具体来讲是远程代理:AMP和AMN是运行在两个进程中的,AMP是client端,AMN是Server端,而Server端中具体的功能是由AMN的子类AMS来实现的,因此AMP就是AMS在client端的代理类。AMN又实现了Binder类,这样AMP和AMS就可以通过Binder来进行进程间通信。ActivityManager通过AMN的getDefault方法得到AMP,通过AMP就可以和AMS进行通信。

Android8.0的AMS相关信息

  Android8.0的AMS相关类与Android7.0的有一些差别,在Activity的启动过程中,会调用Instrumentation的execStartActivity方法,接着调用ActivityManager.getService方法,getService方法调用了IActivityManagerSingleton的get方法,IActivityManagerSingleton是一个Singleton类。先得到名为“activity”的Service引用,也就是IBinder类型的AMS应用,接着将它转换为IActivityManager类型的对象,采用的是AIDL,IActivityManager类是由AIDL工具在编译时自动生成的,IActivityManager.aidl的文件路径为frameworks/base/core/java/android/app/IActivityManager.aidl。要实现进程间通信,服务端也就是AMS只需要继承IActivityManager.Stub类并实现相应的方法就可以。采用AIDL后就不需要使用AMS的代理类AMP了。因此Android8.0去掉了AMP,代替它的是IActivityManager,它是AMS的本地代理。
  Android8.0的AMS相关类要简单的多,ActivityManager的getService方法会得到IActivityManager,AMS只需要继承IActivityManager.Stub类,就可以和ActivityManager实现进程间通信了。

AMS的启动过程

  AMS的启动是在SystemServer进程中启动的,从SystemServer的main方法开始,main方法只调用了SystemServer的run方法,先创建消息Looper,然后加载动态库libandroid_server.so。创建系统的Context,创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理,接着调用startBootstrapServices方法,用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务,然后调用startCoreServices方法启动了DropBoxManagerService、BatteryService、UsageStatsService和WebViewUpdateService。调用startOtherServices方法启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类均为SystemService。官方把系统服务分为了三种类型,分别是引导服务、核心服务、其他服务。
  在startBootstrapServices方法中,调用了SystemServiceManager的startService方法,该方法参数为ActivityManagerService.Lifecycle.class。在startService中将service对象添加到ArrayList类型的mServices中来完成注册。然后调用service的onStart方法来启动Service对象。Lifecycle是AMS的内部类,在Lifecycle的构造方法中,创建了AMS实例,当调用了SystemService类型的service的onStart方法时,实际上是调用了AMS的start方法,Lifecycle的getService方法返回了AMS实例。这样在SystemServer的startBootstrapServices方法中mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService实际得到的就是AMS实例。

AMS与应用程序

  Zygote的Java框架层中,会创建一个Server端的Socket,这个Socket用来等待AMS请求Zygote来创建新的应用程序进程。要启动一个应用程序,首先要保证这个应用程序所需要的进程已经存在。在启动应用程序时AMS会检查这个应用程序需要的进程是否存在,不存在就会请求Zygote进程创建需要的应用程序进程。已Service为例,Service在启动过程中会调用ActivityServices的bringUpServiceLocked方法,先得到ServiceRecord的processName的值并赋值给procName,其中processName用来描述Service想要在哪个进程运行,默认是当前进程,也可以在AndroidManifest文件中设置android:process属性来新开启一个进程运行Service。将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来描述运行的应用程序进程的信息。如果Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用AMS的startProcessLocked方法来创建对应的应用程序进程;如果用来运行Service的应用程序进程存在,则调用realStartServiceLocked方法来启动Service。
  AMS与应用程序进程的关系主要有以下两点:

  • 启动应用程序时AMS会检查这个应用程序需要的应用程序进程是否存在。
  • 如果需要的应用程序进程不存在,AMS就会请求Zygote进程创建需要的应用程序进程。
AMS重要的数据结构
解析ActivityRecord

  内部记录了Activity的所有信息,用来描述了一个Activity,在启动Activity时被创建的,具体时在ActivityStarter的startActivity方法中被创建的。
  ActivityRecord的重要成员变量:

名称类型说明
serviceActivityManagerServiceAMS的引用
infoActivityInfoActivity中代码和AndroidManifest设置的节点信息,比如launchMode
launchedFromPackageString启动Activity的包名
taskAffinityStringActivity希望归属的栈
taskTaskRecordActivityRecord所在的TaskRecord
appProcessRecordActivityRecord所在的应用程序进程
stateActivityState当前Activity的状态
iconintActivity的图标资源标识符
themeintActivity的主题资源标识符

  ActivityRecord的作用,其内部存储了Activity的所有信息,包括AMS的引用,AndroidManifest节点信息,Activity状态,Activity资源信息和Activity进程相关信息。

解析TaskRecord

  TaskRecord用来描述一个Activity任务栈

名称类型说明
taskIdint任务栈的唯一标识符
affinityString任务栈的倾向性
intentIntent启动这个任务栈的Intent
mActivitiesArrayList< ActivityRecord>按照历史顺序排列的Activity记录
mStackActivityStack当前归属的ActivityStack
mServiceActivityManagerServiceAMS的引用

  TaskRecord的作用,其内部存储了任务栈的所有信息,包括任务栈的唯一标识符、任务栈的倾向性、任务栈中的Activity记录和AMS的引用等。

解析ActivityStack

  ActivityStack是一个管理类,用来管理系统所有Activity,其内部维护了Activity的所有状态、特殊状态的Activity以及和Activity相关的列表数据。ActivityStack是由ActivityStackSupervisor来进行管理的,而ActivityStackSupervisor在AMS的构造方法中被创建,在createStackSupervisor方法中创建了ActivityStackSupervisor。

ActivityStack的实例类型

  在ActivityStackSupervisor中由多种ActivityStack,mHomeStack用来存储Launcher App的所有Activity,mFocusedStack表示当前正在接收输入或启动下一个Activity的所有Activity,mLastFocusedStack表示此前接收输入的所有Activity。通过ActivityStackSupervisor提供了获取上述ActivityStack的方法,比如要获取mFocusedStack,只需要调用ActivityStackSupervisor的getFocusedStack方法就可以了。

ActivityState

  再ActivityStack中通过枚举存储了Activity的所有状态。

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

  overridePendingTransition方法用于设置Activity的切换动画,可以看到只有ActivityState为RESUMED状态或者PAUSING状态时才会调用WMS类型的mWindowManager对象的overridePendingAppTransition方法来切换动画。

特殊状态的Activity

mPausingActivity: 正在暂停的Activity
mLastPausedActivity:上一个已暂停的Activity
mLastNoHistoryActivity:最近一次没有历史记录的Activity
mResumedActivity:已经resume的Activity
mLastStartedActivity:最近一次启动的Activity
mTranslucentActivityWaiting:传递给convertToTranslucent方法最上层的Activity

维护的ArrayList

  在ActivityState中维护了很多ArrayList

ArrayList元素类型说明
mTaskHistoryTaskRecord所有没有被销毁的Activity任务栈
mLRUActivitiesActivityRecord正在运行的Activity,列表中第一个条目时最近最少使用的Activity
mNoAnimActivitiesActivityRecord不考虑转换动画的Activity
mValidateAppTokensTaskGroup用于与窗口管理器验证应用令牌
Activity任务栈模型

Activity任务栈
  ActivityRecord用来记录一个Activity的所有信息,TaskRecord中包含了一个或多个ActivityRecord,TaskRecord用来表示Activity的任务栈,用来管理栈中的ActivityRecord,ActivityStack又包含了一个或多个TaskRecord,它是TaskRecord的管理者。Activity栈管理就是建立在Activity任务栈模型上的,有了栈管理,可以对应用程序进行操作,应用可以服用自身应用中以及其他应用的Activity,节省了资源。

LaunchMode
  1. standard:默认模式,每次启动Activity都会创建一个新的Activity实例。
  2. singleTop:如果要启动的Activity已经在栈顶,则不会重新创建Activity,同时该Activity的onNewIntent方法会被调用;如果要启动的Activity不在栈顶,则会重新创建该Activity的实例。
  3. singleTask:如果要启动的Activity已经存在于它想要归属的栈中,那么不会创建该Activity实例,将栈中位于该Activity上的所有的Activity出栈,同时该Activity的onNewIntent方法会被调用。如果要启动的Activity不存在与它想要归属的栈中,并且该栈存在,则会重新创建该Activity的实例;如果要启动的Activity想要归属的栈不存在,则首先要创建一个新栈,然后创建该Activity实例并压入栈中。
  4. singleInstance:和singleTask基本类似,不同的是启动Activity时,首先要创建一个新栈,然后创建该Activity实例并压入新栈中,新栈只会存在这一个Activity实例。
Intent的FLAG

  在Intent中定义了很多FLAG,其中几个FLAG也可以设定Activity的启动方式。

  • FLAG_ACTIVITY_SINGLE_TOP:同singleTop效果一样
  • FLAG_ACTIVITY_NEW_TASK:同singleTask效果一样
  • FLAG_ACTIVITY_CLEAR_TOP:如果要启动的Activity已经存在于栈中,则将所有位于它上面的Activity出栈,singleTask默认具有此标记位的效果。
  • FLAG_ACTIVITY_NO_HISTORY:Activity一旦退出就不会存在于栈中,也可以在AndroidManifest.xml中设置Android:noHistory。
  • FLAG_ACTIVITY_MULTIPLE_TASK:需要和FLAG_ACTIVITY_NEW_TASK一同使用才效果,系统会启动一个新的栈来容纳新启动的Activity。
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:Activity不会被放入到“最近启动的Activity”列表中。
  • FLAG_ACTIVITY_BROUGHT_TO_FRONT:这个标志位通常不是由应用程序中的代码设置的,而是LaunchMode为singleTask时,由系统自动加上的。
  • FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY:这个标志位通常不是由应用程序中的代码设置的,而是从历史记录启动的(长按Home键调出)Activity由系统添加的。
  • FLAG_ACTIVITY_CLEAR_TASK:需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,用于清除于启动的Activity相关栈的所有其他Activity。
      Activity启动时会调用AMS的startActivity方法,经过层层调用会调用ActivityStarter的startActivityUnchecked方法,setInitialState用于初始化启动Activity的各种配置,在初始化前会重置各种配置再进行配置,这些配置包括ActivityRecord、Intent、TaskRecord和LaunchFlags(Activity启动的FLAG)等。computeLaunchingTaskFlags方法用于计算出Activity启动的FLAG,并将计算的值赋值给mLaunchFlags,然后将mLaunchFlags设置给Intent,达到设定Activity的启动方式的目的。
      计算启动的FLAG的逻辑比较复杂,当TaskRecord类型的mInTask为null时,说明Activity要加入的栈不存在。ActivityRecord类型的mSourceRecord用于描述“初始Activity”,当mSourceRecord为null且FLAG_ACTIVITY_NEW_TASK时需要创建一个新栈,如果“初始Activity”所在的栈只允许有一个Activity实例,则也需要创建一个新栈;如果LaunchMode设置了singleTask或singleInstance则也要创建一个新栈。
taskAffinity

  可以在AndroidManifest.xml中设置android:taskAffinity,用来指定Activity希望归属的栈,在默认情况下,同一个应用程序的所有的Activity都有着相同的taskAffinity。

  1. taskAffinity于FLAG_ACTIVITY_NEW_TASK或者singleTask配合。如果新启动Activity的taskAffinity和栈的taskAffinity相同则加入到该栈中;如果不同,就会创建新栈。
  2. taskAffinity与allowTaskReparentingpeihe。如果allowTaskReparenting为true,说明Activity具有转移的能力。当社交应用启动发送邮件Activity,此时二者处于同一个栈中,且这个栈位于前台;如果发送邮件Activity的allowTaskReparenting为true,此后E-mail应用所在栈位于前台时,发送邮件的Activity就会由社交应用栈转移到邮件应用栈(taskAffinity相同)。taskAffinity对应的代码在ActivityStack的findTaskLocked中,遍历mTaskHistory列表,列表元素为TaskRecord,用于存储没有被销毁的栈,对每一个栈的信息,将栈的rootAffinity(初始的taskAffinity)和目标Activity的taskAffinity做对比,如果相同,则将FindTaskResult的matchByRootAffinity属性设置为true,说明找到了匹配的栈。

这篇关于Android的AMS相关知识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/585133

相关文章

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

log4j2相关配置说明以及${sys:catalina.home}应用

${sys:catalina.home} 等价于 System.getProperty("catalina.home") 就是Tomcat的根目录:  C:\apache-tomcat-7.0.77 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> 2017-08-10

Node Linux相关安装

下载经编译好的文件cd /optwget https://nodejs.org/dist/v10.15.3/node-v10.15.3-linux-x64.tar.gztar -xvf node-v10.15.3-linux-x64.tar.gzln -s /opt/node-v10.15.3-linux-x64/bin/npm /usr/local/bin/ln -s /opt/nod