第1章 Android系统概述 1
1.1 基础知识 1
1.1.1 Android开发系统的由来 1
1.1.2 移动电话系统开发模式 2
1.1.3 未来移动电话的功能及Android的优势 4
1.2 Android的开发工作 6
1.2.1 Android移植开发 6
1.2.2 Android应用开发 8
1.2.3 Android系统开发 9
1.3 Android的SDK与源代码 10
1.3.1 基于SDK的Android开发 10
1.3.2 基于源代码SDK Android开发 11

第2章 Android系统开发综述 13
2.1 Android的系统架构 13
2.1.1 软件结构 13

android程序库:

系统C库:一个从BSD继承来的标准C系统函数库(libc),它是专门为嵌入式Linux的设备制定的库

多媒体库:基于PacketVideo的OpenCore:该哭支持多种常用的音频视频格式回访和录制,支持多种媒体格式的编码解码格式。

SurfaceManager:显示子系统的管理器,并且为多个应用程序提供2D和3D图层的无缝融合。

LibWebCore:一个最新的Web浏览器引擎,支持Android浏览器以及一个可嵌入的Web视图。

SGL:Skia图形库,底层的2D图形引擎。

3Dlibraries:基于OpenGL ES1.0 API的实现:该库可以使用硬件3D加速(如果可用)或者使用高度优化的3D软加速。

FreeType:位图(bitmap)和矢量(vector)字体显示。

3. Android 运行环境

android 有Dalvik java虚拟机和基础Java类库组成

Dalvik是Android中使用的Java虚拟机,每一个Android程序都运行在自己的进程中,都有一个Dalvik虚拟机实例。Dalvik被设计成一个可以同时运行多个虚拟机实例的虚拟系统

Davik运行针对小内存做了优化的Dex可执行文件

同时虚拟机是基于寄存器的,所有的类都经过Java编译,然后通过SDK中的dx工具转化成.dex格式虚拟机执行

Dalvik虚拟机依赖于Linux内核一些功能,比如线程机制和底层内存管理机制。

4、 Android应用程序框架

应用程序重用机制也使用户可以方便替换程序组件,包括

views:丰富而又可扩展的视图(Views):可以用来构建应用程序,包括列表(lists)、网格(grids)、文本框(text boxes),按钮(buttons)等基本的UI元素,甚至可嵌入的Web浏览器。

content providers :使得应用程序可以访问另一个应用程序的数据(如联系人数据库),或者共享它们自己的数据。

resource Manager:提供非代码资源的访问,如本地字符串,图形和布局文件(layout files).

Notification Manager : 使得应用程序可以在状态栏中显示自定义的提示信息。

Activity Manager:用来管理应用程序声明周期并提供常用的导航回退功能。

WindowManager是Android中一个重要的服务(Service )。WindowManager Service 是全局的,是唯一的。它将用户的操作,翻译成                                                         为指令,发送给呈现在界面上的各个Window。Activity会将顶级的控件注册到 Window Manager 中,
当用户点击触碰屏幕或键盘的时候,Window Manager就会通知到,而当控件有一些请求产生,也会经由ViewParent送回到Window                                                                Manager中。从而完成整个通信流程。
整个Android的窗口机制是基于一个叫做 WindowManager,这个接口可以添加view到屏幕,也可以从屏幕删除view。它面向的对象一端                                                           是屏幕,另一端就是View,通过WindowManager的 addView方法创建View,这样产生出来的View根据
WindowManager.LayoutParams属性不同,效果也就不同了。比如创建 系统顶级窗口,实现悬浮窗口效果!WindowManager的方法很                                                            简单,基本用到的就三addView,removeView,updateViewLayout。接口,而WindowManager.LayoutParams的属性就多了,非常丰富,                                                       具体请查后面介绍
怎么样获取windowManager实例呢,下面我们就通过一个小的例子来说明以下:
Button bb=new Button(getApplicationContext());  
WindowManager wmManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);  
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();  
/** 
*以下都是WindowManager.LayoutParams的相关属性 
* 具体用途请参考SDK文档 
*/  
  wmParams.type=2002;   //这里是关键,你也可以试试2003  
  wmParams.format=1;  
/** 
*这里的flags也很关键 
*代码实际是wmParams.flags |= FLAG_NOT_FOCUSABLE; 
*40的由来是wmParams的默认属性(32)+ FLAG_NOT_FOCUSABLE(8) 
*/  
  wmParams.flags=40;  
  wmParams.width=40;  
  wmParams.height=40;  
 
  wmManager.addView(bb, wmParams);  //创建View  
上面就是一个简单的例子,创建了一个Button对象然后通过WindowManager实例对象的addView添加这个ButtonVIew并根据相应的LayoutParams参数进行显示。
 
WindowManager对象的一些接口说明:
1)abstract Display  getDefaultDisplay();  //获取默认显示的 Display 对象。
2)abstract void removeViewImmediate(View view);//是removeView(View) 的一个特殊扩展,在方法返回前能够立即调用该视图层次的View.onDetachedFromWindow() 方法。
 
下面我们就重点介绍以下WindowManager接口的嵌套内部类LayoutParams。
WindowManager.LayoutParams 是 WindowManager 接口的嵌套类;继承于 ViewGroup.LayoutParams 。它的内容十分丰富。其实WindowManager.java的主要内容就是由这个类定义构成。下面来分析一下这个类:
 
定义 
public static class WindowManager.LayoutParams 
extends ViewGroup.LayoutParams implements Parcelable
继承关系 
java.lang.Object
  ↳android.view.ViewGroup.LayoutParams
  ↳android.view.WindowManager.LayoutParams

继承来的属性与常量 
从 ViewManager.LayoutParams 继承来的属性:
android:layout_height
 Specifies the basic height of the view.

android:layout_width
 Specifies the basic width of the view.

从 ViewManager.LayoutParams继承的常量:
FILL_PARENT
WRAP_CONTENT
MATCH_PARENT
 
两个变量: 
width
height
 
属性及可用的常量定义 
1. public int x;
  如果忽略gravity属性,那么它表示窗口的绝对X位置。
  什么是gravity属性呢?简单地说,就是窗口如何停靠。
  当设置了 Gravity.LEFT 或 Gravity.RIGHT 之后,x值就表示到特定边的距离。
 
2. public int y;
  如果忽略gravity属性,那么它表示窗口的绝对Y位置。
  当设置了 Gravity.TOP 或 Gravity.BOTTOM 之后,y值就表示到特定边的距离。
 
3. public float horizontalWeight;
  public float verticalWeight;
  在纵/横向上,为关联的view预留了多少扩展空间(像素)。如果是0,那么此view不能被拉伸。
  其他情况下,扩展空间(像素)将被widget所均分。

4. public int type;
窗口类型。有3种主要类型:
a)Applicationwindows:
取值在 FIRST_APPLICATION_WINDOW 和 LAST_APPLICATION_WINDOW 之间。
是通常的、顶层的应用程序窗口。必须将 token 设置成 activity 的 token 。
b)Sub_windows:
取值在 FIRST_SUB_WINDOW 和 LAST_SUB_WINDOW 之间。
与顶层窗口相关联,token 必须设置为它所附着的宿主窗口的 token。
c)Systemwindows:
取值在 FIRST_SYSTEM_WINDOW 和 LAST_SYSTEM_WINDOW 之间。
用于特定的系统功能。它不能用于应用程序,使用时需要特殊权限。
下面定义了 type 的取值:
 应用程序窗口。
 public static final int FIRST_APPLICATION_WINDOW = 1;

所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。     
 public static final int TYPE_BASE_APPLICATION   =1;

普通应哟功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。
 public static final int TYPE_APPLICATION       = 2;

用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。
 它用于让系统显示些信息,直到应用程序可以开启自己的窗口。   
 public static final int TYPE_APPLICATION_STARTING = 3;

