【Android源码 栏目提醒】:网学会员鉴于大家对Android源码 十分关注,论文会员在此为大家搜集整理了“安卓软件开发--Android手机开发 - 产品手册”一文,供大家参考学习
Android 手机开发(一) 导读:对于
Android 开发者来说,成系列的技术文章对他们的技术成长帮助最大。
如下是我们向您强烈推荐的主题为
Android 开发的第一个系列文章。
《
Android 核心分析》整理如下: 1. 方法论探讨之设计意图 为什么要研究
Android,是因为它够庞大,它够复杂,他激起了我作为一个程序员的内心的渴望,渴望理解这种复杂性。
我研究的对象是作为手机开发平台的
Android 软件系统部分,而不是 Dalvik 虚拟机本身。
作为一个从其他平台装接过来的程序员,要从事 Andoid 平台系统开发,我的关于手机平台上积累的知识已经不能满足需要了,
Android 为我们带来了大量的新名词,Activity,Manifest,INTENT,Service,Binder,Dalvik 虚拟机,Framework,Linux,Navtive ,JNI.....。
通过在源代码,在开发社区,在开发博客,甚至在招聘过程中,我不断的寻求
Android 是什么。
经过一定时间的沉淀,我慢慢的理解到
Android 不仅仅是一类手机的总称,不仅仅是一个手机开发平台,不仅仅是一个虚拟 java 操作系统,不仅仅是一个开发社区,一个开发标准,不仅仅是一堆代码,
Android 已经成了一个新的潮流。
代码多,系统复杂,纵观社区中
Android 的研究者,一开始从源代码分析
Android 就走向迷途,不断的跋山涉水,向纵深冲刺,最终脑袋堆栈不够用,迷失在开始的旅程,或者挂在半途中,鲜有通达者。
我感觉到大部分的研究者总是忘记站在高山上向下望一望设计者的意图,一味的随着代码的控制流走入繁杂的谜团,陷入到复杂性的深渊。
我的研究分析是从设计者的意图出发,从抽象的甚至从哲学的高度,从最简单的系统原型开始,从设计猜想开始,而不是一开始就从代码分析展开。
首先理解
Android 大的运行框架,主干流程,系统原型,之后再用源代码分析充实之。
当然我这里的设计者意图并不是真正的
Android 设计者意图,而是我以为的
Android 设计者意图。
要理解设计者意图,就需要抽象。
我们需要在哲学意义空间中去考虑系统的描述,即系统在本质上要表达什么。
在逻辑空间上去考虑系统基本构成和动态结构。
从现实到虚拟对象的映射去理解系统对象的组成,在从数据流的角度分析数据的产生者和消费者之间作用关系,从控制流的角度去分析对象之间的交互关系,从函数调用去分析具体的层次关系。
在系统设计上,原型是最能表达哲学空间和逻辑空间中系统本质的东西,原型是事物本质的第一层体现。
我以为任何复杂的系统都一个简洁的系统原型,都有它简洁的意义。
系统原型是设计者意图的第一体现,所以我们需要从几个方向上去提炼系统原型: (1)从系统本质和基本原理出发 (2)从分析系统数据流和控制流分析出发。
从设计者意图出发,得出系统原型,提取到大的逻辑结构和系统构成是第一步。
之后我们可以从设计者的角度考虑系统猜想系统设计,为什么要这样设计,为什么要有这些构成。
这样的基本原型是什么?系统的限制是什么,应用场景有哪些,有些设计的引进还是系统收敛性而为之呢。
我们还可以从代码痕迹上去分析,这些概念是如何的得来的?从一定的抽象和高度去理解这些问题,遵循系统原型出发之原则,在深入分析代码的时候,就不容易陷入细节中。
我们就可以随时跳出来想,这些代码在整体上载表达一个什么概念,在描绘一个什么逻辑,他要构成一个虚拟层吗?他是在管理这个硬件吗?他在 虚拟这个对象吗?他在构建管理机构?还是在构建一个对象管理?空间管理,为了快速引入了什么样的复杂算法,实际上的原型算法应该是什么样的? 只有深入到这个抽象层次,我们才能很好的把握住系统的每一条线,每一个对象的意义。
只用从原型出发,我们才能把握住这个系统的实质所在,在干什么?他要表达什么?设计者为什么要这样想?最终极的想法是什么?这样,代码分析就变得简单明了,读代码就变成了是在印证猜想,修正方向。
2. 方法论探讨之概念空间篇 我们潜意识就不想用计算机的方式来思考问题,我们有自己的思维描述方式,越是接近我们思维描述方式,我们越容易接受和使用。
各种计算机语言,建模工具,不外乎就是建立一个更接近人的思维方式的概念空间,再使用工具从该概念空间向另外一个概念空间映射,我称之为人性思维空间向 01 序列描述空间的一个映射。
实现方面来看,系统就是一个翻译器,将机器性更加人性化的一种机制。
大学计算机经典课“计算机体系结构”,其他的可以忘记,但是下面这个图不能忘记: 这个就是概念空间最本质的原型体现:作为观测者看到了什么?设计者给了观察者什么?给出的答案是外部特性。
(1)提供给观察者的概念空间是什么? (2)内部特性的概念空间是什么? 概念空间所表达的东西带有两个方面的缠绕:一面是人性自由,一面是物性制约(实时响应,系统资源的限制)。
所以程序实现的概念空间是人性自由与特定计算机系统物性之间有一个折中,并且根据实际系统而采取某种动态的平衡。
而这种平衡将会影响到系统架构,以及设计的思想。
特别在手机这样的嵌入式系统中,这种矛盾和平衡无处不在,这种折中无处不在。
而对系统的选取和采用,也就接受了某个方面的折中或某中即在的,也许是看不见的标准,及这样的标准有隐式和显式的。
正因为如此,不管是工具的产生,新的平台的产生, 都是计算机的物性向人性靠近的一个小台阶。
一个新的思想的形成随即带来的新工具,新系统框架,新的体系结构。
如果设计者站的高度足够高,那么设计者一开始就会考虑到“我该给他们一个什么样的概念空间,甚至一个什么样的理念,让他们这个概念空间去建立自己的产品”,于是设计者就会开始主动的去建立概念空间,这个概念空间要表达的实际意义,概念空间应该有哪些内容构成,考虑概念空间的完备性和封闭性,考虑概念空间的边界,考虑从哪个基础上建立这个概念空间,考虑如何与概念空间外的实体进行交互,考虑系统的资源限制条件,考虑功能性构建的合理性,考虑机器系统与人的平衡问题。
我们在学习新系统时,首先映入眼帘的就是新概念。
新名词,就如现在我们面临的
Android 大量的新名词,在程序员的世界都是从代码实践开始的,是从写应用开始去涉及。
SDK 给了我们一个概念,我们就在这个概念框架下,使用 SDK 给我提供的函数接口,数据结构,初始化过程等,我们最初的接触到原型就是“HelloWorld”之类的 DEMO 程序,我们在 Hello world 上去使用各种不同的接口函数,对于应用程序员来讲他说看到的系统就是系统调用接口,及其编程开发流程。
实际上只要一使用这些接口就不得不接受一系列的概念只有在这种概念系统下我们才能工作。
但是实际上我们却忽略了这样的概念系统的理解只是在编程接口的这个狭窄的空间去理解系统.我们理解系统在形成理解概念的空间只是微小的一角,很少有资料来介绍这种概念系统的形成和理解编程接口只是这个概念空间一个,对外部的一个表征。
我们可以抽象起来以接口协议和行为来描述系统的情况。
SDK API 的实质向上层提供了一个语义接口,从而在层间实现了一个转义过程,同时又成为一个功能的集合体。
但是我们很少这样跳出来看,我们到底是处于一种什么样的概念空间,SDK 除了调用接口外,还给了我们怎样一种整体概念?目标系统的基本构架在本质上的东西就是一个概念系统到另一个概念系统的映射。
让我们大脑理解的概念系统映射到计算机能实现的概念域的一个映射。
我们假定这个概念域 E机器能够理解的概念域为 M我们的软件工程要做的事情实质就是:EàM 领域的一个映射过程。
为什么要在宏观上把握这些概念呢,显然有我的目的,理解概念空间是理解设计者意图的一个重要途径。
设计者要想给开发者提供什么,设计者想要提供给最终用户什么。
我们需要站在高处看待系统明白设计者意图。
Android 的实质还是一套管理手机硬件系统的软件,这个话讲起来没有多大意义计算机操作系统本质都是如此,
Android是 Google 云计算计划的一部分,我们修正成:
Android 建立的本质就是让计算机成为我的云接入移动智能终端。
作为硬件管理软件,
Android 提供概念空间内涵实质上泛操作系统内涵,我们的理解可以从泛操作系统概念空间映射到
Android 系统中去。
而作为云计算的一部分的内容,我们可以云计算的概念入手去研究 Andoird。
3. 手机之硬件形态 本节可能与
Android 无关,但是
Android 系统现在这个阶段更多的是移动终端形态的开发平台,本节给出了
Android 背后的工作-
Android 管理的硬件是什么,
Android 的本质就是要管理好这些硬件部分,为用户提供一个体验更好,速度更快的智能移动终端。
对手机硬件形态的认识是要让我们对手机硬件组成有个感性的认识,让程序员知道系统中的代码是管理那一部分的,即我们堆砖头的目的是什么,让思维有一个伸展。
为了对手机这类嵌入式系统有一个较为深入的了解,我制作了如下的手机硬件结构思维导图,在这张图上我们可以看到组成手机硬件的有哪些,初步了解到手机管理平台为什么要那么多的管理框架和层次,从最底层理解
Android 设计者的设计意图,这个思维导图其实只是示意图。
我们知道手机这种嵌入式系统,硬件架构最简单描述的描述为: 应用处理器Modem射频 对于应用处理器而言,对设计者最为本质的描述为输入输出,而对于移动终端设备电源管理,连接机制,多媒体又是很重要的考虑环节,而这些环节都会在软件平台上有所体现。
4. 手机的软件形态 上节我给出了手机的硬件树,本节将给出手机软件形态树。
主要突出手机软件涵盖的内容。
通过该思维导图,我们可以看到手机软件所涉及到的方方面面,
Android 所涉及到的内容也不会超过下面所示太多,这个也是 Andoid 系统外特性空间所要展示的,这个也是
Android 设计者需要考虑管理的大部分内容,通过下面的整理,我们可以让我们的思维更加贴近
Android 设计意图,从而更深入的了解
Android 中各种组成的由来,这个就是前面讲到的分析思想之一从退到源头出发,从思考最终极的问题开始。
5.
Android 基本空间划分 Google 给了我们一张系统架构图,在这张图上我们可以看到
Android 的大体框架组成。
从上图可以看到:
Android ApplicationsApplication FrameworkDalvik Virtual MachineLinux。
如果将
Android 泛化,我们可以将系统划分成两部分: 但是为了研究的方便我们先看最为本质的三层,上面是
Android,中间叫 Dalvik 虚拟机,下面叫 Linux。
虽然上两层都包含在
Android 中,但是为了理解的方便或者从实用主义出发,我还是将虚拟机这次给分开出来,因为我研究的对象是
Android 的手机系统相关部分,对于虚拟机我们不做太深入的研究。
e: prequotgt 从上面我们可以看到这个系统静态的划分成这样的三层。
但是从动态运行逻辑上不是这样划分的,所以空间的划分是一个有趣的概念。
我们从操作系统的角度看,
Android 就是一堆 Linux 应用的集合。
从 Linux 角度看到的空间划分:进程空间和内核空间。
从
Android 的应用对应着 Linux 的一个个进程。
Andoid 中包含一个 Java 虚拟机,虚拟机是运行在 Linux 之上的,
Android 构建在 JVM 之上,从
Android 动态运行逻辑上我们需要将
Android 划分成
Android 空间和非
Android 空间。
在 Andoid 系统中我们面对的是 Andoid 概念空间,而不是 Linux 进程了,在 Andoid 概念空间中已经没有了 Lliux 进程的概念,而是 Service,proxy,Activity,provider 等。
至于虚拟机 JVM,我们只需要知道 JVM 是 Dalvik VM(虚拟机)这是一个专为嵌入式设备打造的JAVA虚拟机,是一个有着自己的 code-byte 和格式的可以在嵌入式设备上高效运行的 Java 虚拟机。
为了研究的深入,我们还是需要涉及到 JNI Native 部分。
在这个分类中我将 JVM 分为 JVM 空间和 C空间。
Android 应用的开发者是工作在
Android 外特性概念空间的,这里没有了 Linux 的一点气息,
Android 构建的外特性空间概念包含了:ActivityProviderInterfaceEventsProvider,Service 等。
至于 JVM 空间和 C空间的划分是为了研究
Android 核心的描述而提出的,我们在做
Android 系统开发时,常常需要修改到 JNI 的 Native 部分。
后面我将用较多的篇幅来深入阐述这个部分。
6. IPC 框架分析(Binder,Service,Service manager) 我首先从宏观的角度观察 BinderServiceService Manager,并阐述各自的概念。
从 Linux 的概念空间中,
Android 的设计Activity 托管在不同的的进程,Service 也都是托管在不同的进程,不同进程间的 ActivityService 之间要交换数据属于 IPC。
Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架。
在代码分析中,我发现
Android 中只是把 Binder 理解成进程间通讯的实现,有点狭隘,而是应该站在公共对象请求代理这个高度来理解 Binder,Service 的概念,这样我们就会看到不一样的格局,从这个高度来理解设计意图,我们才会对
Android 从中的一些天才想法感到惊奇。
Android 的外特性概念空间中,我们看不到进程的概念,而是 Activity,Service,AIDL,INTENT。
一般的如果我作为设计者,在我们的根深蒂固的想法中,这些都是如下的 C/S 架构,客户端和服务端直接通过 Binder 交互数据,打开 Binder 写入数据,通过 Binder 读取数据,通讯就可以完成了。
该注意到
Android 的概念中,Binder 是一个很低层的概念,上面一层根本都看不到 Binder,而是 Activity 跟一个 Service的对象直接通过方法调用,获取服务。
这个就是
Android 提供给我们的外特性:在
Android 中,要完成某个操作,所需要做的就是请求某个有能力的服务对象去完成动作,而无需知道这个通讯是怎样工作的,以及服务在哪里。
所以 Andoid 的 IPC 在本质上属于对象请求代理架构,
Android的设计者用 CORBA 的概念将自己包装了一下,实现了一个微型的轻量级 CORBA 架构,这就是 Andoid 的 IPC 设计的意图所在,它并不是仅仅解决通讯,而是给出了一个架构,一种设计理念,这就是
Android 的闪光的地方。
Android 的 Binder 更多考虑了数据交换的便捷,并且只是解决本机的进程间的通讯,所以不像 CORBA 那样复杂,所以叫做轻量级。
所以要理解
Android 的 IPC 架构,就需要了解 CORBA 的架构。
而 CORBA 的架构在本质上可以使用下面图来表示: 在服务端,多了一个代理器,更为抽象一点我们可以下图来表示。
分析和 CORBA 的大体理论架构,我给出下面的
Android 的对象代理结构。
在结构图中,我们可以较为清楚的把握
Android 的IPC包含了如下的概念: 设备上下文什(ContextObject) 设备上下文包含关于客服端,环境或者请求中没有作为参数传递个操作的上下文信息,应用程序开发者用 ContextObject接口上定义的操作来创建和操作上下文。
Android 代理:这个是指代理对象 Binder Linux 内核提供的 Binder 通讯机制
Android 的外特性空间是不需要知道服务在那里,只要通过代理对象完成请求,但是我们要探究
Android 是如何实现这个架构,首先要问的是在 Client 端要完成云服务端的通讯,首先应该知道服务在哪里?我们首先来看看 Service Manger 管理了那些数据。
Service Manager 提供了 add servicecheck service 两个重要的方法,并且维护了一个服务列表记录登记的服务名称和句柄。
Service manager service 使用 0 来标识自己。
并且在初始化的时候,通过 binder 设备使用 BINDER_SET_CONTEXT_MGRioctl 将自己变成了 CONTEXT_MGR。
Svclist 中存储了服务的名字和 Handle,这个 Handle 作为 Client 端发起请求时的目标地址。
服务通过 add_service 方法将自己的名字和 Binder 标识 handle 登记在 svclist 中。
而服务请求者,通过 check_service 方法,通过服务名字在 service list 中获取到 service 相关联的 Binder 的标识 handle通过这个 Handle 作为请求包的目标地址发起请求。
我们理解了 Service Manager 的工作就是登记功能,现在再回到IPC上,客服端如何建立连接的?我们首先回到通讯的本质:IPC。
从一般的概念来讲,
Android 设计者在 Linux 内核中设计了一个叫做 Binder 的设备文件,专门用来进行
Android 的数据交换。
所有从数据流来看 Java 对象从 Java 的 VM 空间进入到 C空间进行了一次转换,并利用 C空间的函数将转换过的对象通过 driver/binder 设备传递到服务进程,从而完成进程间的 IPC。
这个过程可以用下图来表示。
这里数据流有几层转换过程。
(1) 从 JVM 空间传到 c空间,这个是靠 JNI 使用 ENV 来完成对象的映射过程。
(2) 从 c空间传入内核 Binder 设备,使用 ProcessState 类完成工作。
(3) Service 从内核中 Binder 设备读取数据。
Android设计者需要利用面向对象的技术设计一个框架来屏蔽掉这个过程。
要让上层概念空间中没有这些细节。
Android 设计者是怎样做的呢?我们通过 c空间代码分析,看到有如下空间概念包装ProcessStateProcessState.cpp 在 ProcessState 类中包含了通讯细节,利用 open_binder 打开 Linux 设备 dev/binder通过 ioctrl 建立的基本的通讯框架。
利用上层传递下来的 servicehandle 来确定请求发送到那个 Service。
通过分析我终于明白了 Bnbinder,BpBinder 的命名含义,Bn-代表 Native,而 Bp 代表 Proxy。
一旦理解到这个层次,ProcessState 就容易弄明白了。
下面我们看 JVM 概念空间中对这些概念的包装。
为了通篇理解设备上下文,我们需要将
Android VM 概念空间中的设备上下文和 C空间总的设备上下文连接起来进行研究。
为了在上层使用统一的接口,在 JVM 层面有两个东西。
在
Android 中,为了简化管理框架,引入了 ServiceManger 这个服务。
所有的服务都是从 ServiceManager 开始的,只用通过 Service Manager 获取到某个特定的服务标识构建代理 IBinder。
在
Android 的设计中利用 Service Manager 是默认的 Handle 为 0,只要设置请求包的目标句柄为 0,就是发给 Service Manager 这个Service 的。
在做服务请求时,
Android 建立一个新的 Service Manager Proxy。
Service Manager Proxy 使用 ContexObject 作为 Binder和 Service Manager Service(服务端)进行通讯。
我们看到
Android 代码一般的获取 Service 建立本地代理的用法如下: IXXX mIxxxIXXXInterface.Stub.asInterfaceServiceManager.getServicequotxxxquot 例如:使用输入法服务: IInputMethodManager mImm IInputMethodManager.Stub.asInterfaceServiceManager.getServicequotinput_methodquot 这些服务代理获取过程分解如下: (1) 通过调用 GetContextObject 调用获取设备上下对象。
注意在 AndroidJVM 概念空间的 ContextObject 只是 与 ServiceManger Service 通讯的代理 Binder 有对应关系。
这个跟 c概念空间的 GetContextObject 意义是不一样的。
注意看看关键的代码 BinderInternal.getContextObject() BinderInteral.java NATIVE JNI:getContextObject
android_util_Binder.cpp
Android_util_getConextObject
android_util_Binder.cpp ProcessState::self-gtgetCotextObject0 processState.cpp getStrongProxyForHandle0 NEW BpBinder0 注意 ProcessState::self-gtgetCotextObject0 processtate.cpp,就是该函数在进程空间建立 了 ProcessState 对象,打开了Binder 设备 dev/binder并且传递了参数 0,这个 0 代表了与 Service Manager 这个服务绑定。
(2) 通过调用 ServiceManager.asInterface(ContextObject)建立一个代理 ServiceManger。
mRemote ContextObjectBinder这样就建立起来 ServiceManagerProxy 通讯框架。
3客户端通过调用 ServiceManager 的 getService 的方法建立一个相关的代理 Binder。
ServiceMangerProxy.remote.transactGET_SERVICEIBinderret.ReadStrongBinder -》这个就是 JVM 空间的代理 BinderJNI Navite:
android_os_Parcel_readStrongBinder
android_util_binder.cppParcel-gtreadStrongBinder pacel.cppunflatten_binder pacel.cppgetStrongProxyForHandleflat_handleNEW BpBinderflat_handle-》这个就是底层 c空间新建的代理 Binder。
整个建立过程可以使用如下的示意图来表示: Activity 为了建立一个 IPC,需要建立两个连接:访问 Servicemanager Service 的连接,IXXX 具体 XXX Service 的代理对象与 XXXService 的连接。
这两个连接对应 c空间 ProcessState 中 BpBinder。
对 IXXX 的操作.