`
一夕剑
  • 浏览: 55237 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Android源码学习之六——ActivityManager框架解析

 
阅读更多

ActivityManager在操作系统中有重要的作用,本文利用操作系统源码,逐步理清ActivityManager的框架,并从静态类结构图和动态序列图两个角度分别进行剖析,从而帮助开发人员加强对系统框架及进程通信机制的理解。

ActivityManager的作用

参照SDK的说明,可见ActivityManager的功能是与系统中所有运行着的Activity交互提供了接口,主要的接口围绕着运行中的进程信息,任务信息,服务信息等。比如函数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;

}

}

从中可以看到,ActivityManager的大多数功能都是调用了ActivityManagerNative类接口来完成的,因此,我们寻迹来看ActivityManagerNative的代码,并以此揭示ActivityManager的整体框架。

ActivityManager的静态类图

通过源吗,可以发现ActivityManagerNative类的继承关系如下:

public abstract class ActivityManagerNative extends Binder implements IActivityManager

继承自Binder类,同时实现了IActivityManager接口。

同样的,我们继续沿Binder和IActivityManager上溯,整理出如下图所示的类结构图。

 

1.gif

 

在这张图中,绿色的部分是在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运行时的机制。

动态序列图

2.gif

 

我们以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机制的理解。从而为学习其他框架打下了基础。

总结

本文从静态类结构和动态类结构两个角度分析了ActivityManager的框架,兼顾了Binder机制和代理模式在进程间通信的机理,对帮助开发人员深化操作系统的结构和框架具有一定的指导作用。

 

转载自:http://www.apkbus.com/forum.php?mod=viewthread&tid=1155&extra

分享到:
评论

相关推荐

    android api code学习之ActivityManager

    这篇博客"android api code学习之ActivityManager"可能深入解析了ActivityManager的工作原理以及如何通过API进行相关操作。下面将详细讨论ActivityManager的相关知识点。 1. **Activity生命周期管理**: - ...

    Activity_Manager框架解析

    本文详细解析了Android中`ActivityManager`框架的功能、接口以及其实现机制。通过理解这些关键概念和技术细节,开发者能够更好地掌握如何管理和监控应用程序的生命周期,进而优化应用性能,提升用户体验。

    安卓Android源码——源代码分析.zip

    这部分源码解析会解释如何实现硬件兼容性和性能优化。 3. **System Server**:Android系统的守护进程,负责启动并管理Android系统服务,如窗口管理器、包管理器、活动管理器等。源代码分析将揭示其工作流程和事件...

    安卓Android源码——Chalmers.zip

    本篇文章将围绕“安卓Android源码——Chalmers.zip”这一主题,深入探讨Android系统的内核、框架层以及应用层的源码,揭示Chalmers项目的精髓。 一、Android系统结构概览 Android系统主要由四个层次组成:Linux...

    安卓Android源码——一键锁屏功能源码.rar

    "安卓Android源码——一键锁屏功能源码.rar" 是一个压缩包,包含了一个实现一键锁屏功能的示例代码。这个资源可能对那些想要学习如何在Android系统上快速实现设备锁定功能的开发者特别有用。下面我们将详细探讨这一...

    安卓Android源码——(截屏).rar

    Android系统作为全球最受欢迎的智能手机操作系统之一,其源码的开放性为开发者提供了深入了解和定制系统的可能性。"安卓Android源码——(截屏).rar"这个压缩包很可能包含了与Android系统中截图功能相关的源代码,...

    安卓Android源码——MonitorPhone.rar

    《安卓Android源码——MonitorPhone详解》 在深入探讨安卓Android源码——MonitorPhone之前,首先需要理解Android系统的基本架构。Android是一个开源的操作系统,基于Linux内核,为移动设备如智能手机和平板电脑...

    安卓Android源码——Jewels.zip

    10. **动画系统**:Android的动画系统包括属性动画、视图动画等,源码解析能帮助我们实现更流畅、复杂的动画效果。 以上只是对Android源码一部分内容的概述,实际的"Jewels.zip"可能包含特定的示例或项目,涉及更多...

    安卓Android源码——获取系统程序信息.zip

    "安卓Android源码——获取系统程序信息.zip"这个压缩包很可能包含了用于解析和显示系统中安装的应用程序信息的相关代码。下面,我们将深入探讨这一主题,围绕Android源码、系统程序信息的获取以及可能涉及的技术细节...

    安卓Android源码——强行结束APP进程的方法.zip

    4. **源码解析**:在`ActivityManagerService`的`forceStopPackageLocked()`方法中,Android会遍历与包名关联的所有活动记录、服务记录,停止它们并清理相关资源。然后,如果当前进程不是系统进程,它会调用`Process...

    安卓Android源码——软件管理器.zip

    本资源“安卓Android源码——软件管理器.zip”包含的可能是一份关于安卓软件管理器的源代码实现,这为我们深入理解Android系统的内部工作原理提供了宝贵的资料。 软件管理器,通常被称为应用管理器或App Manager,...

    Android源码——仿Siri的中文语音助理源码.zip

    这个压缩包文件"Android源码——仿Siri的中文语音助理源码.zip"包含了实现这一功能所需的全部源代码,旨在帮助开发者理解和构建自己的智能语音助手应用。下面我们将详细探讨其中涉及的关键知识点。 首先,语音识别...

    安卓Android源码——任务管理器源码.zip

    这份“安卓Android源码——任务管理器源码.zip”包含的文件将帮助我们深入理解Android系统内部的任务调度机制。我们将探讨以下几个关键知识点: 1. **任务与活动(Tasks and Activities)**: 在Android中,任务是...

    安卓Android源码——返回键退出程序的两种方式.zip

    在安卓(Android)系统中,开发应用程序时,处理返回键以退出程序是常见的需求。本文将深入探讨两种主要的方法,帮助开发者理解并实现这一功能。 首先,我们要知道,Android应用程序通常由多个活动(Activity)组成...

    安卓Android源码——完全退出程序的方法.zip

    本压缩包文件“安卓Android源码——完全退出程序的方法.zip”可能包含了一个示例代码,展示了如何实现这一功能。下面我们将详细探讨在Android中完全退出程序的方法。 首先,理解Android的应用程序生命周期至关重要...

    android源码大全

    源码解析Intent的发送、接收过程,可理解其在不同组件间如何传递信息。 5. **Service管理**:Service是Android后台运行的服务,源码中可以了解Service的生命周期管理和启动、绑定过程,有助于优化服务的使用。 6. ...

Global site tag (gtag.js) - Google Analytics