应用程序窗口结束。
 public static final int LAST_APPLICATION_WINDOW = 99;

子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。
 public static final int FIRST_SUB_WINDOW       = 1000;

面板窗口,显示于宿主窗口上层。
 public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;

媒体窗口,例如视频。显示于宿主窗口下层。
 public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;

应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)
 public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;

对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。
 public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;

媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)
 public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW +4;

子窗口结束。( End of types of sub-windows )
 public static final int LAST_SUB_WINDOW        = 1999;

系统窗口。非应用程序创建。
 public static final int FIRST_SYSTEM_WINDOW    = 2000;

状态栏。只能有一个状态栏;它位于屏幕顶端,其他窗口都位于它下方。
 public static final int TYPE_STATUS_BAR        =  FIRST_SYSTEM_WINDOW;

搜索栏。只能有一个搜索栏;它位于屏幕上方。
 public static final int TYPE_SEARCH_BAR        = FIRST_SYSTEM_WINDOW+1;

电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
 public static final int TYPE_PHONE            = FIRST_SYSTEM_WINDOW+2;

系统提示。它总是出现在应用程序窗口之上。
 public static final int TYPE_SYSTEM_ALERT      =  FIRST_SYSTEM_WINDOW +3;

锁屏窗口。
 public static final int TYPE_KEYGUARD          = FIRST_SYSTEM_WINDOW +4;

信息窗口。用于显示toast。
 public static final int TYPE_TOAST            = FIRST_SYSTEM_WINDOW +5;

系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。
 public static final int TYPE_SYSTEM_OVERLAY    =  FIRST_SYSTEM_WINDOW +6;

电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。
 public static final int TYPE_PRIORITY_PHONE    =  FIRST_SYSTEM_WINDOW +7;

系统对话框。(例如音量调节框)。
 public static final int TYPE_SYSTEM_DIALOG     =  FIRST_SYSTEM_WINDOW +8;

锁屏时显示的对话框。
 public static final int TYPE_KEYGUARD_DIALOG   =  FIRST_SYSTEM_WINDOW +9;

系统内部错误提示,显示于所有内容之上。
 public static final int TYPE_SYSTEM_ERROR      =  FIRST_SYSTEM_WINDOW +10;

内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖。
 public static final int TYPE_INPUT_METHOD      =  FIRST_SYSTEM_WINDOW +11;

内部输入法对话框,显示于当前输入法窗口之上。
 public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW +12;

墙纸窗口。
 public static final int TYPE_WALLPAPER         = FIRST_SYSTEM_WINDOW +13;

状态栏的滑动面板。
 public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW +14;

系统窗口结束。
 public static final int LAST_SYSTEM_WINDOW     = 2999;
5. public int memoryType;
  指出窗口所使用的内存缓冲类型。默认为 NORMAL 。

下面定义了 memoryType 的取值:
 窗口缓冲位于主内存。
 public static final int MEMORY_TYPE_NORMAL = 0;

窗口缓冲位于可以被DMA访问,或者硬件加速的内存区域。
 public static final int MEMORY_TYPE_HARDWARE = 1;

窗口缓冲位于可被图形加速器访问的区域。
 public static final int MEMORY_TYPE_GPU = 2;

窗口缓冲不拥有自己的缓冲区,不能被锁定。缓冲区由本地方法提供。
 public static final int MEMORY_TYPE_PUSH_BUFFERS = 3;
6.  public int flags;
行为选项/旗标,默认为 none .

下面定义了 flags 的取值:
 窗口之后的内容变暗。
 public static final int FLAG_DIM_BEHIND       = 0x00000002;

窗口之后的内容变模糊。
 public static final int FLAG_BLUR_BEHIND       = 0x00000004;

不许获得焦点。
 public static final int FLAG_NOT_FOCUSABLE     = 0x00000008;

不接受触摸屏事件。
 public static final int FLAG_NOT_TOUCHABLE     = 0x00000010;

当窗口可以获得焦点(没有设置 FLAG_NOT_FOCUSALBE 选项)时,仍然将窗口范围之外的点设备事件(鼠标、触摸屏)发送给后面的窗口处理。否则它将独占所有的点设备事件,而不管它们是不是发生在窗口范围内。
 public static final int FLAG_NOT_TOUCH_MODAL   = 0x00000020;

如果设置了这个标志,当设备休眠时,点击触摸屏,设备将收到这个第一触摸事件。
 通常第一触摸事件被系统所消耗,用户不会看到他们点击屏幕有什么反应。
 public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;

当此窗口为用户可见时,保持设备常开,并保持亮度不变。
 public static final int FLAG_KEEP_SCREEN_ON    = 0x00000080;

窗口占满整个屏幕,忽略周围的装饰边框(例如状态栏)。此窗口需考虑到装饰边框的内容。
 public static final int FLAG_LAYOUT_IN_SCREEN   =0x00000100;

允许窗口扩展到屏幕之外。
 public static final int FLAG_LAYOUT_NO_LIMITS   =0x00000200;

窗口显示时,隐藏所有的屏幕装饰(例如状态条)。使窗口占用整个显示区域。
 public static final int FLAG_FULLSCREEN     = 0x00000400;

此选项将覆盖FLAG_FULLSCREEN选项,并强制屏幕装饰(如状态条)弹出。
 public static final int FLAG_FORCE_NOT_FULLSCREEN   =0x00000800;

抖动。指 对半透明的显示方法。又称“点透”。图形处理较差的设备往往用“点透”替代Alpha混合。
 public static final int FLAG_DITHER           = 0x00001000;

不允许屏幕截图。
 public static final int FLAG_SECURE           = 0x00002000;

一种特殊模式,布局参数用于指示显示比例。
 public static final int FLAG_SCALED           = 0x00004000;

当屏幕有可能贴着脸时,这一选项可防止面颊对屏幕造成误操作。
 public static final int FLAG_IGNORE_CHEEK_PRESSES   = 0x00008000;

当请求布局时,你的窗口可能出现在状态栏的上面或下面,从而造成遮挡。当设置这一选项后,窗口管理器将确保窗口内容不会被装饰条(状态栏)盖住。
 public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;

反转FLAG_NOT_FOCUSABLE选项。
 如果同时设置了FLAG_NOT_FOCUSABLE选项和本选项,窗口将能够与输入法交互,允许输入法窗口覆盖;
 如果FLAG_NOT_FOCUSABLE没有设置而设置了本选项,窗口不能与输入法交互,可以覆盖输入法窗口。
 public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;

如果你设置了FLAG_NOT_TOUCH_MODAL,那么当触屏事件发生在窗口之外事,可以通过设置此标志接收到一个 MotionEvent.ACTION_OUTSIDE事件。注意,你不会收到完整的down/move/up事件,只有第一次down事件时可以收到 ACTION_OUTSIDE。
 public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;

当屏幕锁定时,窗口可以被看到。这使得应用程序窗口优先于锁屏界面。可配合FLAG_KEEP_SCREEN_ON选项点亮屏幕并直接显示在锁屏界面之前。可使用FLAG_DISMISS_KEYGUARD选项直接解除非加锁的锁屏状态。此选项只用于最顶层的全屏幕窗口。
 public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;

请求系统墙纸显示在你的窗口后面。窗口必须是半透明的。
 public static final int FLAG_SHOW_WALLPAPER = 0x00100000;

窗口一旦显示出来,系统将点亮屏幕,正如用户唤醒设备那样。
 public static final int FLAG_TURN_SCREEN_ON = 0x00200000;

解除锁屏。只有锁屏界面不是加密的才能解锁。如果锁屏界面是加密的,那么用户解锁之后才能看到此窗口,除非设置了FLAG_SHOW_WHEN_LOCKED选项。
 public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;

锁屏界面淡出时,继续运行它的动画。
 public static final int FLAG_KEEP_SURFACE_WHILE_ANIMATING =0x10000000;

