Android Framwork 之AMS源码解析

AMS启动

  • 在 system_ server进 程 中 启 动SystemServer. java # startBootstrapServices ( )

  • 创 建 AMS实 例 对 象

  • 创 建 Andoid Runtime

  • ActivityThread和 Context对 象 setSystemProcess

  • 注 册 AMS、 meminfo、 cpuinfo等 服 务 到 ServiceManager; installSystemProviderss

  • 加 载SettingsProvider;

  • 启动SystemUIService,再调用一系列服务的systemReady()方法; 发布Binder服务

  • 在这里插入图片描述

3.2 AMS类图结构
在这里插入图片描述

在这张图中,绿色的部分是在SDK中开放给应用程序开发人员的接口,蓝色的部分是一个典型的Proxy模
层的服务实现,是真正的动作执行者。这里的一个核心思想是Proxy模式,我们接下来 对此模式加以介绍

Proxy模式

Proxy模式,也称代理模式,是经典设计模式中的一种结构型模式,其定义是为其他对象提供一种代理以控
问,简单的说就是在访问和被访问对象中间加上的一个间接层, 以隔离访问者和被访问 者的实现细节。

结合上面的类结构图,其中ActivityManager是一个客户端,为了隔离它与ActivityManagerService,有效降低甚至消除二者的耦合度,在这中间使用了ActivityManagerProxy代理类,所有对ActivityManagerService的访问都转换成对代理类的访问,这样ActivityManager就与ActivityManagerService解耦了。这就是代理模式的典型应用场景

为了让代理类与被代理类保持一致的接口,从而实现更加灵活的类结构,或者说完美的屏蔽实现细节,通常的作 法是让代理类与被代理类实现一个公共的接口,这样对调用者来说,无法知道被调用的是代理类还是直接是被代理 类, 因为二者的接口是相同的。

这个思路在上面的类结构图里也有落实,IActivityManager接口类就是起的这个作用。

以上就是代理模式的思路,有时我们也称代理类为本地代理 (Local Proxy) ,被代理类为远端代理 (Remote Proxy)

本地代理与远端代理的Binder 我们再来看一下Binder类的作用,Binder的含义可能译为粘合剂更为贴切,即将两侧的东西粘贴起来。在操作系统中,Binder的一大作用就是连接本地代理和远端代理。Binder中最重要的一个函 数是:

public final boolean transact( int code , Parcel data , Parcel reply ,
int flags) throws RemoteException {
……
boolean r = onTransact(code , data , reply , flags) ;
if (reply != null) {
reply .setDataPosition(0) ;
}
return r ;
}

它的作用就在于通过code来表示请求的命令标识,通过data和reply进行数据传递,只要远端代理能实现onTransact( )函数, 即可做出正确的动作,远端的执行接口被完全屏蔽了。

当然,Binder的实现还是很复杂的,不仅是类型转换,还要透过Binder驱动进入KERNEL层来完成进程通信,这 些内容不在本文的范围之内,故此处不再深入解析相应的机制。此处我们只要知道Binder的transact()函数实现就可 以了。

到此为止,我们对ActivityManager的静态类结构就分析完了,但这还不足以搞清在系统运行中的调用过程,因 此,我们以下图的序列图为基础,结合源码探索一下ActivityManager运行时的机制。
在这里插入图片描述

我 们 以 ActivityManager的 getRunningServices( ) 函 数为 例 , 对上 述 序 列图 进 行 解析 。

public List< RunningServiceInfo> getRunningServices( int maxNum)
throws SecurityException {
try {
return ( List< RunningServiceInfo> ) ActivityManagerNative . getDefault( )
.getServices(maxNum , 0) ;
} catch ( RemoteException e) {
/ / System dead , we will be dead too soon !
return null ;
}
}

可 以 看 到 , 调 用 被 委 托 到 了 ActivatyManagerNative. getDefault( ) 。

static public IActivityManager asInterface( IBinder obj)
{
……
return new ActivityManagerProxy( obj) ;
}
static public IActivityManager getDefault( )
{
……
IBinder b = ServiceManager . getService( " activity" ) ;
gDefault = asInterface( b) ;
return gDefault ;
}

从上述简化后的源码可以看到,getDefault()函数返回的是一个ActivityManagerProxy对象的引用,也就是说,
ActivityManager得 到 了一 个 本 地代 理 。
因 为在IActivityManager接口中已经定义了getServices() 函数,所以我们来看这个本地代理对该函数的实现。

public List getServices( int maxNum, int flags) throws RemoteException {
Parcel data = Parcel .obtain() ;
Parcel reply = Parcel .obtain() ;
……
mRemote .transact(GET_SERVICES_TRANSACTION , data , reply , 0) ;
……
}

从 这个 代码版 段我们 看到, 调用远 端代理 的transact( ) 函数 ,而这 个mRemote就是 ActivityManagerNative的
Binder接 口。

接下来我们看一下ActivityManagerNative的代码,因为该类是继承于Binder类的,所以transact的机制此前我 们已经展示了代码,对于该类而言,重要的是对onTransact()函数的实现。

public boolean onTransact( int code, Parcel data , Parcel reply , int flags)
throws RemoteException {
switch ( code) {
case GET_ SERVICES_ TRANSACTION : {
……
List list = getServices(maxNum , fl) ;
……
return true ;
}
……
}
return super .onTransact(code , data, reply , flags);
}

在onTrasact()函数内,虽然代码特别多,但就是一个switch语句,根据不同的code命令进行不同的处理,比如 对于

GET_ SERVICES_ TRANSACTION命 令, 只 是 调用 了 getServices( ) 函 数。 而 该 函数 的 实 现是 在 ActivityManagerService类 中, 它 是ActivityManagerNative的子类,对于该函数的实现细节,不在本文中详细分 析。Activity启动 在经过前文的学习以后,我们一起来整理一下Activity的启动机制。就从Activity的startActivity()函数开始吧。

