Android 技术专题系列之七 -- 输入法 框架(2009-03-02 14:25:25)
标签:android 中文 输入法 结构图 架构图 解析 手机操作系统 智能手机 it 分类:android
Android的输入法框架比价复杂。从进程的角度来讲,相关功能主要分布在下面三个位置:
客户端应用是一个包含有图形界面的应用,如地址本。图形界面上包含有能够接收输入的编辑框,如TextView。
输入法模块提供软键盘,将用户在软键盘上的按键输入根据某种算法(如Zi, T9, 国笔等)转换成单词,然后传递给客户端应用。目录development/samples/SoftKeyboard下提供了一个输入法模块实例。如果想要实现一个中文输入法,可参考这个实例。
平台部分实现一些管理功能,负责装载某个输入法模块,启动,终止该模块等。
相关代码主要位于下面几个位置。其中,位于3,5,6,7目录下的代码最值得关注。
1. frameworks/base/core/java/com/android/internal/view
这个目录下定义了几个重要的idl 接口。
IInputMethod.aidl 定义了IInputMethod idl 接口,用于客户端跨进程操作InputMethod接口。
IInputMethodSession.aidl 定义了IInputMethodSession接口,是IInputMethod的辅助接口。用于客户端跨进程操作InputMethodSession接口。
IInputMethodCallback.aidl定义了一个helper 接口,由客户端实现。IInputMethod.aidl和IInputMethodSession.aidl实例可以分别调用该接口中的不同方法
IInputMethodManager.aidl 定义了Input Method Manager的service接口。客户端通过InputMethodManager interface调用这个service。
InputMethodManagerService.java实现了IInputMethodManager.aidl接口
IInputMethodClient.aidl定义接口,标识一个Input Method Manager 的客户。这个service在客户端实现,提供给server端调用。
IInputContext.aidl定义了一个接口,由客户端提供InputMethod使用。InputMethod可以与客户端交互,调用客户端提供的callback。
IInputConnectionWrapper.java 实现了IInputContext接口。
IInputContextCallback.aidl定义了一个接口,定义了一组callback函数给IInputContext.aidl实例调用,从客户端返回信息给InputMethod。
InputConnectionWrapper.java实现了IInputContextCallback接口。
2. frameworks/base/services/java/com/android/server
InputMethodManagerService.java实现了IInputMethodManager.aidl接口
3. frameworks/base/core/java/android/view/inputmethod
这个目录下定义了几个重要的interface和类。
InputMethodManager.java实现了InputMethodManager 类。此类调用IInputMethodManager.aidl接口功能,而IInputMethodManager.aidl接口功能由InputMethodManagerService.java实现,并运行在不同于客户端进程的server进程中。
InputConnection.java定义了InputConnection interface。InputConnection 接口在输入法和客户端之间建立了一个连接,输入法可以使用该连接获取或发送信息给客户端。InputConnection实例由客户端创建之后传递给输入法使用。BaseInputConnection.java 实现了InputConnection接口的一个基类: BaseInputConnection。 EditableInputConnection.java实现了一个派生类
InputBinding.java 定义了类InputBinding,这个类实现了parcelable 接口。这个类的成员变量包含了客户端传向server的信息。
InputMethod.java定义了InputMethod interface。文件InputMethodService.java中类InputMethodImpl实现了这个接口。这个接口定义了一套操纵一个输入法的方法。如,createSession,startInput等。要编写一个具体输入法的话,就需要派生这个接口。
InputMethodSession.java定义了InputMethodSession接口。文件InputMethodService.java中类InputMethodSessionImpl实现了这个接口。InputMethodSession是InputMethod的辅助接口,用于具体和某个输入法客户端交互。
CompletionInfo.java 类描述一个text completion.
EditorInfo.java类描述一个接收输入的view的属性,如内容属性(text, digit, etc)。
ExtractedText.java类描述从view中提取的传递给输入法的文本属性。
4. frameworks/base/core/java/com/android/internal/widget
EditableInputConnection.java实现了BaseInputConnection的一个派生类。
5. frameworks/base/core/java/android/inputmethodservice
这个目录下的代码提供了实现一个具体输入法的框架类。从这些类派生,就可以定制一个输入法。
SoftInputWindow.java中的SoftInputWindow类是一个Dialog子类。它代表一个输入法的顶级窗口(由窗口管理器管理),这个窗口由上到下,包含extractArea, candidatesArea, 和 inputArea。
Keyboard.java 中的Keyboard类装载并解析一个描述虚拟键盘(Soft Keyboard)的xml文件(如development/samples/SoftKeyboard/res/xml),并存储该键盘的属性,如该虚拟键盘包含多上行,每行有哪些键等。
KeyboardView.java 中的KeyboardView类是一个View子类。它根据Keyboard数据结构真正的在screen上画出一个虚拟键盘。这个虚拟键盘就是SoftInputWindow中的inputArea。
AbstractInputMethodService是Service的派生类,并实现了KeyEvent.Callback 接口。实现了InputMethod 和 InputMethodSession的基类。dispatchKeyEvent 函数将收到的key event传给相应的key 处理函数(在派生类中实现)。当这个service被客户端绑定时,其onBind()函数给客户端返回了一个IInputMethodWrapper实例,这个实例实现了IInputMethod idl接口。客户端可以使用该接口的相关功能。
IInputMethodWrapper.java 实现了IInputMethod idl 接口。这个类收到客户端的跨进程命令后,调用InputMethod完成相应功能。
IInputMethodSessionWrapper.java 实现了IInputMethodSession idl接口。这个类收到客户端的跨进程命令后,调用InputMethodSession完成相应功能。
6. frameworks/base/core/res/res/layout
这个目录下存放着一些系统资源。其中,
input_method.xml描述了一个输入法的窗口(即SoftInputWindow)布局,从上往下,依次排列extractArea, candidatesArea 和 inputArea。
input_method_extract_view.xml。
7. development/samples/SoftKeyboard
这个目录下代码实现了一个的输入法实例--软键盘英文/数字输入法。这里面实现的类大都是从frameworks/base/core/java/android/inputmethodservice 中的类派生而来。
AndroidManifest.xml:描述这个.apk提供的service以及关于这个输入法的一些信息。
res/xml/目录下存储着几个描述不同虚拟键盘的xml文件。
LatinKeyboard.java中的LatinKeyboard类是Keyboard的子类。
LatinKeyboardView.java中的LatinKeyboardView类是KeyboardView的子类。
8. frameworks/base/core/java/android/widget
在这里TextView.java是使用Input Method Framework (IMF)的客户端。TextView创建了一个InputMethodManager的实例并调用其restartInput 函数。
InputMethodManager::restartInput函数创建了一个InputConnection 实例并调用IInputMethodManager::startInput。
IInputMethodManager::startInput 函数使用mContext.bindService启动一个InputMethod service, 如 Sample Soft Keyboard。
9. frameworks/base/core/java/com/android/internal/widget
2009年8月17日 星期一
Android 技术专题系列之十一 -- DRM(2009-04-26 13:10:45)
Android 技术专题系列之十一 -- DRM(2009-04-26 13:10:45)
标签:drm android it 分类:android
简而言之,DRM系统提供一套机制对用户使用手机上的媒体内容(如ringtong, mp3等)进行限制,如限制拷贝给第三方,限制使用次数或时限等,从而保护内容提供商的权利。建议读者可以阅读OMA DRM 的规范,以便更好的了解代码。
相关代码主要位于下列目录:
frameworks/base/media/java/android/drm/mobile1
frameworks/base/media/libdrm/moblile1
frameworks/base/media/libdrm/mobile2
packages/apps/Mms/src/com/android/mms/drm: drm
packages/providers/DrmProvider/src/com/android/providers/drm
下面先作简要分析:
frameworks/base/media/libdrm/moblile1应该是提供OMA DMA1.0的本地/c++ 实现
frameworks/base/media/libdrm/moblile2应该是提供OMA DAM2.0的本地/c++ 实现。
frameworks/base/media/java/android/drm/mobile1 对应用提供OMA DRM 1.0 (即frameworks/base/media/libdrm/moblile1)的java接口。目前尚没有OMA DRM 2.0的java接口,也就意味着OMA DRM 2.0在Android中尚未应用。
packages/apps/Mms/src/com/android/mms/drm 实现在MMS中如何使用DRM。
packages/providers/DrmProvider/src/com/android/providers/drm ?
下面再作具体介绍:
一 目录 frameworks/base/media/java/android/drm/mobile1
这个目录是OMA DRM 1.0的java 接口。
OMA DRM 1.0 定义了几个重要概念:
DRM消息(DRM message):用户下载的一条DRM内容。根据下面介绍的DRM内容 传输方式的不同,DRM消息中包含的内容亦有所不同,可能只包含一个未经加密的媒体对象;也可能即包含未加密的媒体对象,也包含一个权利对象;也可能只包含一个经过加密的媒体对象(.dcf)。
媒体对象 (media object):包含媒体资源,如一个mp3, ringtone等。
权利对象(Right object): 限制用户如何使用媒体对象。
OMA DRM 1.0 定义了DRM内容的四种传输方式:
1. Combined delivery: 这种传输方式中,媒体对象以未经加密的方式(plain) 与Right object打成一个包,一块传输。这个包下载到手机设备上后,不允许转发给其他设备。
2. Forward lock: 这种传输方式是combined delivery的一个特例。媒体对象没有对应的Rigth object。媒体对象不允许转发给其他设备
3. Separate delivery: 媒体对象和权利对象分别传输。媒体对象采用对称密钥加密,文件以.dcf为后缀。权利对象中则包含对应的密钥。
4. Superdistribution:类似separate delivery, 但媒体内容允许转发给其他设备。
相应地,本目录的代码中:
DrmConstraintInfo对象描述了(对媒体内容的)一组限制属性,如开始/结束使用日期,使用次数等;
DrmRights对象代表了一个OMA 权利对象。
DrmRightsManager管理设备上的Rigth Objects。所有下载的权利对象,不论是由separate delivery 还是 combined delivery,权利对象都要首先安装到设备上。
DrmRawContent代表一条DRM内容,分为两类:DRM_MIMETYPE_MESSAGE_STRING --DRM内容是经combined delivery 或 forward lock传输的 (也即媒体对象没有加密,没有或者有一个权利对象); DRM_MIMETYPE_CONTENT_STRING -- DRM内容是经 separate delivery传输的(也即媒体对象是经过加密的dcf格式,不包含权利对象)。
DrmInputStream:这个对象从一个DrmRawContent对象中读出经过权利对象验证并解密后的(需要的话)媒体对象内容。这个内容之后就可以传给相关应用输出给用户。
二 目录frameworks/base/media/libdrm/moblile1
本目录真正实现DRM DRM 1.0。
drm1_jni.c提供对DrmRawContent中方法的本地实现;
objmng目录下是具体实现。frameworks/base/media/libdrm/mobile1/include/objmng/svc_drm.h中有关于每个方法的详细解释,基本思路是每打开一个Drm 内容,就创建一个session,然后提供一系列方法,以此session为参数,对Drm进行各种操作,如获取属性,读取解密后内容等。这里不再赘述。
标签:drm android it 分类:android
简而言之,DRM系统提供一套机制对用户使用手机上的媒体内容(如ringtong, mp3等)进行限制,如限制拷贝给第三方,限制使用次数或时限等,从而保护内容提供商的权利。建议读者可以阅读OMA DRM 的规范,以便更好的了解代码。
相关代码主要位于下列目录:
frameworks/base/media/java/android/drm/mobile1
frameworks/base/media/libdrm/moblile1
frameworks/base/media/libdrm/mobile2
packages/apps/Mms/src/com/android/mms/drm: drm
packages/providers/DrmProvider/src/com/android/providers/drm
下面先作简要分析:
frameworks/base/media/libdrm/moblile1应该是提供OMA DMA1.0的本地/c++ 实现
frameworks/base/media/libdrm/moblile2应该是提供OMA DAM2.0的本地/c++ 实现。
frameworks/base/media/java/android/drm/mobile1 对应用提供OMA DRM 1.0 (即frameworks/base/media/libdrm/moblile1)的java接口。目前尚没有OMA DRM 2.0的java接口,也就意味着OMA DRM 2.0在Android中尚未应用。
packages/apps/Mms/src/com/android/mms/drm 实现在MMS中如何使用DRM。
packages/providers/DrmProvider/src/com/android/providers/drm ?
下面再作具体介绍:
一 目录 frameworks/base/media/java/android/drm/mobile1
这个目录是OMA DRM 1.0的java 接口。
OMA DRM 1.0 定义了几个重要概念:
DRM消息(DRM message):用户下载的一条DRM内容。根据下面介绍的DRM内容 传输方式的不同,DRM消息中包含的内容亦有所不同,可能只包含一个未经加密的媒体对象;也可能即包含未加密的媒体对象,也包含一个权利对象;也可能只包含一个经过加密的媒体对象(.dcf)。
媒体对象 (media object):包含媒体资源,如一个mp3, ringtone等。
权利对象(Right object): 限制用户如何使用媒体对象。
OMA DRM 1.0 定义了DRM内容的四种传输方式:
1. Combined delivery: 这种传输方式中,媒体对象以未经加密的方式(plain) 与Right object打成一个包,一块传输。这个包下载到手机设备上后,不允许转发给其他设备。
2. Forward lock: 这种传输方式是combined delivery的一个特例。媒体对象没有对应的Rigth object。媒体对象不允许转发给其他设备
3. Separate delivery: 媒体对象和权利对象分别传输。媒体对象采用对称密钥加密,文件以.dcf为后缀。权利对象中则包含对应的密钥。
4. Superdistribution:类似separate delivery, 但媒体内容允许转发给其他设备。
相应地,本目录的代码中:
DrmConstraintInfo对象描述了(对媒体内容的)一组限制属性,如开始/结束使用日期,使用次数等;
DrmRights对象代表了一个OMA 权利对象。
DrmRightsManager管理设备上的Rigth Objects。所有下载的权利对象,不论是由separate delivery 还是 combined delivery,权利对象都要首先安装到设备上。
DrmRawContent代表一条DRM内容,分为两类:DRM_MIMETYPE_MESSAGE_STRING --DRM内容是经combined delivery 或 forward lock传输的 (也即媒体对象没有加密,没有或者有一个权利对象); DRM_MIMETYPE_CONTENT_STRING -- DRM内容是经 separate delivery传输的(也即媒体对象是经过加密的dcf格式,不包含权利对象)。
DrmInputStream:这个对象从一个DrmRawContent对象中读出经过权利对象验证并解密后的(需要的话)媒体对象内容。这个内容之后就可以传给相关应用输出给用户。
二 目录frameworks/base/media/libdrm/moblile1
本目录真正实现DRM DRM 1.0。
drm1_jni.c提供对DrmRawContent中方法的本地实现;
objmng目录下是具体实现。frameworks/base/media/libdrm/mobile1/include/objmng/svc_drm.h中有关于每个方法的详细解释,基本思路是每打开一个Drm 内容,就创建一个session,然后提供一系列方法,以此session为参数,对Drm进行各种操作,如获取属性,读取解密后内容等。这里不再赘述。
Android 技术专题系列之十二 -- Alarm manager(2009-04-27 11:21:35)
Android 技术专题系列之十二 -- Alarm manager(2009-04-27 11:21:35)
标签:alarm manager android it 分类:android
Alarm manager 主要管理硬件时钟。一些与时间相关的应用,如日历,闹钟等需要使用Alarm Manager的服务。Alarm manager功能相对比较简单,相关代码位于
frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
frameworks/base/services/java/com/android/server/AlarmManagerService.java
一. frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
这部分代码直接管理硬件时钟,设备名为/dev/alarm。包括打开设备,关闭设备,设置时区,设置触发时间 (timeout),以及等待时钟触发。
二. frameworks/base/services/java/com/android/server/AlarmManagerService.java
这部分封装目录一中的代码,向上提供java接口,同时与客户端(如calendar)交互,接收来自客户端的时钟设置请求,并在时钟触发时通知客户端。
标签:alarm manager android it 分类:android
Alarm manager 主要管理硬件时钟。一些与时间相关的应用,如日历,闹钟等需要使用Alarm Manager的服务。Alarm manager功能相对比较简单,相关代码位于
frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
frameworks/base/services/java/com/android/server/AlarmManagerService.java
一. frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
这部分代码直接管理硬件时钟,设备名为/dev/alarm。包括打开设备,关闭设备,设置时区,设置触发时间 (timeout),以及等待时钟触发。
二. frameworks/base/services/java/com/android/server/AlarmManagerService.java
这部分封装目录一中的代码,向上提供java接口,同时与客户端(如calendar)交互,接收来自客户端的时钟设置请求,并在时钟触发时通知客户端。
ndroid 技术专题系列之十五 -- 更新开发手机到1.5
ndroid 技术专题系列之十五 -- 更新开发手机到1.5(2009-05-15 11:14:18)
标签:dev phone 开发手机 升级 image android it 分类:android
参照http://www.htc.com/www/support/android/adp.html,下面是在Android 开发手机上更新1.5 image的步骤 (主机是ubuntu Hardy):
1. 下载必要的image。
Radio image: ota-radio-2_22_19_26I.zip
Recovery image: signed-dream_devphone-ota-147201.zip
2. 在主机上创建文件/etc/udev/rules.d/50-android.rules,内容:
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
并修改文件属性:
chmod a+rx /etc/udev/rules.d/50-android.rules
然后重启机器
3. 将主机和Android开发手机通过usb 相连,运行命令 (./adb 命令来自sdk的tools)
./adb devices
应当看到一个device被列出。
4.参见http://www.htc.com/www/support/android/adp.html的 Update the Device Radio Firmware一节 ,更新firmware
5.参见http://www.htc.com/www/support/android/adp.html的 Copy the Recovery Image Package to the device一节 ,更新系统。
6. 切换到中文环境
./adb shell
$ su -
# setprop persist.sys.language zh;setprop persist.sys.country CN;stop;sleep 5;start
运行步骤6后,能看到有些应用的图标是中文,如"google 地图“。但大部分图标/环境仍然是英文。这应该是由于应用没有带中文语言包的缘故。读者可以试着安装一些带中文语言报的测试程序验证是否能够显示中文
标签:dev phone 开发手机 升级 image android it 分类:android
参照http://www.htc.com/www/support/android/adp.html,下面是在Android 开发手机上更新1.5 image的步骤 (主机是ubuntu Hardy):
1. 下载必要的image。
Radio image: ota-radio-2_22_19_26I.zip
Recovery image: signed-dream_devphone-ota-147201.zip
2. 在主机上创建文件/etc/udev/rules.d/50-android.rules,内容:
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
并修改文件属性:
chmod a+rx /etc/udev/rules.d/50-android.rules
然后重启机器
3. 将主机和Android开发手机通过usb 相连,运行命令 (./adb 命令来自sdk的tools)
./adb devices
应当看到一个device被列出。
4.参见http://www.htc.com/www/support/android/adp.html的 Update the Device Radio Firmware一节 ,更新firmware
5.参见http://www.htc.com/www/support/android/adp.html的 Copy the Recovery Image Package to the device一节 ,更新系统。
6. 切换到中文环境
./adb shell
$ su -
# setprop persist.sys.language zh;setprop persist.sys.country CN;stop;sleep 5;start
运行步骤6后,能看到有些应用的图标是中文,如"google 地图“。但大部分图标/环境仍然是英文。这应该是由于应用没有带中文语言包的缘故。读者可以试着安装一些带中文语言报的测试程序验证是否能够显示中文
Android 技术专题系列之十六 -- 在模拟器上安装 sd(2009-05-18 17:25:26)
Android 技术专题系列之十六 -- 在模拟器上安装 sd(2009-05-18 17:25:26)
标签:sd music 安装 mount emulator android it 分类:android
本文基于http://blog.jayway.com/2009/04/22/working-with-sd-cards-in-the-android-emulator/。特此申明。
今天想玩玩Android模拟上的music应用,可总是报告没有sd卡。网上搜了一下,有一哥们有一完整的解决方案(见上述连接)。这儿我将要点列在下面:
1.创建sd card image:
./mksdcard 1024M sdcard.img
2. 拷贝媒体文件, 如xxx.mp3, 到sd card image上。我考了一个我最喜欢的《滚滚长江东逝水》,呵呵。
sudo mount -o loop sdcard.img /mnt
cp xxx.mp3 /mnt
sudo umount /mnt
3. 创建一个AVD (Android Virtual Device)
./android create avd --name myAVD --target 2 --sdcard sdcard.img
这个命令会有很多选项让你确认,我只管一路回车。
4. 启动emulator
./emulator -avd myAVD
现在就可以打开music应用,欣赏音乐了。
标签:sd music 安装 mount emulator android it 分类:android
本文基于http://blog.jayway.com/2009/04/22/working-with-sd-cards-in-the-android-emulator/。特此申明。
今天想玩玩Android模拟上的music应用,可总是报告没有sd卡。网上搜了一下,有一哥们有一完整的解决方案(见上述连接)。这儿我将要点列在下面:
1.创建sd card image:
./mksdcard 1024M sdcard.img
2. 拷贝媒体文件, 如xxx.mp3, 到sd card image上。我考了一个我最喜欢的《滚滚长江东逝水》,呵呵。
sudo mount -o loop sdcard.img /mnt
cp xxx.mp3 /mnt
sudo umount /mnt
3. 创建一个AVD (Android Virtual Device)
./android create avd --name myAVD --target 2 --sdcard sdcard.img
这个命令会有很多选项让你确认,我只管一路回车。
4. 启动emulator
./emulator -avd myAVD
现在就可以打开music应用,欣赏音乐了。
Android 技术专题系列之十八-- 媒体文件管理
Android 技术专题系列之十八-- 媒体文件管理(2009-05-19 17:32:47)
本文引用了http://letsgoustc.spaces.live.com/Blog/cns!89AD27DFB5E249BA!473.entry部分内容,特此申明。
Android平台上的媒体文件管理和桌面系统不同。在桌面系统上,不同目录下的媒体文件呈树状结构显示给用户,用户需要进入不同目录寻找该目录下的文件。而在Android平台上,不同目录下的媒体文件则以一层列表方式显示给用户,用户不需进入子目录就可以列出(某种类型的)所有媒体文件。
在Android上,为了实现这种模式的媒体文件管理,对所有管理的媒体文件抽取其元数据(mp3文件包含的元数据可参考http://en.wikipedia.org/wiki/ID3),存储在数据库中,并作为一个content provider提供给其他应用使用。用户的每一次显示媒体文件的操作,就是对这个数据库的一次查询操作。
实现这一功能的代码位于
frameworks/base/core/java/android/provider/MediaStore.java
packages/providers/MediaProvider/src/com/android/providers/media.
frameworks/base/media/java/android/media/MediaScanner*
frameworks/base/media/jni/android_media_*
external/opencore/android/mediascanner.cpp
下面略作分析:
external/opencore/android/mediascanner.cpp负责从媒体文件(mp3, mp4, wma等)中提取元数据。
Android平台上的媒体文件管理和桌面系统不同。在桌面系统上,不同目录下的媒体文件呈树状结构显示给用户,用户需要进入不同目录寻找该目录下的文件。而在Android平台上,不同目录下的媒体文件则以一层列表方式显示给用户,用户不需进入子目录就可以列出(某种类型的)所有媒体文件。
在Android上,为了实现这种模式的媒体文件管理,对所有管理的媒体文件抽取其元数据(mp3文件包含的元数据可参考http://en.wikipedia.org/wiki/ID3),存储在数据库中,并作为一个content provider提供给其他应用使用。用户的每一次显示媒体文件的操作,就是对这个数据库的一次查询操作。
实现这一功能的代码位于
frameworks/base/core/java/android/provider/MediaStore.java
packages/providers/MediaProvider/src/com/android/providers/media.
frameworks/base/media/java/android/media/MediaScanner*
frameworks/base/media/jni/android_media_*
external/opencore/android/mediascanner.cpp
下面略作分析:
external/opencore/android/mediascanner.cpp负责从媒体文件(mp3, mp4, wma等)中提取元数据。
Android 技术专题系列之九 -- 图形系统
Android 技术专题系列之九 -- 图形系统(2009-04-03 10:45:41)
本文试图讲述Android图形系统的底层实现。Android图形系统底层实现非常复杂,文档较少,没有使用比较流行的图形组建如X window, Cairo等。
Android中的图形系统采用Client/Server架构。Server (即SurfaceFlinger)主要由c++代码编写而成。Client端代码分为两部分,一部分是由Java提供的供应用使用的api,另一部分则是由c++写成的底层实现。下图概要介绍了android图形系统的架构以及使用到的主要组件。


Android图形系统中一个重要的概念和线索是surface。View及其子类(如TextView, Button)要画在surface上。每个surface创建一个Canvas对象 (但属性时常改变),用来管理view在surface上的绘图操作,如画点画线。每个canvas对象对应一个bitmap,存储画在surface上的内容。
每个Surface通常对应两个buffer,一个front buffer, 一个back buffer。其中,back buffer就是canvas绘图时对应的bitmap (研究android_view_Surface.cpp::lockCanvas)。因此,绘画总是在back buffer上,需要更新时,则将back buffer和front buffer互换。
The window is tied to a Surface and the ViewRoot asks the Surface for a
Canvas that is then used by the Views to draw onto. After View draw its data to canvas, ViewRoot
will call surface.unlockCanvasAndPost(canvas) to schedule surfaceFlinger::composeSurfaces() which do the actually display to display panel. SurfaceFlinger handles to transfers drawn data in canvas to surface front buffer or backbuffer
Except for SurfaceViews, different views within the same ViewRoot share the same surface.
Layer的概念:
有几个对象与Surface概念紧密相关:
1. Java Surface (frameworks/base/core/java/android/view/Surface.java)。该对象被应用间接调用(通过SurfaceView, ViewRoot等), 应用需要创建surface,(并同时创建canvas), 将图形绘制到这个对象上并最终投递到屏幕上。
2. C++ Surface (frameworks/base/libs/ui/Surface.cpp。 这个对象被Java Surface通过Jni 调用,实现Java Surface 的功能
3. ISurface (以及其派生类BnSurface)。这个对象是应用和server之间的接口。C++ Surface创建这个ISurface (BnSurface)并发送命令,如更新surface内容到屏幕上。Server端接受这个命令并执行相应操作。
研究一个surface如何创建的关键路径如下:
1. frameworks/base/core/java/android/view/Surface.java -- Surface::Surface ()
2. frameworks/base/core/jni/android_view_Surface.cpp -- Surface_init ()。在这个函数中SurfaceComposerClient 对象被创建。
3. frameworks/base/libs/ui/SurfaceComposerClient.cpp -- SurfaceComposerClient::SurfaceComposerClient (). 这个函数非常重要,在这里建立了client和server之间的桥梁。通过函数_get_surface_manager()获得了一个指向server的IBinder 对象(具有ISurfaceComposer接口),之后通过这个IBinder就可以跨进程访问Server的功能。接着调用ISurfaceComposer::createConnection()创建并返回了一个ISurfaceFlingerClient的IBinder。
4. frameworks/base/libs/ui/SurfaceComposerClient.cpp -- SurfaceComposerClient::createSurface().这个函数中,利用前面获得的ISurfaceFlingerClient的IBinder,调用其createSurface接口。
5.frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp -- BClient::createSurface ()。BClient由ISurfaceFlingerClient派生而来。
6. frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp -- SurfaceFlinger:: createSurface()。这个函数为Surface创建一个对应的Layer。
上述关键路径中,1,2,3,4运行于client进程中,而5,6运行与server进程中。server作为一个service提供给client访问。
与图形相关的代码主要位于下列目录:
1、frameworks/base/graphics/java/android/graphics
2、frameworks/base/core/java/android/view
3、frameworks/base/core/java/android/widget
4、frameworks/base/opengl/
5、frameworks/base/libs/ui
6、frameworks/base/libs/surfaceflinger
7、frameworks/base/core/jni/android/graphics
8、frameworks/base/core/jni/android/opengl
9、frameworks/base/core/jni/android/android_view_*.cpp
10、external/skia
一、下列目录中的部分代码:
1、frameworks/base/graphics/java/android/graphics
2、frameworks/base/core/java/android/view
3、frameworks/base/core/java/android/widget
android.graphics, android.view和android.widget功能和其他类似的图形库如Qt/Gtk+差不多,分别提供基本的图形原语(如画点画线,设置图形上下文等),事件机制,以及开发图形用户界面的控件等。canvas 用于开发2D图形, Surface 代表一个可供图形系统绘制的surface。可在其上绘制2D活3D图形。
二. frameworks/base/opengl/
这个目录包含opengel的接口以及软件实现。在http://developer.android.com/guide/topics/graphics/opengl.html有详细介绍如何使用android.opengl开发3d graphics。
三.external/skia,台湾的Jserv先生有一篇比较好的介绍,感兴趣的读者可以参考他的博文(http: //blog.linux.org.tw/~jserv/archives/002095.html)。简而言之,skia与cairo功能相当,封装底 层的图形硬件,为上面的图形库提供最基础的操作图形硬件的原语。
四. frameworks/base/libs/ui 和 frameworks/base/libs/surfaceflinger
ISurface 定义了基础的Surface接口,供图形系统客户端 (应用)和server端(即surfaceflinger)交互。
BpSurface是ISurface的派生类,提供接口供server 调用客户端功能;
BnSurface是ISurface的另一个派生类,提供接口供客户端调用server功能。当 server 收到来自客户端 (通过BnSurace)的调用请求后,如registerBuffers, postBuffer等,BnSurface::onTransact被触发。
Surface (LayerBaseClient的私有类)是BnSurface的派生类。
SurfaceBuffer (SurfaceBuffer的私有类)是Surface的派生类。
ISurfaceComposer 定义了基础的接口,供客户端和server端交互。
BpSurfaceComposer是一个派生类,提供接口供server调用客户端功能;
BnSurfaceComposer是另一派生类,提供接口供客户端调用server功能。类 SurfaceFlinger 由BnSurfaceComposer派生而来。
SurfaceComposerClient直接供客户端使用,调用ISurface (BnSurface)和 ISurfaceComposer (BnSurfaceComposer)以及 ISurfaceFlingerClient 接口,与server交互。
BClient 派生自ISurfaceFlingerClient (BnSurfaceFlingerClient),调用server的createSurface,真正创建一个surface。每个surface对应一个layer.
egl_native_window_t 定义了一个本地window类 。这个类提供了对本地window的所有描述以及用于egl (opengl 与本地图形系统的接口)操作本地windwo的所有方法。
EGLNativeSurface是egl_native_window_t的一个派生类。
EGLDisplaySurface是EGLNativeSurface的派生类。 EGLDisplaySurface 是一个非常重要的类,在这个类里,真正打开framebuffer设备(/dev/graphics/fb0 或者/dev/fb0),并将这个设备封装成EGLDisplaySurface的形式供server使用。函数mapFrameBuffer打开framebuffer, 创建两个缓冲区,(一个是on screen front 缓冲区, 另一个back buffer, 可能位于offscreen framebuffer,也可能位于系统内存)。 函数swapBuffers将back buffer内容拷贝到front buffer中。
DisplayHardware 类中初始化了egl系统,并为本地窗口对象EGLDisplaySurface 创建了对应的EGLSurface 对象。surfaceflinger 使用DisplayHardware去和本地窗口打交道。
五、下列目录中的部分代码
7、frameworks/base/core/jni/android/graphics
8、frameworks/base/core/jni/android/opengl
9、frameworks/base/core/jni/android/android_view_*.cpp
这些目录下的代码在Java层的graphics 组件和native (c++)组件之间衔接,将java层的功能调用转换到对应的本地调用。
hardware/libhardware实现了HAL(Hardware Abstraction Layer)层,copybit device是其中一个模块。
Android中的图形系统采用Client/Server架构。Server (即SurfaceFlinger)主要由c++代码编写而成。Client端代码分为两部分,一部分是由Java提供的供应用使用的api,另一部分则是由c++写成的底层实现。下图概要介绍了android图形系统的架构以及使用到的主要组件。
Android图形系统中一个重要的概念和线索是surface。View及其子类(如TextView, Button)要画在surface上。每个surface创建一个Canvas对象 (但属性时常改变),用来管理view在surface上的绘图操作,如画点画线。每个canvas对象对应一个bitmap,存储画在surface上的内容。
每个Surface通常对应两个buffer,一个front buffer, 一个back buffer。其中,back buffer就是canvas绘图时对应的bitmap (研究android_view_Surface.cpp::lockCanvas)。因此,绘画总是在back buffer上,需要更新时,则将back buffer和front buffer互换。
The window is tied to a Surface and the ViewRoot asks the Surface for a
Canvas that is then used by the Views to draw onto. After View draw its data to canvas, ViewRoot
will call surface.unlockCanvasAndPost(canvas) to schedule surfaceFlinger::composeSurfaces() which do the actually display to
Except for SurfaceViews, different views within the same ViewRoot share the same surface.
Layer的概念:
每个surface又对应一个layer, SurfaceFlinger负责将各个layer的front buffer合成(composite)绘制到屏幕上。
A Layer is something that can be composited by SurfaceFlinger (should have been called LayerFlinger). There are several types of Layers if you look in the code, in particular the regular ones (Layer.cpp) , they are backed by a Surface, and the LayerBuffer (very badly chosen name) which don't have a backing store, but receive one from their client. . Note that the GGLSurface type, should have been called GGLBuffer
Multiple layers are just composited to the final buffer intheir Z order.
有几个对象与Surface概念紧密相关:
1. Java Surface (frameworks/base/core/java/android/view/Surface.java)。该对象被应用间接调用(通过SurfaceView, ViewRoot等), 应用需要创建surface,(并同时创建canvas), 将图形绘制到这个对象上并最终投递到屏幕上。
2. C++ Surface (frameworks/base/libs/ui/Surface.cpp。 这个对象被Java Surface通过Jni 调用,实现Java Surface 的功能
3. ISurface (以及其派生类BnSurface)。这个对象是应用和server之间的接口。C++ Surface创建这个ISurface (BnSurface)并发送命令,如更新surface内容到屏幕上。Server端接受这个命令并执行相应操作。
研究一个surface如何创建的关键路径如下:
1. frameworks/base/core/java/android/view/Surface.java -- Surface::Surface ()
2. frameworks/base/core/jni/android_view_Surface.cpp -- Surface_init ()。在这个函数中SurfaceComposerClient 对象被创建。
3. frameworks/base/libs/ui/SurfaceComposerClient.cpp -- SurfaceComposerClient::SurfaceComposerClient (). 这个函数非常重要,在这里建立了client和server之间的桥梁。通过函数_get_surface_manager()获得了一个指向server的IBinder 对象(具有ISurfaceComposer接口),之后通过这个IBinder就可以跨进程访问Server的功能。接着调用ISurfaceComposer::createConnection()创建并返回了一个ISurfaceFlingerClient的IBinder。
4. frameworks/base/libs/ui/SurfaceComposerClient.cpp -- SurfaceComposerClient::createSurface().这个函数中,利用前面获得的ISurfaceFlingerClient的IBinder,调用其createSurface接口。
5.frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp -- BClient::createSurface ()。BClient由ISurfaceFlingerClient派生而来。
6. frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp -- SurfaceFlinger:: createSurface()。这个函数为Surface创建一个对应的Layer。
上述关键路径中,1,2,3,4运行于client进程中,而5,6运行与server进程中。server作为一个service提供给client访问。
与图形相关的代码主要位于下列目录:
1、frameworks/base/graphics/java/android/graphics
2、frameworks/base/core/java/android/view
3、frameworks/base/core/java/android/widget
4、frameworks/base/opengl/
5、frameworks/base/libs/ui
6、frameworks/base/libs/surfaceflinger
7、frameworks/base/core/jni/android/graphics
8、frameworks/base/core/jni/android/opengl
9、frameworks/base/core/jni/android/android_view_*.cpp
10、external/skia
一、下列目录中的部分代码:
1、frameworks/base/graphics/java/android/graphics
2、frameworks/base/core/java/android/view
3、frameworks/base/core/java/android/widget
android.graphics, android.view和android.widget功能和其他类似的图形库如Qt/Gtk+差不多,分别提供基本的图形原语(如画点画线,设置图形上下文等),事件机制,以及开发图形用户界面的控件等。canvas 用于开发2D图形, Surface 代表一个可供图形系统绘制的surface。可在其上绘制2D活3D图形。
二. frameworks/base/opengl/
这个目录包含opengel的接口以及软件实现。在http://developer.android.com/guide/topics/graphics/opengl.html有详细介绍如何使用android.opengl开发3d graphics。
三.external/skia,台湾的Jserv先生有一篇比较好的介绍,感兴趣的读者可以参考他的博文(http: //blog.linux.org.tw/~jserv/archives/002095.html)。简而言之,skia与cairo功能相当,封装底 层的图形硬件,为上面的图形库提供最基础的操作图形硬件的原语。
四. frameworks/base/libs/ui 和 frameworks/base/libs/surfaceflinger
ISurface 定义了基础的Surface接口,供图形系统客户端 (应用)和server端(即surfaceflinger)交互。
BpSurface是ISurface的派生类,提供接口供server 调用客户端功能;
BnSurface是ISurface的另一个派生类,提供接口供客户端调用server功能。当 server 收到来自客户端 (通过BnSurace)的调用请求后,如registerBuffers, postBuffer等,BnSurface::onTransact被触发。
Surface (LayerBaseClient的私有类)是BnSurface的派生类。
SurfaceBuffer (SurfaceBuffer的私有类)是Surface的派生类。
ISurfaceComposer 定义了基础的接口,供客户端和server端交互。
BpSurfaceComposer是一个派生类,提供接口供server调用客户端功能;
BnSurfaceComposer是另一派生类,提供接口供客户端调用server功能。类 SurfaceFlinger 由BnSurfaceComposer派生而来。
SurfaceComposerClient直接供客户端使用,调用ISurface (BnSurface)和 ISurfaceComposer (BnSurfaceComposer)以及 ISurfaceFlingerClient 接口,与server交互。
BClient 派生自ISurfaceFlingerClient (BnSurfaceFlingerClient),调用server的createSurface,真正创建一个surface。每个surface对应一个layer.
egl_native_window_t 定义了一个本地window类 。这个类提供了对本地window的所有描述以及用于egl (opengl 与本地图形系统的接口)操作本地windwo的所有方法。
EGLNativeSurface是egl_native_window_t的一个派生类。
EGLDisplaySurface是EGLNativeSurface的派生类。 EGLDisplaySurface 是一个非常重要的类,在这个类里,真正打开framebuffer设备(/dev/graphics/fb0 或者/dev/fb0),并将这个设备封装成EGLDisplaySurface的形式供server使用。函数mapFrameBuffer打开framebuffer, 创建两个缓冲区,(一个是on screen front 缓冲区, 另一个back buffer, 可能位于offscreen framebuffer,也可能位于系统内存)。 函数swapBuffers将back buffer内容拷贝到front buffer中。
DisplayHardware 类中初始化了egl系统,并为本地窗口对象EGLDisplaySurface 创建了对应的EGLSurface 对象。surfaceflinger 使用DisplayHardware去和本地窗口打交道。
五、下列目录中的部分代码
7、frameworks/base/core/jni/android/graphics
8、frameworks/base/core/jni/android/opengl
9、frameworks/base/core/jni/android/android_view_*.cpp
这些目录下的代码在Java层的graphics 组件和native (c++)组件之间衔接,将java层的功能调用转换到对应的本地调用。
hardware/libhardware实现了HAL(Hardware Abstraction Layer)层,copybit device是其中一个模块。
訂閱:
文章 (Atom)