以原始尺寸显示窗口。用于在兼容模式下运行程序。
 public static final int FLAG_COMPATIBLE_WINDOW = 0x20000000;

用于系统对话框。设置此选项的窗口将无条件获得焦点。
 public static final int FLAG_SYSTEM_ERROR = 0x40000000;
7. public int softInputMode;
  软输入法模式选项:

以下选项与 softInputMode 有关:
 软输入区域是否可见。
 public static final int SOFT_INPUT_MASK_STATE = 0x0f;

未指定状态。
 public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;

不要修改软输入法区域的状态。
 public static final int SOFT_INPUT_STATE_UNCHANGED = 1;

隐藏输入法区域(当用户进入窗口时)。
 public static final int SOFT_INPUT_STATE_HIDDEN = 2;

当窗口获得焦点时,隐藏输入法区域。
 public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;

显示输入法区域(当用户进入窗口时)。
 public static final int SOFT_INPUT_STATE_VISIBLE = 4;

当窗口获得焦点时,显示输入法区域。
 public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;

窗口应当主动调整,以适应软输入窗口。
 public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;

未指定状态,系统将根据窗口内容尝试选择一个输入法样式。
 public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;

当输入法显示时,允许窗口重新计算尺寸,使内容不被输入法所覆盖。
 不可与SOFT_INPUT_ADJUSP_PAN混合使用,如果两个都没有设置,系统将根据窗口内容自动设置一个选项。
 public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;

输入法显示时平移窗口。它不需要处理尺寸变化,框架能够移动窗口以确保输入焦点可见。
 不可与SOFT_INPUT_ADJUST_RESIZE混合使用;如果两个都没设置,系统将根据窗口内容自动设置一个选项。
 public static final int SOFT_INPUT_ADJUST_PAN = 0x20;

当用户转至此窗口时,由系统自动设置,所以你不要设置它。
 当窗口显示之后该标志自动清除。
 public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
8. public int gravity;
  gravity 属性。什么是gravity属性呢?简单地说,就是窗口如何停靠。

9. public float horizontalMargin;
  水平边距,容器与widget之间的距离,占容器宽度的百分率。

10. public float verticalMargin;
纵向边距。

11. public int format;
期望的位图格式。默认为不透明。参考android.graphics.PixelFormat。

12. public int windowAnimations;
窗口所使用的动画设置。它必须是一个系统资源而不是应用程序资源,因为窗口管理器不能访问应用程序。

13. public float alpha = 1.0f;
整个窗口的半透明值,1.0表示不透明,0.0表示全透明。

14. public float dimAmount = 1.0f;
当FLAG_DIM_BEHIND设置后生效。该变量指示后面的窗口变暗的程度。1.0表示完全不透明,0.0表示没有变暗。

15. public float screenBrightness = -1.0f;
用来覆盖用户设置的屏幕亮度。表示应用用户设置的屏幕亮度。从0到1调整亮度从暗到最亮发生变化。
 
16. public IBinder token = null;
窗口的标示符。( Identifier for this window. This will usually be filled in for you. )

17. public String packageName = null;
此窗口所在的包名。

18. public int screenOrientation =ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
屏幕方向,参见android.content.pm.ActivityInfo#screenOrientation。

19. 在兼容模式下,备份/恢复参数所使用的内部缓冲区。
public int[] mCompatibilityParamsBackup = null;
 
常用方法 
1. public final int copyFrom (WindowManager.LayoutParams o);
  下面定义了各种“CHANGE”信息,为copyFrom函数所使用。
public staticfinal int LAYOUT_CHANGED =1<<0;
public staticfinal int TYPE_CHANGED =1<<1;
public staticfinal int FLAGS_CHANGED =1<<2;
public staticfinal int FORMAT_CHANGED =1<<3;
public staticfinal int ANIMATION_CHANGED =1<<4;
public staticfinal int DIM_AMOUNT_CHANGED =1<<5;
public staticfinal int TITLE_CHANGED =1<<6;
public staticfinal int ALPHA_CHANGED =1<<7;
public staticfinal int MEMORY_TYPE_CHANGED =1<<8;
public staticfinal int SOFT_INPUT_MODE_CHANGED =1<<9;
public staticfinal int SCREEN_ORIENTATION_CHANGED =1<<10;
public staticfinal int SCREEN_BRIGHTNESS_CHANGED =1<<11;

package manager

1. 用来获取当前设备上应用包的相关信息。

Activity manager

5. Android应用程序

android所有的应用程序都是使用Java语言编写的。Android系统的核心应用程序和系统一起发布,包括:E-mail客户端,SMS短消息程序、日历、地图、浏览器、联系人管理程序等。

由用户开发的Android应用程序和Android的核心应用程序是同一层次的,它们都是基于Android的系统API构建的。
2.1.2 Android的工具 16

aapt

adb

android工具

AIDL

AVDS

DDMS

dx

Draw9-patch

Emulator

Hierarchy Viewer

mksdcard

Monkey

sqlite3

Traceview

2.2 Android源代码的开发环境 18

基于Linux的开发环境,推荐使用Ubuntu

2.2.1 Android源代码的获取和提交 18

主机环境包括以下需求:git工具,repo工具,java的JDK 主机编译工具

Ubuntu主机需要安装以下包:

1. 获取Android源代码

2. 提交android源代码

2.2.2 Android源代码结构 21

工程名称

工程描述

bionic

C运行时支持:libc,libm,libdl,动态linker

bootloader/legacy

Bootloader参考代码

build

Build系统

dalvik

Dalvik虚拟机

development

高层的开发和调试工具

frameworks/base

Android核心的框架库

frameworks/policies/base

框架配置策略

Hardware/libhardware

硬件抽象层

hardware/ril

无线接口层(radio Inteface  Layer)

kernel

Linux内核

Prebuilt

对Linux和Mac OS编译的二进制支持

System/core

最小化可启动的环境

System/extras

底层调试和检查工具

bootloader中包含的是内核加载器的内容,在内核运行之前。其中kernel中包含的室内和的内容,bionic和build是编译系统,prbuilt是预编译的内核,

2. Android的扩展工程

android的扩展工程包含在external文件夹中,这是一个经过修改后适应Android系统的开源工程,这些工程中的内容有些在主机是哪个运行,有些在目标及上运行。

工程名称

工程描述

Aes

高级加密标准(Advanced  Encrypted Standard)

Apache-http

Http服务器

Bison

(主机)自动生成语法分析器程序

Bluez

蓝牙库

Bsdiff

(主机)用于为二进制文件生成补丁

Bzip2

(主机/目标机)压缩文件工具

Clearsilver

(主机)模板语言,包括Python、java、perl、C的库

Dbus

freedesktop下开源的Linux  IPC通信机制

Dhcpcd

动态主机配置协议的工具

Dropbear

ssh2服务器和客户端

E2fsprogs

(主机)Ext2/3/4 文件系统的工具

Elfcopy

(主机)ELF工具

Elfutils

(主机)ELF工具

Embunit

嵌入式C系统的测试框架

Emma

(Java)Java代码覆盖检查工具

Esd

(仅头文件)

Expat

(主机/目标机)XML  Parser

Fdlibm

精确实现IEEE754浮点数

Freetype

C语言实现的字体光栅化引擎制作的一个软件库

Gdata

(Java)用于数据操作

Genext2fs

(主机)Ext2文件系统生成工具

Giflib

GIF工具

Googleclient

(Java)Google客户端

Grub

多重炒作系统启动管理器

Icu4c

IBM支持软件国际滑的开源项目

Iptables

建构在Xtables的架构下,定义“表(tables)”、“键(chain)”、“规则(rules)”来处理风暴的运送

Jdiff

(主机Java库)比较工具

Jhead

Jpeg文件头(Exif)编辑修改软件