startActivity( ) 函 数 调 用 了 startActivityForResult( ) 函 数 , 该 函 数 有 源 码 如 下 :

public void startActivityForResult( Intent intent , int requestCode) {
……
Instrumentation . ActivityResult ar =
mInstrumentation . execStartActivity(
this , mMainThread.getApplicationThread() , mToken , this ,
intent, requestCode) ;
……
}

可见,功能被委托给Instrumentation对象来执行了。这个类的功能是辅助Activity的监控和测试,在此我们不详 细描述,我们 来 看它 的 execStartActivity( ) 函 数。

public ActivityResult execStartActivity(
Context who , IBinder contextThread , IBinder token , Activity target,
Intent intent , int requestCode) {
……
try {
int result = ActivityManagerNative . getDefault( )
. startActivity( whoThread , intent,
intent . resolveTypeIfNeeded( who . getContentResolver( ) ) ,
null , 0 , token , target != null ? target.mEmbeddedID : null ,
requestCode , false , false);
checkStartActivityResult( result , intent) ;
} catch ( RemoteException e) {
}
return null;
}

在 这 个 函 数 里 , 我 们 看 到 了 前 文 熟 悉 的 ActivityManagerNative. getDefault( ) , 没 错 , 利 用 了 ActivityManagerService。

通过前文的线索,利用Proxy模式,我们可以透过ActivityManagerProxy,通过Binder的transact机制,找到真正的动作执行者,即ActivityManagerService类的startActivity() 函数,并沿此线索继续追踪源 码,在startActivityLocked() 函数里边看到了mWindowManager. setAppStartingWindow的 语 句 调 用 ,mWindowManager是 WindowManagerService对 象 , 用 于 负 责 界 面 上 的 具 体窗口调试。

通过这样的源码追踪,我们了解到了Activity启动的底层实现机制,也加深了对Proxy模式和Binder机制的理解。
真的不能更新UI吗?

Process : com .example.amsdemo , PID : 4855
android . view . ViewRootImpl$ CalledFromWrongThreadException : Only the original thread that
created a view hierarchy can touch its views.
at android .view .ViewRootImpl .checkThread(ViewRootImpl .java:6891)
at android .view.ViewRootImpl .requestLayout(ViewRootImpl .java:1048)
at android .view .View .requestLayout(View.java:19781)
at android .view.View .requestLayout(View .java:19781)
at android .view.View .requestLayout(View .java:19781)
at android .view.View .requestLayout(View .java:19781)
at android .view.View .requestLayout(View .java:19781)
at android .view.View .requestLayout(View .java:19781)
at android. support. constraint. ConstraintLayout. requestLayout( ConstraintLayout. java: 3 1 7 2 )
at android. view. View. requestLayout( View. java: 1 9 7 8 1 )
at android. widget. TextView. checkForRelayout( TextView. java: 7 3 6 8 ) at
android. widget. TextView. setText( TextView. java: 4 4 8 0 )
at android. widget. TextView. setText( TextView. java:4 3 3 7 ) at
android. widget. TextView. setText( TextView. java:4 3 1 2 )
at com. example. amsdemo. MainActivity$ 3 . run( MainActivity. java: 4 6 )
ViewRootImpl. java# checkThread ( ) L 68 8 9
- > #requestLayout() L 1046
-> # scheduleTraversals() L 12 2 2
- > # TraversalRunnable L 6 3 3 4
- > #doTraversal() L 1245
ActivityThread. java# handleResumeActivity ( ) L3 4 5 6
- > # performResumeActivity( ) L 3 3 8 5
Activity. java#performResume () L 6774
Instrumentation. java# callActivityOnResume ( ) L 1 2 6 7
// performResumeActivity方法确实是回调onResume方法的入口
ActivityThread. java# handleResumeActivity ( ) L 3 5 6 0
Activity. java# makeVisible () L 51 2 8
WindowManagerImpl. java# addView ( ) L 9 1
WindowManagerGlobal. java# addView ( ) L 2 6 3
- > addView() L 331

android中进程的层次如下 (重要性由高到低) :

1、前端进程。顾名思义,前端进程就是目前显示在屏幕上和用户交互的进程,在系统中前端进程数量很少,而 这种进程是对用 户 体验的影响最大,只有系统的内存稀少到不足以维持和用户的基本交互时才会销毁前端进程。因此 这种进程重要性是最高的。

2、可见进程。可见进程也拥有一个可视化的界面,只是目前不是最上层界面 (最上层界面在前端进程里面) , 可见进程一般调用了OnPause(),可见进程比前端进程重要性低,但是在交互方面影响还是很大,因为用户可能随时 切换过去,所以系统不会轻易销毁它。

3、服务进程。一个服务进程就是一个Service,它调用了startService(),就是UNIX中说的守护进程,对用户不 可见,但是保证了一些重要的事件被监听或者维持着某些状态,比如网络数据传输、后台音乐播放,这类进程在内存 不足且为了保证前端交互的顺利进行的时候被销毁。

4、后台进程。这里叫后台进程可能会和一般意义上的后台进程混淆,要说明的是,android里的后台进程是调
的,可以理解成用户暂时没有和这个进程交互的愿望,所以这里后台进程有点“待销毁”的意思。

5、空进程。这是一种系统缓存机制,其实就是个进程的外壳,当有新进程创建的时候,这个空进程可以加快进
当系统内存不足的时候,首先销毁空进程。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集
在这里插入图片描述
二、源码解析合集

在这里插入图片描述
三、开源框架合集

在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值