Jpeg

Jpeg工具库

Libffi

可移植的

Libpcap

网络数据包补货函数包

Libpng

PNG工具库

Libxml2

(主机/目标机)C语言的XML解析库

Netcat

用来对网络连线TCP或者UDP进行读/写

Netperf

网络性能的测量工具

Neven

人脸识别的一套库

Opencore

多媒体框架

Openssl

C语言的SSL(Secure  Sockets Layer)工具

Oprofile

Linux内核支持的一种性能分析机制

Ping

Ping工具

Ppp

Ppp(点对点)工具

Protobuf

Google工具,利用.proto文件自动生成代码

qemu

(主机)模拟环境

Safe-iop

跨平台的整数运算

Skia

一个图形库

Sonivox

Sonic嵌入式的音乐合成器

Sqlite

轻量级的SQL嵌入式数据库

Srec

(主机、目标机)motorols  S-records十六进制文件格式工具

Strace

监视系统调用的工具

Tagsoup

(Java)HTML解析工具

Tcpdump

为网络中传送的数据包的头被完全接货下来提供分析的工具

Tinyxml

(主机、目标机)XML工具

Tremor

Ogg Vorbis的播放器

Webkit

开源的浏览器引擎

Wpa_supplicant

无线局域网Wifi的工具

Xdelta3

二进制文件比较工具

Yaffs2

YAFFS文件系统

3. Android中的Java程序包

2.2.3 编译 24

1. 编译方法

在其根目录下直接执行make即可(MakeFile)

$make

make过程将递归找到各个目录中的Android.mk文件进行编译。Android编译将搜索所有的目录,编译本身和目录的名称及位置没有关系

2. 编译结果

Android编译结果包含以下内容

主机工具

目标程序

目标映像文件

目标机Linux内核(需要单独编译)

Android系统编译完成的结果全部在其根目录out目录中,原始的各个工程不会改动。

out目录的结构如下

out/

|---- host                                     //主机内容

|          |----common                   //主机的通用内容

|          |         |-- obj                     编译所生成的主机linux上运行的工具

|          |----linux-x86

|                    |---  bin

|                    |-----framework

|                    |----lib

|                     ----obj

|----------target                             //目标机内容

|-----common             //目标机的通用内容

|              |---R

|              |---docs

|              -----obj

|-----------product           //目标机的产品目录

|------generic

其中out/target/product目录是目标产品的目录,在默认的情况下使用generic作为目标产品的名称,目录结构如下所示:

out/target/product/generic

|-- android-info.txt

|-- clean_steps.mk

|-- data                                                      //数据目录

|-- installed-files.txt

|-- obj                                                         中间目标文件目录

|       |-- APPS                                            Java应用程序包

|       |-- ETC                                              运行时配置文件

|       |-- EXECUTABLES                         可执行程序

|       |-- KEYCHARS

|       |-- NOTICE.html

|       |-- NOTICE.html.gz

|       |--NOTICE_FILES

|       |--PACKAGING

|       |--SHEARED_LIBRARIES           动态库(共享库)

|       |--STATIC_LIBRARIES                静态库

|       |--include

|  ---lib

| --- previous_build_config.mk

|--- ramdisk.img                                     根文件系统映像

|---root                                                      根文件系统目录

|---symbols                                             符号的目录

|---system                                               主文件系统目录

|---system.img                                       主文件系统映像

|---userdata-qemu.img                        QEMU的数据映像

----userdata.img                                   数据映像

其中root,system,data三个目录分别是目标根文件系统、主文件系统和数据文件系统的目录,后缀名为.img的文件分别是他们所对应的映像文件。

2.2.4 系统的运行 25

Android Emulator基于QEMU,这个模拟器支持Android Virtual Device(Android 虚拟设备)以及很多的调试性能。

1. 使用模拟器运行系统

2. 在shell中查看信息

3. 模拟器的相关内容

2.3 Android SDK的开发环境 32

Android的SDK开发环境使用预编译的内核和文件系统,屏蔽了Android软件架构第三层及以下的内容,开发者可以基于Android的系统API配合运行应用层次的开发。在SDK、的开发环境中,还可以使用Eclipse等作为IDE开发环境。

2.3.1 SDK的结构 32

android的SDK命名规则为:

android-sdk-{主机系统}_{体系结构}_{版本}

2.3.2 Windows环境SDK开发 33

2.3.3 Linux环境SDK开发 42

第3章 Android的Linux内核与驱动程序 44

3.1 Linux核心与驱动 44

android在标准的Linux内核中主要增加的内容是一些驱动程序,这些驱动主要分成两种类型:

Android专用驱动:

Android使用的设备驱动:

3.2 Android专用驱动 45

3.2.1 Ashmem 45                              //匿名共享驱动

Ashmem的含义是匿名共享内存,通过这种机制,可以为用户空间程序提供分配内存的机制

3.2.2 Binder 45                                  //基于OpenBinder系统的驱动,为Android平台提供IPC支持:

Android的Binder驱动程序为用户层程序提供了IPC(进程间通信)支持,Android整个系统的运行以来Binder驱动。

3.2.3 Logger 46                                 //轻量级的log驱动

Android的Logger驱动程序为用户程序提供log支持,这个驱动作为一个工程来使用

3.3 Android使用的设备驱动 46

作为主要为智能手机定制的操作系统,Android通常可以使用Linux中一些标准的设备驱动程序。

3.3.1 Framebuffer显示驱动 46

在Linux中,Framebuffer驱动是标准的显示设备驱动:对于PC系统,Framebuffer驱动是显卡的驱动:对于嵌入式系统的SOC处理器,Framebuffer
3.3.2 Event输入设备驱动 48

Input驱动程序是linux输入设备的驱动程序,分成游戏杆(joystick)、鼠标(mouse和mice)和事件设备(Event queue)3种驱动程序。其中事件驱动程序是目前通用的驱动程序,可支持键盘、鼠标、触摸屏等多种输入设备。

3.3.3 v4l2摄像头——视频驱动 50

V4L的全称是Video4Linux(Video for Linux),是Linux内核中标准的关于视频驱动程序。
3.3.4 OSS音频驱动 53

3.3.5 ALSA音频驱动 54

3.3.6 MTD驱动 56

3.3.7 蓝牙驱动 57

3.3.8 Wlan驱动 58

第4章 Android的底层库和程序 60
4.1 底层库和程序的结构 60
4.1.1 本地实现的基本结构 60

Android的本地实现层次具有基本的库和程序,这些苦和程序是Android基本系统运行的基础
4.1.2 增加本地程序和库的方法 61

Android中增加被底层徐或者库,这些程序和库与其所在的路径没有关系,只和他们的Android.mk文件有关系。

Android.mk和普通的Makefile略有不同,Android.mk具有统一的写法,主要包含一些系统公共的宏。

Android.mk中选项参考一下全路径:

build/core/config.mk

各个选项的默认值在以下文件中定义:

build/core/base_rules.mk

在一个Android.mk中也可以生成多个可执行程序、动态库或者静态库。

1. 编译程序

2. 安装程序

4.2 标准C/C++库bionic 64

bionic提供C/C++标准库的功能,它是一个专门我嵌入式系统设计的轻量级标准库实现。

bionic 的源代码和头文件在一下目录中:

相对于传统的标准库实现,如glibc,bionic的体积和内存占用更小。bionic支持表尊C、C++库绝大部分功能,支持数学库及NPTL线程库。它还实现了自己的Linker及Loader用于动态库的创建和加载。

bionic加入了Android独有的一些功能,比如log的底层支持。另外它还实现了一套property系统,这是整个Android全局变量的存储区域,bionic使用共享内存的方式来实现property系统。
4.3 C语言工具库libcutils 65

C语言工具库提供了C语言中最基本的工具功能。这是Android本地种最基础的库,基本上Android中所有的本地库和程序都连接了这个库。

4.4 init可执行程序 66

init京城是android 启动后,系统执行的第一个名称为init的可执行程序。这个程序可以一个守进程的方式运行,它提供了一下功能:

设备管理:

解析启动脚本 init.rc:

执行启动脚本中的基本功能:

执行启动脚本中的各种服务:

init进程的代码路径为:system/core/init.

init可执行文件是系统运行的第一个用户空间的程序,它以守护进程的方式运行。因此这个程序的init.c文件包含main函数的入口。
int main(int argc, char **argv)
{
    int device_fd = -1;
    int property_set_fd = -1;
    int signal_recv_fd = -1;
    int keychord_fd = -1;
    int fd_count;
    int s[2];
    int fd;
    struct sigaction act;
    char tmp[PROP_VALUE_MAX];
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;

act.sa_handler = sigchld_handler;
    act.sa_flags = SA_NOCLDSTOP;
    act.sa_mask = 0;
    act.sa_restorer = NULL;
    sigaction(SIGCHLD, &act, 0);

/* clear the umask */
    umask(0);

/* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

/* We must have some place other than / to create the
         * device nodes for kmsg and null, otherwise we won't
         * be able to remount / read-only later on.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    log_init();
    
    INFO("reading config file\n");
    parse_config_file("/init.rc");

/* pull the kernel commandline and ramdisk properties file in */
    qemu_init();
    import_kernel_cmdline(0);

get_hardware_name();
    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    parse_config_file(tmp);

action_for_each_trigger("early-init", action_add_queue_tail);
    drain_action_queue();

INFO("device init\n");
    device_fd = device_init();

property_init();
    
    // only listen for keychords if ro.debuggable is true
    keychord_fd = open_keychord();

if (console[0]) {
        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
        console_name = strdup(tmp);
    }

fd = open(console_name, O_RDWR);
    if (fd >= 0)
        have_console = 1;
    close(fd);

if( load_565rle_image(INIT_IMAGE_FILE) ) {
    fd = open("/dev/tty0", O_WRONLY);
    if (fd >= 0) {
        const char *msg;
            msg = "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"  // console is 40 cols x 30 lines
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "             A N D R O I D ";
        write(fd, msg, strlen(msg));
        close(fd);
    }
    }

if (qemu[0])
        import_kernel_cmdline(1);

if (!strcmp(bootmode,"factory"))
        property_set("ro.factorytest", "1");
    else if (!strcmp(bootmode,"factory2"))
        property_set("ro.factorytest", "2");
    else
        property_set("ro.factorytest", "0");

property_set("ro.serialno", serialno[0] ? serialno : "");
    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");

property_set("ro.hardware", hardware);
    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
    property_set("ro.revision", tmp);

/* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);
    drain_action_queue();

/* read any property files on system or data and
         * fire up the property service.  This must happen
         * after the ro.foo properties are set above so
         * that /data/local.prop cannot interfere with them.
         */
    property_set_fd = start_property_service();

/* create a signalling mechanism for the sigchld handler */
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
        signal_fd = s[0];
        signal_recv_fd = s[1];
        fcntl(s[0], F_SETFD, FD_CLOEXEC);
        fcntl(s[0], F_SETFL, O_NONBLOCK);
        fcntl(s[1], F_SETFD, FD_CLOEXEC);
        fcntl(s[1], F_SETFL, O_NONBLOCK);
    }

/* make sure we actually have all the pieces we need */
    if ((device_fd < 0) ||
        (property_set_fd < 0) ||
        (signal_recv_fd < 0)) {
        ERROR("init startup failure\n");
        return 1;
    }

/* execute all the boot actions to get us started */
    action_for_each_trigger("early-boot", action_add_queue_tail);
    action_for_each_trigger("boot", action_add_queue_tail);
    drain_action_queue();

/* run all property triggers based on current state of the properties */
    queue_all_property_triggers();
    drain_action_queue();

/* enable property triggers */   
    property_triggers_enabled = 1;

ufds[0].fd = device_fd;
    ufds[0].events = POLLIN;
    ufds[1].fd = property_set_fd;
    ufds[1].events = POLLIN;
    ufds[2].fd = signal_recv_fd;
    ufds[2].events = POLLIN;
    fd_count = 3;

if (keychord_fd > 0) {
        ufds[3].fd = keychord_fd;
        ufds[3].events = POLLIN;
        fd_count++;
    } else {
        ufds[3].events = 0;
        ufds[3].revents = 0;
    }

#if BOOTCHART
    bootchart_count = bootchart_init();
    if (bootchart_count < 0) {
        ERROR("bootcharting init failure\n");
    } else if (bootchart_count > 0) {
        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
    } else {
        NOTICE("bootcharting ignored\n");
    }
#endif

for(;;) {
        int nr, i, timeout = -1;

for (i = 0; i < fd_count; i++)
            ufds[i].revents = 0;

drain_action_queue();
        restart_processes();

if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif
        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

if (ufds[2].revents == POLLIN) {
            /* we got a SIGCHLD - reap and restart as needed */
            read(signal_recv_fd, tmp, sizeof(tmp));
            while (!wait_for_one_process(0))
                ;
            continue;
        }
        if (ufds[0].revents == POLLIN)
            handle_device_fd(device_fd);
        if (ufds[1].revents == POLLIN)
            handle_property_set_fd(property_set_fd);
        if (ufds[3].revents == POLLIN)
            handle_keychord(keychord_fd);
    }
    return 0;
}

2. 启动脚本init.rc

在android 中使用启动脚本init.rc,可以在系统的初始化过程中进行一些简单的初始化操作。

init启动脚本的路径:system/core/rootdir/init.rc

这个脚本被直接安装到目标系统的根文件系统中,被init可执行程序解析。

init.rc是在init启动后被执行的启动脚本,其语法主要包含了以下的内容:

Commands:命令

Actions:动作

Triggers:触发条件

Services:服务

Options:选项

Properties:属性

4.5 Shell工具 72

4.6 C++工具库libutils 75

libutils是android的底层库,这个库以C++实现,它提供的API也是C++的。android层次的本地C/C++程序和库,大都基于libutils开发

4.6.1 libutils的基本内容 75
4.6.2 Binder 76

Binder用于进程间的通信(IPC),它是Android平台的最核心机制之一,也是支撑这个系统运行的基础。

1. Binder简介

Android中的Binder最早来源于OpenBinder,Google为了摆脱OpenBinder的许可问题,重新开发了自己的一套Binder实现,基于宽松的Apache协议发布,架构OpenBinder类似。

相对于socket,Pipe等传统的IPC机制,Binder有着更系统化的架构,他可以实现远程函数调用(RPC),传递结构化的参数和返回值。而且在用户看来,远程函数调用与本地函数调用无异。Binder使用同步的函数调用模式,就如同线程前移一般,将用户京城的参数带到服务进程进行调用,再带着结果返回。

Binder的性能相对于本地函数来说,虽然有一定的差距,但对于智能手机这类外设众多、架构越发复杂、设计周期往往比较短的设备来说,采用Binder这样的IPC方式组织众多功能模块,看了一更有效地分离模块设计,降低模块儿间耦合,也能更好地利用底层操作系统的进程管理特性来辅助管理服务调度。目前大部分智能平台都很好利用了Binder或D-BUS等IPC机制,作为平台提供系统服务的基础。

关于Binder,需要注意的是,本节主要针对native部分的Binder实现:er针对Java部分的是实现见第五章

2. Binder基本架构

Binder可以分为多个层次,主要的机制在本地实现,在Java层也可以使用。

1. 驱动层

组织Binder服务节点,调度Binder相关处理线程,完成实际的BInder传输等。

2. 驱动适配层

主要是IPCThreadState.cpp与ProcessState.cpp , 还包括Parcel.cpp中的一些函数。绝大部分binder相关功能,都有他们完成与Binder驱动的沟通。这是Binder重要组成部分。

3.  Binder核心框架层

Binder核心框架主要是IBinder及它的两个雷,即BBinder和BpBinder,分别代表最基本的服务器端及客户端。

4. Binder框架层

Binder框架在native(CPP)和Java部分分别有一套实现,单模式都是类似的。

5. Binder、服务和客户端实现层

2. Binder基本架构

3. Binder服务端和客户端实现

在native层中,要定义新的Binder服务器和客户端,其实也就是实现第4层和第五层。主要使用的头文件是IInterface.h,其中定义了主要有外部使用的几个类,IInterface的定义如下所示:

class IInterface : public virtual RefBase{

public:sp<IBinder> asBinder();

sp<const IBinder>  asBinder() const;

protected:virtual  IBinder *       onAsBinder() = 0;

};

4.6.3 libutils中的其他内容 82

其中比价重要的类是在IMemory.h中定义的两个和内存相关的类。ImemoryHeap类定义如下:

class IMemoryHeap : public IInterface

{

public:DECLARE_META_INTERFACE(MemoryHeap);

enum{

READ_ONLY = 0x00000001;

MAP_ONCE  = 0x00000002

};

virtual int    getHeapID()  const  = 0;

virtual  void*   getBase()  const = 0;

virtual   size_t   getSize()   const  = 0;

virtual uint32_t   getFlags()   const  = 0;

int32_t   heapID  const

}

Imermory类的定义如下:

class IMemory :  public IInterface{

public:

}

IMemoryHeap接口表示一块堆上的内存,IMemory接口表示一块可以任意使用的内存。IMemory的构造函数中有一个参数IMemoryHeap,一个IMemory可以看做使用IMemoryHeap这个堆上内存的一部分。

MemoryHeapBase是IMemoryHeap接口的一个实现,MemoryBase是IMemory接口的一个实现。

MemoryHeapBase的定义如下所示:

class MemoryHeapBase  : public virtual BnMemoryHeap{

public :

}

4.7 Android的系统进程 85

几个重要系统进程为/init,/system/bin/servicemanager ,/system/bin/mediaserver,system_server及zygote

前面的init分析提到init通过解析init.rc,启动对应服务程序。servicemanager , zygote 和mediaserver都通过这种方式启动:system_server则通过zygote孵化出来。这几个进程是Android系统运行的基础,通过了解他们,可以展现一副Android运行是的全景图。

4.7.1 servicemanager

servicemanager是Binder的服务管理守护进程,也是Binder机制的核心,所有Binder服务都会通过他进行注册,客户端在通过他获取服务接口。

servicemanager是一个本地应用,位于:frameworks/base/cmds/servicemanager/,生成名为servicemanager的可执行文件。

servicemanager代码逻辑非常简洁

int  main(int args,char **argv){

struct  binder_state *bs;

void *svcmgr  = BINDER_SERVICE_MANAGER;

ba = binder_open(128*1024);

if(binder_become_context_manager(bs)){

LOGE("cannot become context manger(%s)\n",strerror(errno));

return  -1;

}

svcmgr_handle = svcmgr;

binder_loop(bs,svcmgr_handler);

return 0;

}

servicemanager的运行流程为:打开Binder驱动-->成为服务管理金曾--->进入binder_loop等待访问请求。

binder_loop 通过发送BINDER_WRITE_READ的ioctl命令给底层Binder驱动,一度去服务注册和获取服务接口等请求。再经由binder_parse,最终由svcmgr_handler完成处理。

支持的请求有:

enum{

}

添加服务的实质是在Binder驱动中创建对应的节点来完成。servicemanager中会维护一个服务列表,来跟踪服务状态。

servicemanager自身也是一个Binder服务,从binder_parse中可以看出。它处理来自客户端的BR_TRANSACTION,这是典型的Binder服务的请求处理流程。

4.7.1 servicemanager 85
4.7.2 zygote 87

zygot通过init进程启动,它是android运行时非常核心的部分。正如其名,zygote是Android  Java部分孵化器,也是Android  Java框架的基础。

zygote首先孵化出system_server,这是Android绝大多数系统服务的守护进程。之后所欲的android应用程序也都由它孵化而来。

第5章 Android的Java虚拟机和Java环境 88
5.1 Dalvik虚拟机和核心库 88

android的Javai基本运行环境包括虚拟机和核心库两个方面,虚拟机是Java运行的基础,核心库提供与标准Java SE兼容的类库。

Dalvik是Android程序的虚拟机,是Android中Java程序的运行基础。Dalvik虚拟机住哟啊完成对象生命周期管理、堆栈管理、线程管理、安全和一成管理、以及垃圾回收等重要功能。dalvik虚拟机是基于寄存器的,所有的类都经由Java编译器编译,Android中的"dx"工具将class装换成dex格式有虚拟机执行。

Dalvik虚拟机相关内容在android中是一个独立的代码路径:Dalvik/  其中包含了目标机和主机内容。

5.1.1 dex工具库和虚拟机的实现 89

5.1.2 核心库 90
5.1.3 nativehelper库 91
5.2 Android的Java程序环境 91
5.2.1 Java类的层次结构 91

在Android系统的层次结构中,自上而下,第三层次是Java程序的框架,第四层次是Java应用程序,在这之间是Java API,这是Android系统的基本API

Android的API层次结构包括主要包含以下部分:

Java标准API

java扩展API

企业和组织提供的java类库(org包)

Android的各种包(android 包)

这些包在dalvik/ 虚拟机的目录中dalvik/libcore进行了实现。

5.2.2 Android Java类的代码 92

java代码框架主要在frameworks/base/目录中。

其中主题部分将生成frameworks.jar包,最终将被防止在目标文件系统的/system/framewok目录中。

android中的Java库主要为android包及其子包,其核心目录为:

frameworks/base/graphics/java/:图形部分java类

frameworks/base/media/java/:媒体部分java类

frameworks/base/opengl/java/:OPENGL部分java类

frameworks/base/wifi/java/:WiFi部分java类

android的Java系统中具有资源文件的概念,例如可现实的图片、多语言字符串、布局文件、XML文件、纯数据文件等。一些内部资源文件也被生成一个jar包,
其路径为:frameworks/base/core/res/
这些内容最后会生成一个名称为framework-res.apk的包,这个包也被防止到目标文件系统/system/framework目录中

5.2.3 Android系统API 92

android系统对提供的API具有严格的组织形式,因为这些API是android系统保持兼容性的基础。

其中一个限制就是android代码中提供的API需要和API描述文件相匹配。

Android中Java类的API描述文件包含在frameworks/base/api/目录中,主要是其中的current.xml文件。current.xml文件的所有内容都包含在<api>标签中。

<api>

</api>

current.xml内部的内容组织十一包分类的。

如Activity:

5.3 JNI的使用 96

android系统中主要的JNI代码在以下的路径中。

frameworks/base/core/jni/

JNI标准成为Java平台的一部分,它允许Java代码和其他语言编写的代码进行交互。JNI是本地接口,它使得Java虚拟机(VM)内部运行的Java代码能够与其他编程语言(如C,C++和汇编语言)编写的应用程序和库进行交互操作。
5.3.1 JNI的架构和实现方式 97

在Android中提供JNI的方式,让Java程序可以调用C语言程序。Android中很多Java类都具有native接口,这些native接口就是有本地实现,然后注册到系统中的。

在android中,主要的JNI代码在一下的路径中:

frameworks/base/core/jni/

这个路径中的内容被编译成库libandroid_runtime.so,这就是一个普通的动态库,被放置在目标系统的/system/lib目录中

除此之外,android还包含其他的JNI库,例如媒体部分的JNI在目录frameworks/base/media/jni/中,被编译成库libmedia_jni.so.

JNI中的各个文件实际上就是C++的普通源文件,齐明明一般和支持的Java类友对应关系。这种关系是习惯上的写法,而不是强制的。

在Android中实现的JNI库,需要连接动态库libnativehelper.so

JNI在Android层次结构中的作用如图:

5.3.2 JNI的实现方式 97

实现JNI需要在Java代码中声明,在C++代码中实现JNI的各种方法,并注册到系统中。

使用JNI的核心是JNINativeMethod结构体,这个结构体在jni.h中定义

typedef struct{

const char* name;           /* JNI函数的名称*/

const char* signature;    /* 描述JNI函数的参数和返回值*/

void*  fnPtr;                       /* JNI函数对应的C语言的函数指针*/

}JNINativeMethod;

JNINativeMethod的第一个参数是字符串,JNI函数的名称,对应于java中使用的方法名称;第二个参数也是字符串,表示参数的返回值类型;地三个参数是JNI函数对应的C语言的函数指针。

JNI中使用的数据类型及对应字母

Java的类型

JNI的类型

对应字母

Java布尔类型(boolean)

jboolean

Z

Java 字节(byte)

jbyte(8位有符号)

B

Java字符(char)

jchar(16位无符号)

C

Java短整形(short)

jshort(16位有符号)

S

Java整形(int)

jint(32位有符号)

I

Java长整形(long)

jlong(64位有符号)

J

Java单精度浮点(float)

jfoat(IEEE754,32位)

F

Java 双进度浮点(double)

jdouble(IEEE754,64位)

D

Java 对象

jobject

L

Java无返回值

Void

V

例如:frameworks/base/core/jni 中的android_util_Log.cpp表示对android.util包中的Log类提供支持。这个文件首先定义了所实现的Java方法列表。

5.3.3 在应用程序中使用JNI 99
5.4 系统服务的Java部分 101
5.4.1 Binder 102

java Binder所在文件夹

frameworks/base/core/java/android/os/

frameworks/base/core/java/com/android/internal/os/

frameworks/base/core/jni/

Java部分的Binder原理与native层类似。

5.4.2 ServiceManager 103

5.4.3 系统进程 103

第6章 Android的GUI系统 106

本章介绍Android的
6.1 Android GUI系统综述 106

Android的GUI系统有C语言框架和Java语言框架组成。对下层,Android的GUI系统通过调用显示输出输入设备的驱动,从而将Android系统和底层的硬件联系起来。对上层

android的GUI系统提供了java层次的绘图结构,android的Java框架层调用这些绘图接口来构建各种UI元素,这些绘图接口也可以提供Java应用程序来调用。

PixelFlinger(下层的工具库);

libui(GUI的框架库);

SurfaceFlinger(Surface的管理和处理);

Skia图形图形引擎

OpenGL 3D引擎;

各种JNI(箱java层提供接口)

6.2 pixelflinger和libui库 108
6.2.1 pixelflinger 108
6.2.2 libui 108
6.2.3 输出/输入与硬件的接口 109
6.3 Surface系统 113

6.3.1 Surface系统本地接口 113
6.3.2 SurfaceFlinger本地代码 115
6.3.3 Surface的Java和JNI代码 119
6.4 Skia和2D图形系统 121
6.4.1 Skia底层库 121
6.4.2 Android图形系统的JNI接口 124
6.4.3 Android的图形包(graphics) 125
6.5 Android的OpenGL系统与3D图形系统 125

6.5.1 OpenGL的本地代码 125

6.5.2 OpenGL的JNI代码 130

6.5.3 OpenGL的Java类 130

第7章 Android的Audio系统 132
7.1 Audio系统综述 132

Audio系统在Android中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。这个部分作为Android的Audio系统的输入/输出层次,一般负责包房PCM声音输出和从外部获取PCM声音,以及管理声音设备和设置。

Audio系统主要分成如下几个层次:

1. media库提供的Audio系统本地部分接口:

2. AudioFlinger作为Audio系统中间层:

3. Audio的硬件抽象层提供底层支持:

4. Audio接口通过JNI和Java框架提供给上层。

Audio系统的各个层次接口主要提供两个方面功能:放音(Track)和录音(Recorder).

Android 的Audio系统结构如图:

Audio系统的代码分布

1. audio的Java部分 代码路径:frameworks/base/media/java/android/media

2. Audio的JNI部分  代码路径:  frameworks/base/core/jni

3. Audio的框架部分: 头文件路径:frameworks/base/include/media/

源代码路径:frameworks/base/media/libmedia

4. Audio Flinger

5. Audio的硬件抽象层接口

7.2 Audio系统和上层接口 134
7.2.1 Audio系统的各个层次 134
7.2.2 media库中的Audio框架部分 135
7.2.3 AudioFlinger本地代码 138
7.2.4 Audio系统的JNI代码 140
7.2.5 Audio系统的Java代码 142

7.3 Audio的硬件抽象层 142

7.3.1 Audio硬件抽象层的接口定义 142
7.3.2 AudioFlinger中自带Audio硬件抽象层实现 144
7.3.3 Audio硬件抽象层的真正实现 150

第8章 Android的Video输入输出系统 151
8.1 Video输入输出系统综述 151
8.1.1 Android的Overlay系统结构 152
8.1.2 Android的Camera系统结构 153
8.2 Overlay系统 155
8.2.1 Overlay系统的框架部分定义 156
8.2.2 SurfaceFlinger系统的Overlay部分 158
8.3 Overlay的硬件抽象层 161
8.3.1 Overlay系统硬件抽象层的接口 161
8.3.2 Overlay系统硬件实现框架 164
8.3.3 Overlay系统硬件实现的注意事项 166
8.4 Camera系统与上层接口 169
8.4.1 Camera本地代码框架 169
8.4.2 CameraService 176
8.4.3 Camera的JNI代码 179
8.4.4 Camera的Java代码 182
8.5 Camera的硬件抽象层 182
8.5.1 Camera硬件抽象层的接口定义 182
8.5.2 Camera硬件抽象层的桩实现 184
8.5.3 Camera硬件抽象层的硬件实现 188

第9章 Android的多媒体系统 190
9.1 Android多媒体系统的结构和业务 190
9.1.1 多媒体系统的宏观结构 190
9.1.2 多媒体的各种业务 192
9.2 多媒体系统的各个层次 199
9.2.1 libmedia的框架部分 199
9.2.2 多媒体服务 208
9.2.3 多媒体部分的JNI代码 213
9.2.4 多媒体部分的Java框架代码 215
9.2.5 android.widget.VideoView类 216
9.3 多媒体实现的核心部分OpenCore 216
9.3.1 OpenCore概述 216
9.3.2 OpenCore的层次结构 217
9.3.3 OpenCore的OSCL部分 219
9.3.4 OpenCore的文件格式和编解码部分 221
9.3.5 OpenCore 的Node 222
9.3.6 OpenCore 的功能扩展 223
9.3.7 OpenCore的 Player 226
9.3.8 OpenCore 的Author 236

第10章 Android的电话部分 243
10.1 Android电话部分综述 243
10.2 Modem驱动 243
10.3 本地的RIL代码 245
10.3.1 简介 245
10.3.2 RILD守护进程 246
10.3.3 libril库 247
10.3.4 RIL的实现库Reference RIL 247
10.3.5 Request(请求)流程 248
10.3.6 Response(响应)流程 249
10.3.7 RIL的移植工作 251
10.4 Java框架及应用 251
10.4.1 基本架构 252
10.4.2 呼叫 255
10.4.3 短信 256
10.4.4 数据连接 257
10.4.5 其他框架部分及其他应用 258

第11章 Android的连接部分 259
11.1 WiFi部分 259
11.1.1 WiFi基本架构 259
11.1.2 WiFi本地实现 260
11.1.3 WiFi的Java和JNI 263
11.1.4 Settings中的WiFi设置 265
11.1.5 WiFi工作流程实例 265
11.2 蓝牙部分 267
11.2.1 蓝牙基本架构 268
11.2.2 蓝牙用户空间库bluez 269
11.2.3 bluez适配层 272
11.2.4 蓝牙的JNI和Java部分 272
11.3 GPS和定位部分 280
11.3.1 定位系统基本架构 281
11.3.2 定位系统驱动层 281
11.3.3 GPS本地实现 282
11.3.4 GPS JNI实现 283
11.3.5 定位系统Java实现 284

第12章 Android的传感器系统 286
12.1 传感器系统综述 286
12.2 传感器系统层次结构 288
12.2.1 传感器系统的各个层次 288
12.2.2 传感器系统的JNI 288
12.2.3 传感器系统的Java代码 290
12.3 传感器系统的硬件抽象层 291
12.3.1 传感器系统硬件抽象层的接口定义 291
12.3.2 传感器系统硬件抽象层的示例实现 293
12.3.3 传感器系统硬件抽象层的实现要点 296
12.4 Sensor的使用 296

第13章 Android应用程序概述及框架 299
13.1 Android应用程序的开发方式 299

android应用程序可以基于两种环境来开发:android SDK和android源代码。
13.2 Android应用程序的内容 300
13.2.1 Android应用程序的概念性描述 300
13.2.2 应用程序包含的各个文件 305
13.2.3 使用am工具启动Android应用程序 306
13.3 Android应用程序示例 308
13.3.1 HelloActivity程序 308
13.3.2 HelloActivity的源代码结构 308
13.3.3 HelloActivity的编译结构(源代码开发) 312
13.3.4 HelloActivity的编译结构(SDK开发) 314
13.4 Android 应用层API参考文档 315

第14章 Android应用程序的主要方面 317
14.1 应用的基本控制 318
14.1.1 UI元素及其控制 318
14.1.2 屏幕间的跳转 320
14.1.3 弹出对话框和菜单 324
14.1.4 样式的设置 328
14.1.5 使用服务 331
14.1.6 使用广播接收器 337
14.2 各种UI元素的使用 339
14.2.1 基本的UI元素 340
14.2.2 视图组的使用 345
14.2.3 自定义的视图 353
14.2.4 滚动视图的使用 354
14.2.5 布局(Layout) 355
14.2.6 网格(Grid)视图组 359
14.2.7 列表(List)视图组 360
14.2.8 使用Tab 362
14.3 图形API的使用 363
14.3.1 2D图形的API 363
14.3.2 3D图形的API 366

第15章 Android应用程序的设计思想 369
15.1 Android程序思想 369
15.1.1 Java 源程序思想 369
15.1.2 资源的思想 373
15.1.3 工程描述文件的思想 375
15.1.4 三位一体的思想 376
15.1.5 安全性和权限 378
15.1.6 App Widget的使用 379
15.2 Android应用开发实例 381
15.2.1 GUI依赖类的程序 382
15.2.2 单独模块类程序 387
15.3 Android的设计理念 393

[Android系统原理及开发要点详解相关推荐

  1. Linux设备驱动程序(第三版)/深入理解计算机系统(原书第2版)/[Android系统原理及开发要点详解].(韩超,梁泉)百度云盘下载

    文档下载云盘连接:http://pan.baidu.com/s/1dDD2sgT 更多其他资料,请关注淘宝:http://shop115376623.taobao.com/ http://item.t ...

  2. Android 系统属性读取和设置详解

    Android 系统属性读取和设置详解 一.在adb中进行属性读取和设置 1.Settings Provider设置和读取 获取 设置 2.SystemProperties属性读取和设置 二.Andr ...

  3. android 辅助功能原理,Android辅助功能原理与基本使用详解-AccessibilityService

    Android辅助功能原理与基本使用详解-AccessibilityService 辅助功能原理与基本使用详解 本文主要介绍辅助功能的使用 辅助功能基本原理 辅助功能基本配置和框架搭建 辅助功能实战解 ...

  4. flutter 获取android 还是ios_Flutter完整开发实战详解(二十、 Android PlatformView 和键盘问题)...

    作为系列文章的第二十篇,本篇将结合官方的技术文档科普 Android 上 PlatformView 的实现逻辑,并且解释为什么在 Android 上 PlatformView 的键盘总是有问题. 为什 ...

  5. 汽车电子ECU bootloader开发要点详解

    引言 1. bootloader的功能 2. 如何建立可靠的总线通信? 3. 解析编程文件(S19/HEX/BIN) 4. NVM驱动程序开发 5. bootloader开发的其他要点 a. boot ...

  6. 【UDS统一诊断服务】(补充)五、ECU bootloader开发要点详解 (1)

    文章目录 引言 1. bootloader的功能 2. 如何建立可靠的总线通信? 重要说明: 3. 解析编程文件(S19/HEX/BIN) 引言 bootloader的功能 如何建立可靠的总线通信? ...

  7. Android 系统Dimension和间距参数详解

    Android作为一个开放性的手持装置作业系统,势必面对终端显示器有多种不同规格的情况,这对程式开发者会有一定程度的困扰.  意图成为"云端的微软"的Google自然不会傻到任由开 ...

  8. android mupdf 快速开发,android 使用mupdf开源开发pdf详解

    最近由于在开发一款需要上线的电子阅读器,现在详细讲述一下pdf模块部分的分享. 在网上找了好多的开源pdf的源代码,都不是太好,其中看到的最好的是开源的mupdf,优化做的很好,解析的比较快,所以需要 ...

  9. Android USB转串口通信开发实例详解

    好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基 ...

  10. Android 笑话+html 实例开发(详解)

    下载地址:http://static.apk.hiapk.com/html/2012/05/591429.html ---------HahamxActivity --------- package ...

最新文章

  1. 查看磁盘uuid命令_Win10推出新的命令行工具,可以查看磁盘空间使用情况
  2. 【自动化测试】整理各种测试开发工具!持续更新
  3. vue报错:dependencies were not found: * element-ui in ./src/main.js * element-ui/lib/theme-chalk/inde
  4. 使用SafeViewFlipper避免ViewFlipper交替时Crash
  5. 信安教程第二版-第18章网络安全测评技术与标准
  6. 设计模式(十三): 命令模式
  7. php 复选框 未选,php – 在表单发布时如何获取复选框元素中未选中复选框的值?...
  8. 为什么要避免不可重复读_浅谈游戏的耐玩性-玩家为什么要重复打开你的游戏?...
  9. 哈佛商学院教授对毕业生讲
  10. 安全技巧:映像劫持与反劫持技术
  11. 【每周荐书系列】——《认知盈余》
  12. python代码格式化神器_牛逼啊!一个随时随地写Python代码的神器
  13. 企业微信开发实战(二、OA审批之获取审批模版详情提交审批申请)
  14. 怎么创建自己的网站?创建自己网站的步骤
  15. 福利,架构师之路定制T恤
  16. 宝德服务器——企业需要真正的按需定制产品
  17. PCB的埋孔、盲孔、通孔
  18. python画八卦_python编程也能八卦?
  19. 企业管理不可忽视“工作日志”
  20. 【管理学视频课程】TOC制约理论的…

热门文章

  1. UE4 合并静态网格体
  2. 计算机基础西南大学,西南大学计算机基础.docx
  3. 树莓派Android Things物联网开发:已知Bug发行说明
  4. 入职5年前端工程师针对web前端小白,作出的职业规划建议
  5. 波浪能及波能流的推导
  6. cm12 for 三星n7100编译
  7. springboot疫情防控下基于微信小程序的食堂订餐系统毕业设计源码261620
  8. [读书笔记] 蔡康永的说话之道
  9. Correct way to wait for VBLANK on windows 10 in windowed mode
  10. Java打开exe文件